Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ RUN --mount=type=cache,target=/root/.npm npm --prefix chatbot ci --include=dev -
COPY chatbot/ chatbot/
COPY web/app/ web/app/
RUN npm --prefix chatbot run build && test -f web/native-chat/index.html
FROM --platform=$BUILDPLATFORM golang:1.26.10-bookworm AS build
FROM --platform=$BUILDPLATFORM golang:1.26.11-bookworm AS build
ARG TARGETOS
ARG TARGETARCH
WORKDIR /src
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: run test test-mysql clean-mysql build build-chatbot build-gate-mcp coverage coverage-go coverage-chatbot coverage-web coverage-e2e

GOCACHE ?= /tmp/agentflow-gocache
# Use the local toolchain; go.mod requires go >= 1.26.10.
# Use the local toolchain; go.mod requires go >= 1.26.11.

run:
GOCACHE=$(GOCACHE) go run ./cmd/agentflow
Expand Down
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ New accounts join the **LoopForge demo project**, which includes an SOP made onl
- **Sandboxes.** In the default Compose installation, SOP runs and conversation workspaces both use Docker sandbox containers started through the host Docker socket. Default sandboxes reuse the installed runtime image, so nothing extra is built after installation; custom Dockerfiles still build their own images. Docker socket access grants control of the host daemon, so this setup is for trusted teams, not untrusted multi-tenant isolation. See [deployment boundaries](docs/deployment.md#accounts). Re-running the installer keeps your data.
- **Accounts and access.** New installations listen on all interfaces (existing bind settings are kept) and are designed for a trusted team: signed-in users can read project data across the instance, and teammates can sign up from the login page (`AGENTFLOW_ALLOW_SIGNUP=false` in `.env` turns that off). Read the [account and access model](docs/deployment.md#accounts) before exposing it beyond your team.
- **Remote access, HTTPS, separate workers.** See [Deployment](docs/deployment.md).
- **Hacking on LoopForge itself?** `bash scripts/dev.sh` runs it natively (Go 1.26.10+).
- **Hacking on LoopForge itself?** `bash scripts/dev.sh` runs it natively (Go 1.26.11+).

</details>

Expand Down Expand Up @@ -193,6 +193,20 @@ See the [local guide](docs/local/usage.md) for each host's entry point and [edit
| Workflows | Chat with Main Bot + custom SOPs on a visual canvas | Built-in Classic / Portable workflows |
| Evidence | Shared run details, approvals and metrics in the web workspace | Artifacts under `artifacts/{task_slug}/` + optional local dashboard |

## LoopForge for VS Code

The standalone desktop [VS Code extension](vscode-extension/) connects to a LoopForge platform server, starts a workflow with project and selected-code context, and shows run status, logs, approvals, artifacts, files and diffs. It targets VS Code 1.85+ and the platform REST API.

Build and install a local VSIX:

```bash
cd vscode-extension
npx --yes @vscode/vsce package --no-dependencies
code --install-extension loopforge-0.1.4.vsix
```

See the [extension guide](vscode-extension/README.md) for configuration, API token storage, capability boundaries, upgrades and uninstalling.

## FAQ

**Do I need an API key to try it?**
Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ cd LoopForge
- **沙箱。** 默认 Compose 安装中,SOP 运行和对话工作区都使用 Docker 沙箱容器,由平台通过宿主机 Docker socket 启动;默认沙箱复用已安装的运行镜像,安装后无需再构建;自定义 Dockerfile 仍单独构建。Docker socket 赋予平台控制宿主机 Docker 的权限,因此只适用于可信团队,不构成不可信多租户隔离边界;详见[部署边界](docs/deployment.md#accounts)。重复执行安装脚本会保留已有数据。
- **账号与访问。** 新安装默认监听所有网卡(已有安装保留原配置),面向可信团队:已登录用户可以读取实例内各项目的数据,团队成员可在登录页自助注册(在 `.env` 中设置 `AGENTFLOW_ALLOW_SIGNUP=false` 可关闭)。对团队以外开放前,请先阅读[账号与访问边界](docs/deployment.md#accounts)。
- **远程访问、HTTPS、独立 Worker。** 见[部署指南](docs/deployment.md)。
- **参与 LoopForge 本身的开发?** 用 `bash scripts/dev.sh` 原生运行(需要 Go 1.26.10+)。
- **参与 LoopForge 本身的开发?** 用 `bash scripts/dev.sh` 原生运行(需要 Go 1.26.11+)。

</details>

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module agentflow

go 1.26.10
go 1.26.11

require (
github.com/creack/pty v1.1.24
Expand Down
2 changes: 2 additions & 0 deletions vscode-extension/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.vsix
node_modules/
6 changes: 6 additions & 0 deletions vscode-extension/.vscodeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
test
lib/*.test.js
*.map
.gitignore
acceptance
52 changes: 52 additions & 0 deletions vscode-extension/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
Tencent is pleased to support the open source community by making LoopForge available.

Copyright (C) 2026 Tencent. All rights reserved.

LoopForge is licensed under MIT, except for the third-party components listed below, which remain licensed under their respective original terms. LoopForge does not impose any additional restrictions beyond those specified in the original licenses of these third-party components. Users are required to comply with all applicable terms and conditions of the original licenses.

In case you believe there have been errors in the attribution below, you may submit the concerns to us for review and correction.

Terms of the MIT License:
--------------------------------------------------------------------
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Dependencies and Licenses:

The below software in this distribution may have been modified by Tencent ("Tencent Modifications"). All Tencent Modifications are Copyright (C) Tencent.


Open Source Software Licensed under the MIT:
--------------------------------------------------------------------
1. superpowers
Copyright (c) 2025 Jesse Vincent
Please note this software has been modified by Tencent in this distribution.
You may find the original code here: https://github.com/obra/superpowers
Terms of the MIT:
--------------------------------------------------------------------
MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

==================================================
End of the Attribution Notice of this project.
61 changes: 61 additions & 0 deletions vscode-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# LoopForge for VS Code

This directory contains the first standalone desktop VS Code extension for LoopForge. It connects to an existing LoopForge HTTP server and reuses the platform Runs API; it does not modify the LoopForge server or install a second workflow engine in the editor.

## Supported scope

- VS Code 1.85 or newer on desktop.
- LoopForge platform API with `POST /api/runs`, the Runs detail/log/approval/artifact endpoints, and the workspace diff endpoint.
- Platform workflows (SOPs). The extension starts a run through the server; model providers and execution environments remain configured by LoopForge.
- A server URL and, when authentication is enabled, a LoopForge Personal API Token. The token is stored in VS Code SecretStorage and is never written to workspace settings.

The extension uses the active file's workspace folder (or the first folder if no file is active). `LoopForge: Start Workflow` asks for a task description and appends the project path, active file path and up to 4,000 characters of selected text as input. This sends the selected content to the configured server. Paths are descriptive: the extension does not upload or mount the local project. Configure a repository on the platform if the workflow needs source files. The server remains the source of truth for project access, workflow permissions, execution, and secrets.

## Install from a VSIX

From the repository root:

```bash
cd vscode-extension
npx --yes @vscode/vsce package --no-dependencies
code --install-extension loopforge-0.1.4.vsix
```

The package can later be published to an extension marketplace with the publisher's normal VSCE credentials. No marketplace account or credential is required to build or install the VSIX locally.

## Configure

Use the command palette:

1. Start or obtain access to a LoopForge platform server. Set `loopforge.serverUrl` in user or remote settings to its base URL (for example `http://127.0.0.1:8090` when the server runs on the extension host). HTTPS is required for non-loopback hosts; HTTP is accepted only for `localhost`, IPv4 addresses in `127.0.0.0/8`, and `::1`. Workspace settings cannot change the server address, to prevent a project from redirecting the stored token.
2. Create a Personal API Token in the platform's account settings if authentication is enabled. `LoopForge: Configure API Token` stores or clears it in SecretStorage. A personal token is not a model-provider key.
3. `LoopForge: Select Project` and `LoopForge: Select Workflow` discover choices from the configured server, or set `loopforge.projectId` and `loopforge.workflowId` in workspace settings. A project owner or authenticated user is required for manual runs.

When switching projects with `LoopForge: Select Project`, the extension clears the workspace's workflow selection so the next run asks for a workflow in the new project. If you edit these settings manually, choose a workflow that belongs to the selected project or is shared with it.

The extension only writes the two explicitly selected LoopForge workspace settings. It does not change unrelated VS Code settings. Uninstalling removes the extension files and leaves the workspace settings and SecretStorage entry under the user's control; clear the token with `LoopForge: Configure API Token` when desired.

## Commands and run view

The LoopForge activity bar view lists recent runs, their status and active stage, waiting human approvals, and artifact metadata. The commands provide:

- Start a workflow with current project/file/selection context.
- Refresh and inspect status, stage output, and logs.
- Approve or send back a stage that is waiting for human input. The client includes the node attempt expectation so stale approval cards are rejected by the server.
- Open an artifact in a VS Code editor.
- Open a changed file from the run workspace in a VS Code editor.
- Open the current workspace change as a VS Code diff. If there are multiple changes, the extension asks which path to compare.

Connection, authentication, timeout, HTTP, and server validation errors are shown in the Runs view or as VS Code error messages. Run polling is bounded by `loopforge.pollInterval` and is disabled on deactivation. To upgrade, install the new VSIX through VS Code; to uninstall, use the Extensions view. Existing LoopForge settings may remain after uninstall; remove them manually if desired.

## Capability boundary

The first release is a platform-connected adapter. It does not claim to execute a workflow locally, provide a model/provider setup wizard, or replace the LoopForge Web workspace. Those remain platform responsibilities and are reported by the same API error messages used by the Web client.

Changed files and diffs are available only while the platform retains the run workspace. In the current platform, a successful or cancelled ordinary workflow can have its workspace reclaimed immediately, so open its changes before completing the workflow when they are needed. After reclamation the extension reports the platform's reason; artifacts stored by the platform remain separately accessible. Workspace snapshots and restoration depend on the platform and are not provided by this extension.

If a connection fails, check that the platform is running and that `loopforge.serverUrl` is reachable from the machine hosting the extension. In a Remote SSH session, `127.0.0.1` refers to the remote extension host, not the desktop running the VS Code window.

## Tests

Run `npm test` in this directory for extension interaction and client tests. To exercise the client against the actual platform HTTP handlers and workflow engine using an isolated in-memory test database, build the repository's web assets as described in the [contributing guide](../CONTRIBUTING.md), then run `go test -v ./vscode-extension/acceptance` from the repository root. The acceptance workflow is a single human approval step and does not need Docker, organization credentials, or a model provider.
36 changes: 36 additions & 0 deletions vscode-extension/acceptance/platform-client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict';
const assert = require('node:assert/strict');
const { LoopForgeClient } = require('../lib/client');
(async () => {
const api = new LoopForgeClient({ baseUrl: process.argv[2] });
const input = 'VS Code acceptance\nfile: src/main.js\nselection:\nline one\nline two';
const run = await api.createRun({ workflowId: 'vscode-acceptance', projectId: 'platform', input });
assert.ok(run.id);
let detail;
for (let i = 0; i < 100; i++) {
detail = await api.getRun(run.id);
if (detail.nodes?.gate?.status === 'waiting_approval') break;
await new Promise(resolve => setTimeout(resolve, 100));
}
assert.equal(detail.nodes.gate.status, 'waiting_approval');
assert.equal(detail.input, input);
const gate = detail.nodes.gate;
await assert.rejects(
() => api.approve(run.id, { nodeId: 'gate', expected: { status: gate.status, attempt: gate.attempt + 1, reworkCount: gate.reworkCount } }),
error => error.status === 400 && /节点状态已变化/.test(error.message)
);
assert.equal((await api.getRun(run.id)).nodes.gate.status, 'waiting_approval');
await api.approve(run.id, { nodeId: 'gate', context: 'Reviewed', expected: { status: gate.status, attempt: gate.attempt, reworkCount: gate.reworkCount } });
for (let i = 0; i < 100; i++) {
detail = await api.getRun(run.id);
if (detail.status === 'succeeded') break;
await new Promise(resolve => setTimeout(resolve, 100));
}
assert.equal(detail.status, 'succeeded');
const artifact = detail.artifacts.find(item => item.name === 'decision');
assert.ok(artifact?.id, 'approval decision artifact missing');
const content = await api.getArtifact(run.id, artifact.id);
assert.ok(content.includes('Reviewed'));
assert.ok(Array.isArray((await api.getLogs(run.id)).logs));
console.log('Real platform: created run, preserved context, approved, inspected result and retrieved artifact.');
})().catch(error => { console.error(error); process.exitCode = 1; });
41 changes: 41 additions & 0 deletions vscode-extension/acceptance/platform_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package acceptance

import (
"os"
"os/exec"
"path/filepath"
"testing"

"agentflow/internal/domain"
"agentflow/internal/engine"
"agentflow/internal/httpapi"
"agentflow/internal/repo"
"agentflow/internal/runtime"
"agentflow/internal/tracker"
"github.com/gin-gonic/gin"
"net/http/httptest"
)

func TestExtensionClientAgainstRealPlatform(t *testing.T) {
t.Setenv("AGENTFLOW_AUTH_REQUIRED", "false")
gin.SetMode(gin.ReleaseMode)
store, err := repo.OpenTest()
if err != nil {
t.Fatal(err)
}
defer store.Close()
wf := domain.WorkflowDefinition{ID: "vscode-acceptance", Name: "VS Code acceptance", SandboxProfileID: "local", Nodes: []domain.WorkflowNode{{ID: "gate", Name: "Approval", Type: "approval", MaxAttempts: 1}}}
if err := store.PutWorkflow(wf); err != nil {
t.Fatal(err)
}
engine := engine.New(store, runtime.NewManager(filepath.Join(t.TempDir(), "workspaces")))
server := httptest.NewServer(httpapi.New(store, engine, tracker.NewService(), "", ""))
defer server.Close()
cmd := exec.Command("node", "platform-client.js", server.URL)
cmd.Env = append(os.Environ(), "NO_PROXY=127.0.0.1,localhost", "no_proxy=127.0.0.1,localhost")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("extension client: %v\n%s", err, out)
}
t.Log(string(out))
}
Loading
Loading