@agent-spaces/server 0.3.65 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/agent-runtime.js +8 -0
- package/dist/adapters/codex-function-tool-bridge.js +152 -0
- package/dist/adapters/codex-runtime.js +23 -4
- package/dist/adapters/git.js +25 -3
- package/dist/adapters/hermes-runtime.js +813 -0
- package/dist/adapters/langchain-runtime.js +384 -21
- package/dist/adapters/oh-my-pi-runtime.js +858 -0
- package/dist/adapters/open-agent-sdk-runtime.js +202 -5
- package/dist/adapters/open-agent-sdk-runtime.test.js +35 -0
- package/dist/agents/agent-message-parts.js +52 -2
- package/dist/agents/issue-task-controller.js +71 -2
- package/dist/agents/pull-request-agent.js +115 -0
- package/dist/agents/scheduler-agent.js +1 -1
- package/dist/agents/title-generator-agent.js +120 -0
- package/dist/app.js +61 -4
- package/dist/middleware/auth.js +1 -1
- package/dist/package.json +2 -1
- package/dist/routes/agent-sse.js +70 -6
- package/dist/routes/channel.js +23 -2
- package/dist/routes/chat-run.js +191 -0
- package/dist/routes/chat.js +142 -0
- package/dist/routes/command.js +16 -0
- package/dist/routes/data.js +189 -0
- package/dist/routes/git.js +10 -1
- package/dist/routes/import.js +199 -0
- package/dist/routes/issue.js +17 -5
- package/dist/routes/notification.js +10 -0
- package/dist/routes/plugin.js +69 -0
- package/dist/routes/version.js +95 -0
- package/dist/routes/workflow-hook.js +71 -0
- package/dist/routes/workflow.js +282 -7
- package/dist/routes/workspace.js +13 -4
- package/dist/routes/worktree.js +93 -0
- package/dist/services/agent.js +123 -36
- package/dist/services/ai-text.js +185 -0
- package/dist/services/builtin-tools/index.js +1 -0
- package/dist/services/builtin-tools/workflow-editor-tools.js +509 -0
- package/dist/services/builtin-tools/workflow-exec-tools.js +320 -0
- package/dist/services/chat.js +134 -0
- package/dist/services/command-process-manager.js +16 -0
- package/dist/services/execution-manager.js +1346 -0
- package/dist/services/generated-title.js +59 -0
- package/dist/services/gitignore.js +22 -18
- package/dist/services/interaction-manager.js +114 -0
- package/dist/services/issue-retry.js +25 -0
- package/dist/services/notification-center.js +9 -0
- package/dist/services/output-style.js +8 -1
- package/dist/services/plugin.js +257 -0
- package/dist/services/prompt-template.js +8 -1
- package/dist/services/pty.js +20 -0
- package/dist/services/search.js +16 -6
- package/dist/services/skill.js +2 -0
- package/dist/services/version.js +69 -0
- package/dist/services/workflow-command-runner.js +24 -0
- package/dist/services/workflow-trigger-service.js +137 -0
- package/dist/services/workflow.js +219 -39
- package/dist/services/workspace.js +23 -1
- package/dist/services/worktree.js +207 -0
- package/dist/storage/agent-store.js +8 -0
- package/dist/storage/chat-store.js +151 -0
- package/dist/storage/database-store.js +6 -0
- package/dist/storage/json-store.js +2 -1
- package/dist/storage/kanban-store.js +6 -0
- package/dist/storage/workflow-store.js +386 -22
- package/dist/storage/worktree-store.js +33 -0
- package/dist/web/404.html +1 -1
- package/dist/web/__next.__PAGE__.txt +4 -4
- package/dist/web/__next._full.txt +21 -21
- package/dist/web/__next._head.txt +4 -4
- package/dist/web/__next._index.txt +13 -13
- package/dist/web/__next._tree.txt +2 -2
- package/dist/web/_next/static/chunks/{08x85faoz58i7.js → 0-92u-tiuy40a.js} +4 -4
- package/dist/web/_next/static/chunks/{0db14450oqzhg.js → 0-yizd8osmas2.js} +1 -1
- package/dist/web/_next/static/chunks/0.ln~3mnv8.69.js +1 -0
- package/dist/web/_next/static/chunks/{11cchuwoupmbf.js → 01y3e9pemva7b.js} +10 -10
- package/dist/web/_next/static/chunks/02l~tmzrgny.~.js +1 -0
- package/dist/web/_next/static/chunks/03f1bwuynjdmk.js +1 -0
- package/dist/web/_next/static/chunks/04cb4kc9r2pd1.js +1 -0
- package/dist/web/_next/static/chunks/04de6ha5_e3pp.js +1 -0
- package/dist/web/_next/static/chunks/09he0p79ov1rn.js +1 -0
- package/dist/web/_next/static/chunks/09vpocs4zuc8h.js +1 -0
- package/dist/web/_next/static/chunks/0_o2exgr0e_nh.js +1 -0
- package/dist/web/_next/static/chunks/{0xbaakj0dfc0..js → 0_y9nskc-xt2k.js} +1 -1
- package/dist/web/_next/static/chunks/0clnj-1fi6u8j.js +3 -0
- package/dist/web/_next/static/chunks/0gv40by0zzxs_.js +1 -0
- package/dist/web/_next/static/chunks/0iusr8y88.kjg.js +1 -0
- package/dist/web/_next/static/chunks/{0-a.-hl3wv99k.js → 0j-8418fxvkd1.js} +1 -1
- package/dist/web/_next/static/chunks/0j.wxxyoclma5.js +1 -0
- package/dist/web/_next/static/chunks/{0.6b64sy0g5.3.js → 0jq.16sozqik..js} +1 -1
- package/dist/web/_next/static/chunks/0jw8xdk_fpnp0.css +1 -0
- package/dist/web/_next/static/chunks/0l1lkd-wcotma.js +1 -0
- package/dist/web/_next/static/chunks/{0u6h-hqc_i52e.js → 0ncxf_zr4n839.js} +1 -1
- package/dist/web/_next/static/chunks/0ndo7um~v7vco.js +1 -0
- package/dist/web/_next/static/chunks/0ngk.~kan8wq_.js +1 -0
- package/dist/web/_next/static/chunks/0ppr271hz0xoq.js +1 -0
- package/dist/web/_next/static/chunks/0rt9bofnn6qvn.js +1 -0
- package/dist/web/_next/static/chunks/0t64.9jd00hio.js +3 -0
- package/dist/web/_next/static/chunks/0taui9--5n6-5.js +1 -0
- package/dist/web/_next/static/chunks/0ty39169lh~z3.js +1 -0
- package/dist/web/_next/static/chunks/0v8nof~waedlu.js +1 -0
- package/dist/web/_next/static/chunks/{0-pi.67w.ymsr.js → 0vcfoagnpf.aw.js} +1 -1
- package/dist/web/_next/static/chunks/{0vis~lx0nxgn-.js → 0wwwq.gyyz0vg.js} +3 -3
- package/dist/web/_next/static/chunks/0x5lak8yz7pm7.js +1 -0
- package/dist/web/_next/static/chunks/0xon_.4-o0_zq.js +7 -0
- package/dist/web/_next/static/chunks/0zjnrbt7inime.js +1 -0
- package/dist/web/_next/static/chunks/0zwebpitvpuv1.js +1 -0
- package/dist/web/_next/static/chunks/0~02o4g-o6n~m.js +1 -0
- package/dist/web/_next/static/chunks/{0w7.tb29958zj.js → 0~fjezp.k4qk3.js} +1 -1
- package/dist/web/_next/static/chunks/0~sh93re1-_rp.js +1 -0
- package/dist/web/_next/static/chunks/10_niiq0k6o-p.js +5 -0
- package/dist/web/_next/static/chunks/12tjr0_2ccrtq.js +2 -0
- package/dist/web/_next/static/chunks/12x5.go_x9mfk.js +1 -0
- package/dist/web/_next/static/chunks/{0l2w0qz1ea7ql.js → 12~5dk9i9d16t.js} +2 -2
- package/dist/web/_next/static/chunks/13iye4rv5p31b.js +1 -0
- package/dist/web/_next/static/chunks/{01~quun6sefgl.js → 13~y-b.b9rrw4.js} +1 -1
- package/dist/web/_next/static/chunks/151wzhb5q0lo5.js +1 -0
- package/dist/web/_not-found/__next._full.txt +19 -19
- package/dist/web/_not-found/__next._head.txt +4 -4
- package/dist/web/_not-found/__next._index.txt +13 -13
- package/dist/web/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/web/_not-found/__next._not-found.txt +3 -3
- package/dist/web/_not-found/__next._tree.txt +2 -2
- package/dist/web/_not-found.html +1 -1
- package/dist/web/_not-found.txt +19 -19
- package/dist/web/index.html +1 -1
- package/dist/web/index.txt +21 -21
- package/dist/web/login/__next._full.txt +21 -21
- package/dist/web/login/__next._head.txt +4 -4
- package/dist/web/login/__next._index.txt +13 -13
- package/dist/web/login/__next._tree.txt +2 -2
- package/dist/web/login/__next.login.__PAGE__.txt +4 -4
- package/dist/web/login/__next.login.txt +3 -3
- package/dist/web/login.html +1 -1
- package/dist/web/login.txt +21 -21
- package/dist/web/settings/__next._full.txt +23 -23
- package/dist/web/settings/__next._head.txt +4 -4
- package/dist/web/settings/__next._index.txt +13 -13
- package/dist/web/settings/__next._tree.txt +2 -2
- package/dist/web/settings/__next.settings.__PAGE__.txt +4 -4
- package/dist/web/settings/__next.settings.txt +5 -5
- package/dist/web/settings/agents/__next._full.txt +23 -23
- package/dist/web/settings/agents/__next._head.txt +4 -4
- package/dist/web/settings/agents/__next._index.txt +13 -13
- package/dist/web/settings/agents/__next._tree.txt +2 -2
- package/dist/web/settings/agents/__next.settings.agents.__PAGE__.txt +4 -4
- package/dist/web/settings/agents/__next.settings.agents.txt +3 -3
- package/dist/web/settings/agents/__next.settings.txt +5 -5
- package/dist/web/settings/agents.html +1 -1
- package/dist/web/settings/agents.txt +23 -23
- package/dist/web/settings/mcps/__next._full.txt +23 -23
- package/dist/web/settings/mcps/__next._head.txt +4 -4
- package/dist/web/settings/mcps/__next._index.txt +13 -13
- package/dist/web/settings/mcps/__next._tree.txt +2 -2
- package/dist/web/settings/mcps/__next.settings.mcps.__PAGE__.txt +4 -4
- package/dist/web/settings/mcps/__next.settings.mcps.txt +3 -3
- package/dist/web/settings/mcps/__next.settings.txt +5 -5
- package/dist/web/settings/mcps.html +1 -1
- package/dist/web/settings/mcps.txt +23 -23
- package/dist/web/settings/models/__next._full.txt +23 -23
- package/dist/web/settings/models/__next._head.txt +4 -4
- package/dist/web/settings/models/__next._index.txt +13 -13
- package/dist/web/settings/models/__next._tree.txt +2 -2
- package/dist/web/settings/models/__next.settings.models.__PAGE__.txt +4 -4
- package/dist/web/settings/models/__next.settings.models.txt +3 -3
- package/dist/web/settings/models/__next.settings.txt +5 -5
- package/dist/web/settings/models.html +1 -1
- package/dist/web/settings/models.txt +23 -23
- package/dist/web/settings/output-styles/__next._full.txt +23 -23
- package/dist/web/settings/output-styles/__next._head.txt +4 -4
- package/dist/web/settings/output-styles/__next._index.txt +13 -13
- package/dist/web/settings/output-styles/__next._tree.txt +2 -2
- package/dist/web/settings/output-styles/__next.settings.output-styles.__PAGE__.txt +4 -4
- package/dist/web/settings/output-styles/__next.settings.output-styles.txt +3 -3
- package/dist/web/settings/output-styles/__next.settings.txt +5 -5
- package/dist/web/settings/output-styles.html +1 -1
- package/dist/web/settings/output-styles.txt +23 -23
- package/dist/web/settings/prompts/__next._full.txt +23 -23
- package/dist/web/settings/prompts/__next._head.txt +4 -4
- package/dist/web/settings/prompts/__next._index.txt +13 -13
- package/dist/web/settings/prompts/__next._tree.txt +2 -2
- package/dist/web/settings/prompts/__next.settings.prompts.__PAGE__.txt +4 -4
- package/dist/web/settings/prompts/__next.settings.prompts.txt +3 -3
- package/dist/web/settings/prompts/__next.settings.txt +5 -5
- package/dist/web/settings/prompts.html +1 -1
- package/dist/web/settings/prompts.txt +23 -23
- package/dist/web/settings/providers/__next._full.txt +23 -23
- package/dist/web/settings/providers/__next._head.txt +4 -4
- package/dist/web/settings/providers/__next._index.txt +13 -13
- package/dist/web/settings/providers/__next._tree.txt +2 -2
- package/dist/web/settings/providers/__next.settings.providers.__PAGE__.txt +4 -4
- package/dist/web/settings/providers/__next.settings.providers.txt +3 -3
- package/dist/web/settings/providers/__next.settings.txt +5 -5
- package/dist/web/settings/providers.html +1 -1
- package/dist/web/settings/providers.txt +23 -23
- package/dist/web/settings/skills/__next._full.txt +23 -23
- package/dist/web/settings/skills/__next._head.txt +4 -4
- package/dist/web/settings/skills/__next._index.txt +13 -13
- package/dist/web/settings/skills/__next._tree.txt +2 -2
- package/dist/web/settings/skills/__next.settings.skills.__PAGE__.txt +4 -4
- package/dist/web/settings/skills/__next.settings.skills.txt +3 -3
- package/dist/web/settings/skills/__next.settings.txt +5 -5
- package/dist/web/settings/skills.html +1 -1
- package/dist/web/settings/skills.txt +23 -23
- package/dist/web/settings/tools/__next._full.txt +23 -23
- package/dist/web/settings/tools/__next._head.txt +4 -4
- package/dist/web/settings/tools/__next._index.txt +13 -13
- package/dist/web/settings/tools/__next._tree.txt +2 -2
- package/dist/web/settings/tools/__next.settings.tools.__PAGE__.txt +4 -4
- package/dist/web/settings/tools/__next.settings.tools.txt +3 -3
- package/dist/web/settings/tools/__next.settings.txt +5 -5
- package/dist/web/settings/tools.html +1 -1
- package/dist/web/settings/tools.txt +23 -23
- package/dist/web/settings.html +1 -1
- package/dist/web/settings.txt +23 -23
- package/dist/web/workflows/__next._full.txt +22 -22
- package/dist/web/workflows/__next._head.txt +4 -4
- package/dist/web/workflows/__next._index.txt +13 -13
- package/dist/web/workflows/__next._tree.txt +2 -2
- package/dist/web/workflows/__next.workflows.__PAGE__.txt +4 -4
- package/dist/web/workflows/__next.workflows.txt +3 -3
- package/dist/web/workflows.html +1 -1
- package/dist/web/workflows.txt +22 -22
- package/dist/web/workspace/_/__next._full.txt +20 -20
- package/dist/web/workspace/_/__next._head.txt +4 -4
- package/dist/web/workspace/_/__next._index.txt +13 -13
- package/dist/web/workspace/_/__next._tree.txt +2 -2
- package/dist/web/workspace/_/__next.workspace.$d$id.__PAGE__.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.$d$id.txt +3 -3
- package/dist/web/workspace/_/__next.workspace.txt +3 -3
- package/dist/web/workspace/_.html +1 -1
- package/dist/web/workspace/_.txt +20 -20
- package/dist/web/workspaces/__next._full.txt +21 -21
- package/dist/web/workspaces/__next._head.txt +4 -4
- package/dist/web/workspaces/__next._index.txt +13 -13
- package/dist/web/workspaces/__next._tree.txt +2 -2
- package/dist/web/workspaces/__next.workspaces.__PAGE__.txt +4 -4
- package/dist/web/workspaces/__next.workspaces.txt +3 -3
- package/dist/web/workspaces.html +1 -1
- package/dist/web/workspaces.txt +21 -21
- package/dist/ws/agent-prompt.js +36 -3
- package/dist/ws/agent-runner.js +30 -18
- package/dist/ws/chat-handler.js +89 -0
- package/dist/ws/connection-manager.js +49 -2
- package/dist/ws/execution-channels.js +88 -0
- package/dist/ws/handler.js +32 -5
- package/dist/ws/message-parts.js +130 -12
- package/dist/ws/terminal-handler.js +26 -0
- package/package.json +13 -1
- package/public/avatars/user.jpg +0 -0
- package/dist/web/_next/static/chunks/0-v_p6j5u3_9l.js +0 -1
- package/dist/web/_next/static/chunks/0.-x29t-8gk0r.js +0 -1
- package/dist/web/_next/static/chunks/0.l5e8~r7_0~p.js +0 -1
- package/dist/web/_next/static/chunks/0.n~yfwf4~6w-.js +0 -1
- package/dist/web/_next/static/chunks/00-syqzi-6zxr.js +0 -1
- package/dist/web/_next/static/chunks/02j4sr9psucf-.js +0 -1
- package/dist/web/_next/static/chunks/06si8l0doqe8p.js +0 -1
- package/dist/web/_next/static/chunks/08kfx8on9oty~.js +0 -1
- package/dist/web/_next/static/chunks/08ugbvzr20drp.js +0 -2
- package/dist/web/_next/static/chunks/0_cqojbge48kq.js +0 -5
- package/dist/web/_next/static/chunks/0d6~~lv0-6kex.js +0 -3
- package/dist/web/_next/static/chunks/0gdwop9cnpmtu.js +0 -1
- package/dist/web/_next/static/chunks/0ghx3j_.-gdyd.js +0 -1
- package/dist/web/_next/static/chunks/0kbvoxla7f751.js +0 -1
- package/dist/web/_next/static/chunks/0paaat8y96ayc.js +0 -7
- package/dist/web/_next/static/chunks/0pq318f8xgafg.js +0 -1
- package/dist/web/_next/static/chunks/0t6s8of0qr6nc.js +0 -1
- package/dist/web/_next/static/chunks/0xt-8wk21gs7g.js +0 -1
- package/dist/web/_next/static/chunks/0yd.m1afqg.2t.js +0 -3
- package/dist/web/_next/static/chunks/0yhbr8hl09b-5.js +0 -1
- package/dist/web/_next/static/chunks/0z~vqzbm_q371.js +0 -1
- package/dist/web/_next/static/chunks/0~~_ltu6dx_ch.js +0 -1
- package/dist/web/_next/static/chunks/12oxcgyhpaxw~.js +0 -1
- package/dist/web/_next/static/chunks/1452eibz62gs6.css +0 -1
- package/dist/web/_next/static/chunks/16zlreiems5cn.js +0 -1
- package/dist/web/_next/static/chunks/18awqjk9-o5m0.js +0 -1
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_buildManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_clientMiddlewareManifest.js +0 -0
- /package/dist/web/_next/static/{x4-CsKe6qUQyFDWVtfvUg → rGXyAK8rgod1NjF3bLZAY}/_ssgManifest.js +0 -0
|
@@ -1,40 +1,404 @@
|
|
|
1
1
|
// packages/server/src/storage/workflow-store.ts
|
|
2
|
-
//
|
|
3
|
-
|
|
2
|
+
// Per-workflow directory storage: supports versions, execution logs, plugin configs.
|
|
3
|
+
// Legacy flat-file workflows are auto-migrated on first access.
|
|
4
|
+
import { ensureDir, readJsonFile, writeJsonFile, getDataDir } from './json-store.js';
|
|
5
|
+
import { existsSync, readdirSync, rmSync, unlinkSync, readFileSync } from 'node:fs';
|
|
4
6
|
import path from 'node:path';
|
|
5
|
-
|
|
7
|
+
// ---- Path helpers ----
|
|
8
|
+
export function workflowsDir() {
|
|
6
9
|
return path.join(getDataDir(), 'workflows');
|
|
7
10
|
}
|
|
8
|
-
function
|
|
11
|
+
function workflowDir(workflowId) {
|
|
12
|
+
return path.join(workflowsDir(), workflowId);
|
|
13
|
+
}
|
|
14
|
+
function workflowPath(workflowId) {
|
|
15
|
+
return path.join(workflowDir(workflowId), 'workflow.json');
|
|
16
|
+
}
|
|
17
|
+
function workflowIndexPath() {
|
|
9
18
|
return path.join(workflowsDir(), 'index.json');
|
|
10
19
|
}
|
|
11
|
-
function
|
|
20
|
+
function versionsDir(workflowId) {
|
|
21
|
+
return path.join(workflowDir(workflowId), 'versions');
|
|
22
|
+
}
|
|
23
|
+
function executionHistoryDir(workflowId) {
|
|
24
|
+
return path.join(workflowDir(workflowId), 'execution_history');
|
|
25
|
+
}
|
|
26
|
+
function pluginConfigsDir(workflowId) {
|
|
27
|
+
return path.join(workflowDir(workflowId), 'plugin_configs');
|
|
28
|
+
}
|
|
29
|
+
function pluginSchemePath(workflowId, pluginId, schemeName) {
|
|
30
|
+
return path.join(pluginConfigsDir(workflowId), pluginId, `${schemeName}.json`);
|
|
31
|
+
}
|
|
32
|
+
function workflowFoldersPath() {
|
|
33
|
+
return path.join(workflowsDir(), 'folders.json');
|
|
34
|
+
}
|
|
35
|
+
function stagingPath(workflowId) {
|
|
36
|
+
return path.join(workflowDir(workflowId), 'staging.json');
|
|
37
|
+
}
|
|
38
|
+
function operationHistoryPath(workflowId) {
|
|
39
|
+
return path.join(workflowDir(workflowId), 'operation_history.json');
|
|
40
|
+
}
|
|
41
|
+
function chatPath(workflowId) {
|
|
42
|
+
return path.join(workflowDir(workflowId), 'chat.json');
|
|
43
|
+
}
|
|
44
|
+
// ---- Legacy migration ----
|
|
45
|
+
function legacyWorkflowPath(workflowId) {
|
|
12
46
|
return path.join(workflowsDir(), `${workflowId}.json`);
|
|
13
47
|
}
|
|
14
|
-
|
|
15
|
-
|
|
48
|
+
function migrateFromLegacyFormat() {
|
|
49
|
+
const dir = workflowsDir();
|
|
50
|
+
if (!existsSync(dir))
|
|
51
|
+
return;
|
|
52
|
+
// Read legacy index
|
|
53
|
+
const indexPath = workflowIndexPath();
|
|
54
|
+
const legacyIndex = readJsonFile(indexPath);
|
|
55
|
+
if (!Array.isArray(legacyIndex) || legacyIndex.length === 0)
|
|
56
|
+
return;
|
|
57
|
+
// Check if already migrated (has per-workflow dirs)
|
|
58
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
59
|
+
const hasWorkflowDirs = entries.some(e => e.isDirectory() && existsSync(path.join(dir, e.name, 'workflow.json')));
|
|
60
|
+
if (hasWorkflowDirs)
|
|
61
|
+
return;
|
|
62
|
+
// Migrate each legacy workflow
|
|
63
|
+
for (const entry of legacyIndex) {
|
|
64
|
+
const legacyFile = legacyWorkflowPath(entry.id);
|
|
65
|
+
if (!existsSync(legacyFile))
|
|
66
|
+
continue;
|
|
67
|
+
try {
|
|
68
|
+
const raw = JSON.parse(readFileSync(legacyFile, 'utf-8'));
|
|
69
|
+
const migrated = migrateLegacyWorkflow(raw);
|
|
70
|
+
ensureDir(workflowDir(migrated.id));
|
|
71
|
+
writeJsonFile(workflowPath(migrated.id), migrated);
|
|
72
|
+
unlinkSync(legacyFile);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Skip broken files
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Remove legacy index
|
|
79
|
+
unlinkSync(indexPath);
|
|
80
|
+
}
|
|
81
|
+
function migrateLegacyWorkflow(raw) {
|
|
82
|
+
return {
|
|
83
|
+
id: raw.id,
|
|
84
|
+
name: raw.name,
|
|
85
|
+
folderId: raw.folderId ?? null,
|
|
86
|
+
description: raw.description,
|
|
87
|
+
nodes: Array.isArray(raw.nodes) ? raw.nodes.map(migrateLegacyNode) : [],
|
|
88
|
+
edges: Array.isArray(raw.edges) ? raw.edges.map(migrateLegacyEdge) : [],
|
|
89
|
+
createdAt: typeof raw.createdAt === 'string' ? Date.parse(raw.createdAt) : (raw.createdAt || Date.now()),
|
|
90
|
+
updatedAt: typeof raw.updatedAt === 'string' ? Date.parse(raw.updatedAt) : (raw.updatedAt || Date.now()),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function migrateLegacyNode(node) {
|
|
94
|
+
return {
|
|
95
|
+
id: node.id,
|
|
96
|
+
type: node.type || 'agent',
|
|
97
|
+
label: node.data?.label || node.label || '',
|
|
98
|
+
position: node.position || { x: 0, y: 0 },
|
|
99
|
+
data: { ...node.data },
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function migrateLegacyEdge(edge) {
|
|
103
|
+
return {
|
|
104
|
+
id: edge.id,
|
|
105
|
+
source: edge.source,
|
|
106
|
+
target: edge.target,
|
|
107
|
+
sourceHandle: edge.sourceHandle ?? null,
|
|
108
|
+
targetHandle: edge.targetHandle ?? null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// ---- CRUD ----
|
|
112
|
+
export function listWorkflows(folderId) {
|
|
113
|
+
migrateFromLegacyFormat();
|
|
114
|
+
const items = readAllWorkflowFiles();
|
|
115
|
+
if (folderId !== undefined)
|
|
116
|
+
return items.filter(w => w.folderId === folderId);
|
|
117
|
+
return items;
|
|
16
118
|
}
|
|
17
119
|
export function getWorkflow(workflowId) {
|
|
18
|
-
|
|
120
|
+
migrateFromLegacyFormat();
|
|
121
|
+
return readWorkflowFile(workflowId);
|
|
19
122
|
}
|
|
20
123
|
export function createWorkflow(workflow) {
|
|
21
|
-
ensureDir(
|
|
22
|
-
writeJsonFile(
|
|
23
|
-
const index = listWorkflows();
|
|
24
|
-
index.push(workflow);
|
|
25
|
-
writeJsonFile(workflowsIndex(), index);
|
|
124
|
+
ensureDir(workflowDir(workflow.id));
|
|
125
|
+
writeJsonFile(workflowPath(workflow.id), workflow);
|
|
26
126
|
}
|
|
27
127
|
export function updateWorkflow(workflow) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const idx = index.findIndex(w => w.id === workflow.id);
|
|
31
|
-
if (idx !== -1)
|
|
32
|
-
index[idx] = workflow;
|
|
33
|
-
writeJsonFile(workflowsIndex(), index);
|
|
128
|
+
ensureDir(workflowDir(workflow.id));
|
|
129
|
+
writeJsonFile(workflowPath(workflow.id), workflow);
|
|
34
130
|
}
|
|
35
131
|
export function deleteWorkflow(workflowId) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
132
|
+
const dir = workflowDir(workflowId);
|
|
133
|
+
if (existsSync(dir))
|
|
134
|
+
rmSync(dir, { recursive: true, force: true });
|
|
135
|
+
// Also clean up legacy flat file if it exists
|
|
136
|
+
const legacy = legacyWorkflowPath(workflowId);
|
|
137
|
+
if (existsSync(legacy))
|
|
138
|
+
unlinkSync(legacy);
|
|
139
|
+
}
|
|
140
|
+
// ---- Folders ----
|
|
141
|
+
export function listWorkflowFolders() {
|
|
142
|
+
const data = readJsonFile(workflowFoldersPath());
|
|
143
|
+
const folders = data?.folders ?? [];
|
|
144
|
+
return [...folders].sort((a, b) => a.order - b.order);
|
|
145
|
+
}
|
|
146
|
+
export function createWorkflowFolder(folder) {
|
|
147
|
+
const folders = listWorkflowFolders();
|
|
148
|
+
folders.push(folder);
|
|
149
|
+
writeJsonFile(workflowFoldersPath(), { folders });
|
|
150
|
+
}
|
|
151
|
+
export function updateWorkflowFolder(id, updates) {
|
|
152
|
+
const folders = listWorkflowFolders();
|
|
153
|
+
const idx = folders.findIndex(f => f.id === id);
|
|
154
|
+
if (idx === -1)
|
|
155
|
+
throw new Error(`Folder ${id} not found`);
|
|
156
|
+
folders[idx] = { ...folders[idx], ...updates };
|
|
157
|
+
writeJsonFile(workflowFoldersPath(), { folders });
|
|
158
|
+
}
|
|
159
|
+
export function deleteWorkflowFolder(id) {
|
|
160
|
+
const folders = listWorkflowFolders();
|
|
161
|
+
const childIds = collectChildFolderIds(folders, id);
|
|
162
|
+
const idsToDelete = new Set([id, ...childIds]);
|
|
163
|
+
const remaining = folders.filter(f => !idsToDelete.has(f.id));
|
|
164
|
+
writeJsonFile(workflowFoldersPath(), { folders: remaining });
|
|
165
|
+
// Delete workflows in removed folders
|
|
166
|
+
const workflows = readAllWorkflowFiles().filter(w => idsToDelete.has(w.folderId ?? ''));
|
|
167
|
+
for (const wf of workflows)
|
|
168
|
+
deleteWorkflow(wf.id);
|
|
169
|
+
}
|
|
170
|
+
// ---- Versions ----
|
|
171
|
+
const MAX_VERSIONS = 100;
|
|
172
|
+
export function listVersions(workflowId) {
|
|
173
|
+
const dir = versionsDir(workflowId);
|
|
174
|
+
if (!existsSync(dir))
|
|
175
|
+
return [];
|
|
176
|
+
return readdirSync(dir)
|
|
177
|
+
.filter(f => f.endsWith('.json'))
|
|
178
|
+
.map(f => {
|
|
179
|
+
try {
|
|
180
|
+
return JSON.parse(readFileSync(path.join(dir, f), 'utf-8'));
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
.filter(Boolean)
|
|
187
|
+
.sort((a, b) => b.createdAt - a.createdAt);
|
|
188
|
+
}
|
|
189
|
+
export function addVersion(workflowId, version) {
|
|
190
|
+
const dir = versionsDir(workflowId);
|
|
191
|
+
ensureDir(dir);
|
|
192
|
+
writeJsonFile(path.join(dir, `${version.id}.json`), version);
|
|
193
|
+
// Enforce limit
|
|
194
|
+
const versions = listVersions(workflowId);
|
|
195
|
+
if (versions.length > MAX_VERSIONS) {
|
|
196
|
+
versions.slice(MAX_VERSIONS).forEach((v) => {
|
|
197
|
+
const p = path.join(dir, `${v.id}.json`);
|
|
198
|
+
if (existsSync(p))
|
|
199
|
+
unlinkSync(p);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return version;
|
|
203
|
+
}
|
|
204
|
+
export function getVersion(workflowId, versionId) {
|
|
205
|
+
const file = path.join(versionsDir(workflowId), `${versionId}.json`);
|
|
206
|
+
return readJsonFile(file);
|
|
207
|
+
}
|
|
208
|
+
export function deleteVersion(workflowId, versionId) {
|
|
209
|
+
const file = path.join(versionsDir(workflowId), `${versionId}.json`);
|
|
210
|
+
if (existsSync(file))
|
|
211
|
+
unlinkSync(file);
|
|
212
|
+
}
|
|
213
|
+
export function clearVersions(workflowId) {
|
|
214
|
+
const dir = versionsDir(workflowId);
|
|
215
|
+
if (!existsSync(dir))
|
|
216
|
+
return;
|
|
217
|
+
readdirSync(dir).filter(f => f.endsWith('.json')).forEach(f => unlinkSync(path.join(dir, f)));
|
|
218
|
+
}
|
|
219
|
+
// ---- Execution Logs ----
|
|
220
|
+
const MAX_LOGS = 100;
|
|
221
|
+
export function listExecutionLogs(workflowId) {
|
|
222
|
+
const dir = executionHistoryDir(workflowId);
|
|
223
|
+
if (!existsSync(dir))
|
|
224
|
+
return [];
|
|
225
|
+
return readdirSync(dir)
|
|
226
|
+
.filter(f => f.endsWith('.json'))
|
|
227
|
+
.map(f => {
|
|
228
|
+
const p = path.join(dir, f);
|
|
229
|
+
try {
|
|
230
|
+
return { log: JSON.parse(readFileSync(p, 'utf-8')), mtime: statSync(p).mtimeMs };
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
})
|
|
236
|
+
.filter(Boolean)
|
|
237
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
238
|
+
.map((item) => item.log);
|
|
239
|
+
}
|
|
240
|
+
export function addExecutionLog(workflowId, log) {
|
|
241
|
+
const dir = executionHistoryDir(workflowId);
|
|
242
|
+
ensureDir(dir);
|
|
243
|
+
writeJsonFile(path.join(dir, `${log.id}.json`), log);
|
|
244
|
+
// Enforce limit
|
|
245
|
+
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
246
|
+
if (files.length > MAX_LOGS) {
|
|
247
|
+
files.map(f => ({ f, mtime: statSync(path.join(dir, f)).mtimeMs }))
|
|
248
|
+
.sort((a, b) => b.mtime - a.mtime)
|
|
249
|
+
.slice(MAX_LOGS)
|
|
250
|
+
.forEach(item => { try {
|
|
251
|
+
unlinkSync(path.join(dir, item.f));
|
|
252
|
+
}
|
|
253
|
+
catch { /* ignore */ } });
|
|
254
|
+
}
|
|
255
|
+
return log;
|
|
256
|
+
}
|
|
257
|
+
export function listAllExecutionLogs(limit = 50) {
|
|
258
|
+
const dir = workflowsDir();
|
|
259
|
+
if (!existsSync(dir))
|
|
260
|
+
return [];
|
|
261
|
+
const results = [];
|
|
262
|
+
const wDirs = readdirSync(dir, { withFileTypes: true }).filter(d => d.isDirectory());
|
|
263
|
+
for (const wDir of wDirs) {
|
|
264
|
+
const wId = wDir.name;
|
|
265
|
+
const historyDir = executionHistoryDir(wId);
|
|
266
|
+
if (!existsSync(historyDir))
|
|
267
|
+
continue;
|
|
268
|
+
// Read workflow name for display
|
|
269
|
+
let workflowName = wId;
|
|
270
|
+
const wfPath = workflowPath(wId);
|
|
271
|
+
if (existsSync(wfPath)) {
|
|
272
|
+
try {
|
|
273
|
+
workflowName = JSON.parse(readFileSync(wfPath, 'utf-8')).name || wId;
|
|
274
|
+
}
|
|
275
|
+
catch { /* ignore */ }
|
|
276
|
+
}
|
|
277
|
+
readdirSync(historyDir)
|
|
278
|
+
.filter(f => f.endsWith('.json'))
|
|
279
|
+
.forEach(f => {
|
|
280
|
+
try {
|
|
281
|
+
const log = JSON.parse(readFileSync(path.join(historyDir, f), 'utf-8'));
|
|
282
|
+
results.push({ ...log, workflowName });
|
|
283
|
+
}
|
|
284
|
+
catch { /* ignore */ }
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
return results
|
|
288
|
+
.sort((a, b) => (b.startedAt || 0) - (a.startedAt || 0))
|
|
289
|
+
.slice(0, limit);
|
|
290
|
+
}
|
|
291
|
+
export function getExecutionLog(workflowId, logId) {
|
|
292
|
+
return readJsonFile(path.join(executionHistoryDir(workflowId), `${logId}.json`));
|
|
293
|
+
}
|
|
294
|
+
export function deleteExecutionLog(workflowId, logId) {
|
|
295
|
+
const file = path.join(executionHistoryDir(workflowId), `${logId}.json`);
|
|
296
|
+
if (existsSync(file))
|
|
297
|
+
unlinkSync(file);
|
|
298
|
+
}
|
|
299
|
+
export function clearExecutionLogs(workflowId) {
|
|
300
|
+
const dir = executionHistoryDir(workflowId);
|
|
301
|
+
if (!existsSync(dir))
|
|
302
|
+
return;
|
|
303
|
+
readdirSync(dir).filter(f => f.endsWith('.json')).forEach(f => unlinkSync(path.join(dir, f)));
|
|
304
|
+
}
|
|
305
|
+
// ---- Staging ----
|
|
306
|
+
export function loadStaging(workflowId) {
|
|
307
|
+
return readJsonFile(stagingPath(workflowId)) ?? [];
|
|
308
|
+
}
|
|
309
|
+
export function saveStaging(workflowId, nodes) {
|
|
310
|
+
ensureDir(workflowDir(workflowId));
|
|
311
|
+
writeJsonFile(stagingPath(workflowId), nodes);
|
|
312
|
+
}
|
|
313
|
+
export function clearStaging(workflowId) {
|
|
314
|
+
const file = stagingPath(workflowId);
|
|
315
|
+
if (existsSync(file))
|
|
316
|
+
unlinkSync(file);
|
|
317
|
+
}
|
|
318
|
+
// ---- Operation History ----
|
|
319
|
+
export function loadOperationHistory(workflowId) {
|
|
320
|
+
return readJsonFile(operationHistoryPath(workflowId)) ?? [];
|
|
321
|
+
}
|
|
322
|
+
export function saveOperationHistory(workflowId, entries) {
|
|
323
|
+
ensureDir(workflowDir(workflowId));
|
|
324
|
+
writeJsonFile(operationHistoryPath(workflowId), entries);
|
|
325
|
+
}
|
|
326
|
+
export function clearOperationHistory(workflowId) {
|
|
327
|
+
const file = operationHistoryPath(workflowId);
|
|
328
|
+
if (existsSync(file))
|
|
329
|
+
unlinkSync(file);
|
|
330
|
+
}
|
|
331
|
+
// ---- Workflow Agent Chat ----
|
|
332
|
+
export function loadChat(workflowId) {
|
|
333
|
+
return readJsonFile(chatPath(workflowId)) ?? [];
|
|
334
|
+
}
|
|
335
|
+
export function saveChat(workflowId, messages) {
|
|
336
|
+
ensureDir(workflowDir(workflowId));
|
|
337
|
+
writeJsonFile(chatPath(workflowId), messages);
|
|
338
|
+
}
|
|
339
|
+
export function clearChat(workflowId) {
|
|
340
|
+
const file = chatPath(workflowId);
|
|
341
|
+
if (existsSync(file))
|
|
342
|
+
unlinkSync(file);
|
|
343
|
+
}
|
|
344
|
+
// ---- Plugin Schemes ----
|
|
345
|
+
export function listPluginSchemes(workflowId, pluginId) {
|
|
346
|
+
const dir = path.join(pluginConfigsDir(workflowId), pluginId);
|
|
347
|
+
if (!existsSync(dir))
|
|
348
|
+
return [];
|
|
349
|
+
return readdirSync(dir).filter(f => f.endsWith('.json')).map(f => f.replace(/\.json$/, '')).sort();
|
|
350
|
+
}
|
|
351
|
+
export function readPluginScheme(workflowId, pluginId, schemeName) {
|
|
352
|
+
const file = pluginSchemePath(workflowId, pluginId, schemeName);
|
|
353
|
+
if (!existsSync(file))
|
|
354
|
+
throw new Error(`Plugin scheme ${schemeName} not found`);
|
|
355
|
+
return JSON.parse(readFileSync(file, 'utf-8'));
|
|
356
|
+
}
|
|
357
|
+
export function savePluginScheme(workflowId, pluginId, schemeName, data) {
|
|
358
|
+
const dir = path.join(pluginConfigsDir(workflowId), pluginId);
|
|
359
|
+
ensureDir(dir);
|
|
360
|
+
writeJsonFile(pluginSchemePath(workflowId, pluginId, schemeName), data);
|
|
361
|
+
}
|
|
362
|
+
export function deletePluginScheme(workflowId, pluginId, schemeName) {
|
|
363
|
+
const file = pluginSchemePath(workflowId, pluginId, schemeName);
|
|
364
|
+
if (existsSync(file))
|
|
365
|
+
unlinkSync(file);
|
|
366
|
+
}
|
|
367
|
+
// ---- Internal helpers ----
|
|
368
|
+
function readAllWorkflowFiles() {
|
|
369
|
+
const dir = workflowsDir();
|
|
370
|
+
if (!existsSync(dir))
|
|
371
|
+
return [];
|
|
372
|
+
const items = [];
|
|
373
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
374
|
+
for (const entry of entries) {
|
|
375
|
+
if (!entry.isDirectory())
|
|
376
|
+
continue;
|
|
377
|
+
const file = path.join(dir, entry.name, 'workflow.json');
|
|
378
|
+
if (!existsSync(file))
|
|
379
|
+
continue;
|
|
380
|
+
try {
|
|
381
|
+
items.push(JSON.parse(readFileSync(file, 'utf-8')));
|
|
382
|
+
}
|
|
383
|
+
catch { /* skip broken */ }
|
|
384
|
+
}
|
|
385
|
+
return items.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
386
|
+
}
|
|
387
|
+
function readWorkflowFile(workflowId) {
|
|
388
|
+
const file = workflowPath(workflowId);
|
|
389
|
+
if (!existsSync(file))
|
|
390
|
+
return null;
|
|
391
|
+
try {
|
|
392
|
+
return JSON.parse(readFileSync(file, 'utf-8'));
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function collectChildFolderIds(folders, parentId) {
|
|
399
|
+
const children = folders.filter(f => f.parentId === parentId);
|
|
400
|
+
return children.reduce((acc, child) => [...acc, child.id, ...collectChildFolderIds(folders, child.id)], []);
|
|
39
401
|
}
|
|
402
|
+
// Need statSync for execution log sorting
|
|
403
|
+
import { statSync } from 'node:fs';
|
|
40
404
|
//# sourceMappingURL=workflow-store.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { getDataDir, ensureDir, readJsonFile, writeJsonFile } from './json-store.js';
|
|
3
|
+
function worktreesDir(workspaceId) {
|
|
4
|
+
return join(getDataDir(), 'workspaces', workspaceId, 'worktrees');
|
|
5
|
+
}
|
|
6
|
+
function worktreesIndex(workspaceId) {
|
|
7
|
+
return join(worktreesDir(workspaceId), 'index.json');
|
|
8
|
+
}
|
|
9
|
+
export function listWorktrees(workspaceId) {
|
|
10
|
+
return readJsonFile(worktreesIndex(workspaceId)) || [];
|
|
11
|
+
}
|
|
12
|
+
export function getWorktree(workspaceId, worktreeId) {
|
|
13
|
+
const list = listWorktrees(workspaceId);
|
|
14
|
+
return list.find(wt => wt.id === worktreeId) ?? null;
|
|
15
|
+
}
|
|
16
|
+
export function createWorktree(workspaceId, info) {
|
|
17
|
+
ensureDir(worktreesDir(workspaceId));
|
|
18
|
+
const list = listWorktrees(workspaceId);
|
|
19
|
+
list.push(info);
|
|
20
|
+
writeJsonFile(worktreesIndex(workspaceId), list);
|
|
21
|
+
}
|
|
22
|
+
export function updateWorktree(workspaceId, info) {
|
|
23
|
+
const list = listWorktrees(workspaceId);
|
|
24
|
+
const idx = list.findIndex(wt => wt.id === info.id);
|
|
25
|
+
if (idx >= 0)
|
|
26
|
+
list[idx] = info;
|
|
27
|
+
writeJsonFile(worktreesIndex(workspaceId), list);
|
|
28
|
+
}
|
|
29
|
+
export function deleteWorktreeFromIndex(workspaceId, worktreeId) {
|
|
30
|
+
const list = listWorktrees(workspaceId).filter(wt => wt.id !== worktreeId);
|
|
31
|
+
writeJsonFile(worktreesIndex(workspaceId), list);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=worktree-store.js.map
|