svamp-cli 0.2.174 → 0.2.175
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/{agentCommands-XAGMtjRQ.mjs → agentCommands-C4upUtMc.mjs} +5 -5
- package/dist/{auth-fEMoSUUD.mjs → auth-BKN98KO4.mjs} +1 -1
- package/dist/cli.mjs +61 -61
- package/dist/{commands-CPHMhYnp.mjs → commands-BF_Wy2B4.mjs} +1 -1
- package/dist/{commands-7wZGSXe5.mjs → commands-BbqjhR4z.mjs} +2 -2
- package/dist/{commands-NdHufk_2.mjs → commands-BssfhM-2.mjs} +1 -1
- package/dist/{commands-BaGfFhwa.mjs → commands-CSK-jSnk.mjs} +1 -1
- package/dist/{commands-3mxZi6dQ.mjs → commands-CkygtYMZ.mjs} +2 -2
- package/dist/{commands-BVyi7762.mjs → commands-D03sBXV4.mjs} +2 -2
- package/dist/{commands-Di_HYoeZ.mjs → commands-D2lD-S4d.mjs} +5 -5
- package/dist/{commands-B3Uk_kN9.mjs → commands-DICHik9Y.mjs} +5 -73
- package/dist/{fleet-B2GyUSYJ.mjs → fleet-qUmhLn41.mjs} +1 -1
- package/dist/{frpc-BZmO_6PK.mjs → frpc-BDZgTsi8.mjs} +1 -1
- package/dist/{headlessCli-Yeuekh99.mjs → headlessCli-BG-PcYjM.mjs} +2 -2
- package/dist/index.mjs +1 -1
- package/dist/{package-CmQGdoJz.mjs → package-CMB-hfB0.mjs} +2 -2
- package/dist/rpc-CQTahguB.mjs +78 -0
- package/dist/rpc-gCEvLUNu.mjs +151 -0
- package/dist/{run-BROwnG-V.mjs → run-Buov6wz-.mjs} +33 -6
- package/dist/{run-BE4jYZdk.mjs → run-DGs1hcvd.mjs} +1 -1
- package/dist/{serveCommands-C1Lfx-NW.mjs → serveCommands-C6l8yA9_.mjs} +5 -5
- package/dist/{serveManager-BdjeAjgf.mjs → serveManager-B_Bj1AF4.mjs} +2 -2
- package/dist/{sideband-CQDEJ2q2.mjs → sideband-BYiyQgZR.mjs} +1 -1
- package/dist/store-D2HNe-Kv.mjs +74 -0
- package/package.json +2 -2
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
-
import { m as resolveProjectRoot } from './run-
|
|
3
|
-
import {
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
import { parse, stringify } from 'yaml';
|
|
2
|
+
import { m as resolveProjectRoot } from './run-Buov6wz-.mjs';
|
|
3
|
+
import { r as removeWorkflow, g as getWorkflow, l as listWorkflows, s as saveWorkflow, a as rawWorkflow } from './store-D2HNe-Kv.mjs';
|
|
6
4
|
import 'os';
|
|
7
5
|
import 'fs/promises';
|
|
8
6
|
import 'fs';
|
|
@@ -11,7 +9,9 @@ import 'url';
|
|
|
11
9
|
import 'child_process';
|
|
12
10
|
import 'crypto';
|
|
13
11
|
import 'node:crypto';
|
|
12
|
+
import 'node:fs';
|
|
14
13
|
import 'util';
|
|
14
|
+
import 'node:path';
|
|
15
15
|
import 'node:events';
|
|
16
16
|
import 'node:os';
|
|
17
17
|
import '@agentclientprotocol/sdk';
|
|
@@ -21,75 +21,7 @@ import '@modelcontextprotocol/sdk/types.js';
|
|
|
21
21
|
import 'zod';
|
|
22
22
|
import 'node:fs/promises';
|
|
23
23
|
import 'node:util';
|
|
24
|
-
|
|
25
|
-
function workflowsDir(projectRoot) {
|
|
26
|
-
return join(projectRoot, ".svamp", "workflows");
|
|
27
|
-
}
|
|
28
|
-
function workflowPath(projectRoot, name) {
|
|
29
|
-
return join(workflowsDir(projectRoot), `${name}.yaml`);
|
|
30
|
-
}
|
|
31
|
-
function parseWorkflow(content) {
|
|
32
|
-
try {
|
|
33
|
-
const o = parse(content);
|
|
34
|
-
if (!o || typeof o !== "object" || !o.name) return null;
|
|
35
|
-
const jobs = Array.isArray(o.jobs) ? o.jobs.map((j) => ({ run: String(j?.run ?? "") })).filter((j) => j.run) : [];
|
|
36
|
-
return { name: String(o.name), on: o.on && typeof o.on === "object" ? o.on : void 0, jobs, session: o.session ?? null };
|
|
37
|
-
} catch {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
function serializeWorkflow(wf) {
|
|
42
|
-
const clean = { name: wf.name };
|
|
43
|
-
if (wf.session) clean.session = wf.session;
|
|
44
|
-
if (wf.on && Object.keys(wf.on).length) clean.on = wf.on;
|
|
45
|
-
clean.jobs = wf.jobs.map((j) => ({ run: j.run }));
|
|
46
|
-
return stringify(clean);
|
|
47
|
-
}
|
|
48
|
-
function listWorkflows(projectRoot) {
|
|
49
|
-
const dir = workflowsDir(projectRoot);
|
|
50
|
-
if (!existsSync(dir)) return [];
|
|
51
|
-
const out = [];
|
|
52
|
-
for (const name of readdirSync(dir)) {
|
|
53
|
-
if (!name.endsWith(".yaml") && !name.endsWith(".yml")) continue;
|
|
54
|
-
try {
|
|
55
|
-
const wf = parseWorkflow(readFileSync(join(dir, name), "utf-8"));
|
|
56
|
-
if (wf) out.push(wf);
|
|
57
|
-
} catch {
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
61
|
-
}
|
|
62
|
-
function getWorkflow(projectRoot, name) {
|
|
63
|
-
const p = workflowPath(projectRoot, name);
|
|
64
|
-
if (!existsSync(p)) return null;
|
|
65
|
-
try {
|
|
66
|
-
return parseWorkflow(readFileSync(p, "utf-8"));
|
|
67
|
-
} catch {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function rawWorkflow(projectRoot, name) {
|
|
72
|
-
const p = workflowPath(projectRoot, name);
|
|
73
|
-
return existsSync(p) ? readFileSync(p, "utf-8") : null;
|
|
74
|
-
}
|
|
75
|
-
function saveWorkflow(projectRoot, wf) {
|
|
76
|
-
const dir = workflowsDir(projectRoot);
|
|
77
|
-
mkdirSync(dir, { recursive: true });
|
|
78
|
-
const path = workflowPath(projectRoot, wf.name);
|
|
79
|
-
const tmp = `${path}.tmp-${process.pid}`;
|
|
80
|
-
writeFileSync(tmp, serializeWorkflow(wf));
|
|
81
|
-
renameSync(tmp, path);
|
|
82
|
-
}
|
|
83
|
-
function removeWorkflow(projectRoot, name) {
|
|
84
|
-
const p = workflowPath(projectRoot, name);
|
|
85
|
-
if (!existsSync(p)) return false;
|
|
86
|
-
try {
|
|
87
|
-
unlinkSync(p);
|
|
88
|
-
return true;
|
|
89
|
-
} catch {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
24
|
+
import 'yaml';
|
|
93
25
|
|
|
94
26
|
function flag(args, name) {
|
|
95
27
|
const i = args.indexOf(name);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import os from 'node:os';
|
|
4
|
-
import { c as connectToHypha } from './run-
|
|
4
|
+
import { c as connectToHypha } from './run-Buov6wz-.mjs';
|
|
5
5
|
import { PINNED_CLAUDE_CODE_VERSION } from './pinnedClaudeCode-HydRNEt7.mjs';
|
|
6
6
|
import 'os';
|
|
7
7
|
import 'fs/promises';
|
|
@@ -4,7 +4,7 @@ import { mkdirSync, writeFileSync, unlinkSync, existsSync, chmodSync, readFileSy
|
|
|
4
4
|
import { join } from 'path';
|
|
5
5
|
import { homedir, platform, arch } from 'os';
|
|
6
6
|
import { randomUUID, createHash } from 'crypto';
|
|
7
|
-
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-
|
|
7
|
+
import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-Buov6wz-.mjs';
|
|
8
8
|
import 'fs/promises';
|
|
9
9
|
import 'url';
|
|
10
10
|
import 'node:crypto';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { N as resolveModel, $ as describeMisconfiguration, a0 as buildMachineDeps } from './run-
|
|
2
|
-
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-
|
|
1
|
+
import { N as resolveModel, $ as describeMisconfiguration, a0 as buildMachineDeps } from './run-Buov6wz-.mjs';
|
|
2
|
+
import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-BYiyQgZR.mjs';
|
|
3
3
|
import { WebSocket } from 'ws';
|
|
4
4
|
import { execSync, spawn } from 'child_process';
|
|
5
5
|
import 'os';
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-
|
|
1
|
+
export { c as connectToHypha, a as createSessionStore, d as daemonStatus, g as getHyphaServerUrl, r as registerMachineService, s as startDaemon, b as stopDaemon } from './run-Buov6wz-.mjs';
|
|
2
2
|
import 'os';
|
|
3
3
|
import 'fs/promises';
|
|
4
4
|
import 'fs';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "svamp-cli";
|
|
2
|
-
var version = "0.2.
|
|
2
|
+
var version = "0.2.175";
|
|
3
3
|
var description = "Svamp CLI — AI workspace daemon on Hypha Cloud";
|
|
4
4
|
var author = "Amun AI AB";
|
|
5
5
|
var license = "SEE LICENSE IN LICENSE";
|
|
@@ -19,7 +19,7 @@ var exports$1 = {
|
|
|
19
19
|
var scripts = {
|
|
20
20
|
build: "rm -rf dist bin/skills && mkdir -p bin/skills && cp -r ../../skills/artifact bin/skills/artifact && cp -r ../../skills/loop bin/skills/loop && cp -r ../../skills/crew bin/skills/crew && tsc --noEmit && pkgroll",
|
|
21
21
|
typecheck: "tsc --noEmit",
|
|
22
|
-
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-sharing-notify-sync.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-loop-activation.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs",
|
|
22
|
+
test: "npx tsx test/test-context-window.mjs && npx tsx test/test-ratelimit-retry.mjs && npx tsx test/test-instance-config.mjs && npx tsx test/test-authorize.mjs && npx tsx test/test-normalize-allowed-user.mjs && npx tsx test/test-share-url.mjs && npx tsx test/test-update-sharing-normalization.mjs && npx tsx test/test-sharing-notify-sync.mjs && npx tsx test/test-staged-homes-sweep.mjs && npx tsx test/test-session-helpers.mjs && npx tsx test/test-cli-routing.mjs && npx tsx test/test-security-context.mjs && npx tsx test/test-isolation-decision.mjs && npx tsx test/test-loop-activation.mjs && npx tsx test/test-message-helpers.mjs && npx tsx test/test-agent-config.mjs && npx tsx test/test-wrap-command.mjs && npx tsx test/test-credential-staging.mjs && npx tsx test/test-claude-auth.mjs && npx tsx test/test-output-formatters.mjs && npx tsx test/test-inbox-guard.mjs && npx tsx test/test-auto-topic.mjs && npx tsx test/test-project-info.mjs && npx tsx test/test-agent-types.mjs && npx tsx test/test-transport.mjs && npx tsx test/test-session-update-handlers.mjs && npx tsx test/test-session-scanner.mjs && npx tsx test/test-hypha-client.mjs && npx tsx test/test-hook-settings.mjs && npx tsx test/test-session-service-logic.mjs && npx tsx test/test-daemon-persistence.mjs && npx tsx test/test-detect-isolation.mjs && npx tsx test/test-machine-service-logic.mjs && npx tsx test/test-interactive-helpers.mjs && npx tsx test/test-codex-backend.mjs && npx tsx test/test-acp-backend.mjs && npx tsx test/test-acp-bridge.mjs && npx tsx test/test-hook-server.mjs && npx tsx test/test-session-commands.mjs && npx tsx test/test-interactive-console.mjs && npx tsx test/test-session-messages.mjs && npx tsx test/test-session-send-query.mjs && npx tsx test/test-skills.mjs && npx tsx test/test-agent-grouping.mjs && npx tsx test/test-machine-list-directory.mjs && npx tsx test/test-service-commands.mjs && npx tsx test/test-supervisor.mjs && npx tsx test/test-supervisor-lock.mjs && node test/test-supervisor-restart.mjs && npx tsx test/test-clear-detection.mjs && npx tsx test/test-session-consolidation.mjs && npx tsx test/test-inbox.mjs && npx tsx test/test-inbox-cross-machine.mjs && npx tsx test/test-issue-store.mjs && npx tsx test/test-issue-close-gate.mjs && npx tsx test/test-issue-rpc.mjs && npx tsx test/test-workflow-store.mjs && npx tsx test/test-workflow-rpc.mjs && npx tsx test/test-serve-link-subdomain.mjs && npx tsx test/test-short-id.mjs && npx tsx test/test-transcript-edit.mjs && npx tsx test/test-edit-history.mjs && npx tsx test/test-friendly-name.mjs && npx tsx test/test-session-rpc-dispatch.mjs && npx tsx test/test-sandbox-cli.mjs && npx tsx test/test-serve-manager.mjs && npx tsx test/test-serve-stability.mjs && npx tsx test/test-frpc-e2e.mjs --unit-only && npx tsx test/test-frpc-status.mjs && node test/pinnedClaudeCode.test.mjs && node test/fleet.test.mjs && npx tsx test/test-routine.mjs && npx tsx test/test-routine-rpc.mjs && npx tsx test/test-session-file.mjs && npx tsx test/test-channel-rpc.mjs && npx tsx test/test-wise-agent.mjs && npx tsx test/test-channel-agent.mjs && npx tsx test/test-channels-service.mjs && npx tsx test/test-channel-async-reply.mjs && npx tsx test/test-channel-binding.mjs && npx tsx test/test-channel-identity.mjs && npx tsx test/test-shared-session-identity.mjs && npx tsx test/test-wise-agent-auth.mjs && npx tsx test/test-channel-http.mjs && npx tsx test/test-wise-voice.mjs && npx tsx test/test-wise-headless.mjs && npx tsx test/test-wise-machine.mjs && npx tsx test/test-crew-merge.mjs && npx tsx test/test-crew-verdict-routing.mjs",
|
|
23
23
|
"test:hypha": "node --no-warnings test/test-hypha-service.mjs",
|
|
24
24
|
dev: "tsx src/cli.ts",
|
|
25
25
|
"dev:daemon": "tsx src/cli.ts daemon start-sync",
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { m as resolveProjectRoot } from './run-Buov6wz-.mjs';
|
|
3
|
+
import { g as getWorkflow, r as removeWorkflow, s as saveWorkflow, a as rawWorkflow, l as listWorkflows } from './store-D2HNe-Kv.mjs';
|
|
4
|
+
import 'os';
|
|
5
|
+
import 'fs/promises';
|
|
6
|
+
import 'fs';
|
|
7
|
+
import 'path';
|
|
8
|
+
import 'url';
|
|
9
|
+
import 'child_process';
|
|
10
|
+
import 'crypto';
|
|
11
|
+
import 'node:crypto';
|
|
12
|
+
import 'node:fs';
|
|
13
|
+
import 'util';
|
|
14
|
+
import 'node:path';
|
|
15
|
+
import 'node:events';
|
|
16
|
+
import 'node:os';
|
|
17
|
+
import '@agentclientprotocol/sdk';
|
|
18
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
19
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
20
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
21
|
+
import 'zod';
|
|
22
|
+
import 'node:fs/promises';
|
|
23
|
+
import 'node:util';
|
|
24
|
+
import 'yaml';
|
|
25
|
+
|
|
26
|
+
function workflowRpc(cwd, params) {
|
|
27
|
+
const root = resolveProjectRoot(cwd || process.cwd());
|
|
28
|
+
const op = params.op;
|
|
29
|
+
switch (op) {
|
|
30
|
+
case "list":
|
|
31
|
+
return listWorkflows(root);
|
|
32
|
+
case "show": {
|
|
33
|
+
const wf = getWorkflow(root, String(params.name));
|
|
34
|
+
return { meta: wf, yaml: wf ? rawWorkflow(root, String(params.name)) || "" : null };
|
|
35
|
+
}
|
|
36
|
+
case "add": {
|
|
37
|
+
const on = {};
|
|
38
|
+
if (params.cron) on.schedule = String(params.cron);
|
|
39
|
+
if (params.dispatch) on.dispatch = true;
|
|
40
|
+
if (params.channel) on.channel = String(params.channel);
|
|
41
|
+
if (Array.isArray(params.issue) && params.issue.length) on.issue = params.issue.map(String);
|
|
42
|
+
const runs = Array.isArray(params.runs) ? params.runs.map(String).filter(Boolean) : [];
|
|
43
|
+
if (!params.name || !runs.length) throw new Error("workflow add: name and at least one run step required");
|
|
44
|
+
const wf = {
|
|
45
|
+
name: String(params.name),
|
|
46
|
+
on: Object.keys(on).length ? on : void 0,
|
|
47
|
+
jobs: runs.map((r) => ({ run: r })),
|
|
48
|
+
session: params.session || null
|
|
49
|
+
};
|
|
50
|
+
saveWorkflow(root, wf);
|
|
51
|
+
return wf;
|
|
52
|
+
}
|
|
53
|
+
case "remove":
|
|
54
|
+
return { removed: removeWorkflow(root, String(params.name)) };
|
|
55
|
+
case "run": {
|
|
56
|
+
const wf = getWorkflow(root, String(params.name));
|
|
57
|
+
if (!wf) throw new Error(`Workflow not found: ${params.name}`);
|
|
58
|
+
const out = [`\u25B6 running workflow "${wf.name}" (${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"})`];
|
|
59
|
+
for (let i = 0; i < wf.jobs.length; i++) {
|
|
60
|
+
const step = wf.jobs[i];
|
|
61
|
+
out.push(` [${i + 1}/${wf.jobs.length}] $ ${step.run}`);
|
|
62
|
+
const r = spawnSync("sh", ["-c", step.run], { cwd: root, encoding: "utf-8", timeout: 12e4 });
|
|
63
|
+
if (r.stdout) out.push(r.stdout.trimEnd());
|
|
64
|
+
if (r.stderr) out.push(r.stderr.trimEnd());
|
|
65
|
+
if (r.status !== 0) {
|
|
66
|
+
out.push(` \u2717 step ${i + 1} failed (exit ${r.status ?? "signal"}). Stopping.`);
|
|
67
|
+
return { ok: false, output: out.join("\n") };
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
out.push(`\u2713 workflow "${wf.name}" completed.`);
|
|
71
|
+
return { ok: true, output: out.join("\n") };
|
|
72
|
+
}
|
|
73
|
+
default:
|
|
74
|
+
throw new Error(`workflow rpc: unknown op "${op}"`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export { workflowRpc };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { m as resolveProjectRoot, u as updateIssue, n as getIssue, o as addComment, p as addIssue, q as listIssues, t as searchIssues } from './run-Buov6wz-.mjs';
|
|
2
|
+
import 'os';
|
|
3
|
+
import 'fs/promises';
|
|
4
|
+
import 'fs';
|
|
5
|
+
import 'path';
|
|
6
|
+
import 'url';
|
|
7
|
+
import 'child_process';
|
|
8
|
+
import 'crypto';
|
|
9
|
+
import 'node:crypto';
|
|
10
|
+
import 'node:fs';
|
|
11
|
+
import 'node:child_process';
|
|
12
|
+
import 'util';
|
|
13
|
+
import 'node:path';
|
|
14
|
+
import 'node:events';
|
|
15
|
+
import 'node:os';
|
|
16
|
+
import '@agentclientprotocol/sdk';
|
|
17
|
+
import '@modelcontextprotocol/sdk/client/index.js';
|
|
18
|
+
import '@modelcontextprotocol/sdk/client/stdio.js';
|
|
19
|
+
import '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
import 'zod';
|
|
21
|
+
import 'node:fs/promises';
|
|
22
|
+
import 'node:util';
|
|
23
|
+
|
|
24
|
+
function compact(i) {
|
|
25
|
+
const { body, original, ...rest } = i;
|
|
26
|
+
return rest;
|
|
27
|
+
}
|
|
28
|
+
function buildVerify(p) {
|
|
29
|
+
if (p.verifyCmd) return { type: "command", text: String(p.verifyCmd) };
|
|
30
|
+
if (p.verify) return { type: "agent", text: String(p.verify) };
|
|
31
|
+
if (p.manual) return { type: "manual" };
|
|
32
|
+
if (p.noVerify) return null;
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
function ownerScoped(items, session) {
|
|
36
|
+
if (!session) return items;
|
|
37
|
+
return items.filter((i) => i.scope === "project" || i.session === session);
|
|
38
|
+
}
|
|
39
|
+
const STATUS_MAP = {
|
|
40
|
+
ready: "ready",
|
|
41
|
+
start: "in_progress",
|
|
42
|
+
close: "done",
|
|
43
|
+
done: "done",
|
|
44
|
+
reopen: "ready",
|
|
45
|
+
archive: "archived",
|
|
46
|
+
backlog: "backlog"
|
|
47
|
+
};
|
|
48
|
+
function issueRpc(cwd, params) {
|
|
49
|
+
const root = resolveProjectRoot(cwd || process.cwd());
|
|
50
|
+
const op = params.op;
|
|
51
|
+
switch (op) {
|
|
52
|
+
case "list": {
|
|
53
|
+
const opts = { includeArchived: params.status === "all" || params.status === "archived" || params.includeArchived };
|
|
54
|
+
if (params.status && params.status !== "all") opts.status = params.status;
|
|
55
|
+
if (params.label) opts.label = params.label;
|
|
56
|
+
if (params.scope) opts.scope = params.scope;
|
|
57
|
+
return ownerScoped(listIssues(root, opts), params.session).map(compact);
|
|
58
|
+
}
|
|
59
|
+
case "show":
|
|
60
|
+
return getIssue(root, String(params.id));
|
|
61
|
+
case "search":
|
|
62
|
+
return ownerScoped(searchIssues(root, String(params.query || "")), params.session).map(compact);
|
|
63
|
+
case "pending": {
|
|
64
|
+
const items = ownerScoped(listIssues(root), params.session).filter((i) => i.status === "ready" || i.status === "in_progress" || i.status === "backlog" && !i.triaged);
|
|
65
|
+
return { pending: items.map((i) => i.id), count: items.length };
|
|
66
|
+
}
|
|
67
|
+
case "add": {
|
|
68
|
+
const owner = params.session || null;
|
|
69
|
+
const scope = params.scope || (owner ? "session" : "project");
|
|
70
|
+
let title = params.title ? String(params.title) : "";
|
|
71
|
+
let body = params.body ? String(params.body) : void 0;
|
|
72
|
+
let original;
|
|
73
|
+
if (!title) {
|
|
74
|
+
const src = (body || "").trim();
|
|
75
|
+
if (!src) throw new Error("issue add: title or body required");
|
|
76
|
+
const nl = src.indexOf("\n");
|
|
77
|
+
title = (nl === -1 ? src : src.slice(0, nl)).trim().slice(0, 200);
|
|
78
|
+
original = src;
|
|
79
|
+
body = void 0;
|
|
80
|
+
}
|
|
81
|
+
return addIssue(root, {
|
|
82
|
+
title,
|
|
83
|
+
status: params.ready ? "ready" : "backlog",
|
|
84
|
+
scope,
|
|
85
|
+
labels: Array.isArray(params.labels) ? params.labels.map(String) : [],
|
|
86
|
+
verify: buildVerify(params) ?? null,
|
|
87
|
+
session: scope === "session" ? owner : null,
|
|
88
|
+
original,
|
|
89
|
+
body
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
case "comment":
|
|
93
|
+
return addComment(root, String(params.id), String(params.text || ""));
|
|
94
|
+
case "status": {
|
|
95
|
+
const status = STATUS_MAP[params.status];
|
|
96
|
+
if (!status) throw new Error(`issue status: unknown status "${params.status}"`);
|
|
97
|
+
const patch = { status };
|
|
98
|
+
if (status === "in_progress" && params.session) {
|
|
99
|
+
const cur = getIssue(root, String(params.id));
|
|
100
|
+
if (cur && cur.scope === "project" && !cur.session) patch.session = params.session;
|
|
101
|
+
}
|
|
102
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
103
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
104
|
+
return updated;
|
|
105
|
+
}
|
|
106
|
+
case "work": {
|
|
107
|
+
const patch = { status: "in_progress" };
|
|
108
|
+
if (params.branch) patch.branch = String(params.branch);
|
|
109
|
+
const worker = params.session || null;
|
|
110
|
+
const cur = getIssue(root, String(params.id));
|
|
111
|
+
if (worker && cur && cur.scope === "project" && !cur.session) patch.session = worker;
|
|
112
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
113
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
114
|
+
return updated;
|
|
115
|
+
}
|
|
116
|
+
case "edit": {
|
|
117
|
+
const patch = {};
|
|
118
|
+
if (params.title != null) patch.title = String(params.title);
|
|
119
|
+
if (Array.isArray(params.labels)) patch.labels = params.labels.map(String);
|
|
120
|
+
const v = buildVerify(params);
|
|
121
|
+
if (v !== void 0) patch.verify = v;
|
|
122
|
+
if (params.scope) patch.scope = params.scope;
|
|
123
|
+
if (params.unclaim) patch.session = null;
|
|
124
|
+
else if (params.session != null) patch.session = String(params.session);
|
|
125
|
+
if (params.body != null) patch.body = String(params.body);
|
|
126
|
+
if (params.status) patch.status = params.status;
|
|
127
|
+
if (params.disposition) patch.disposition = params.disposition === "crew" ? "crew" : "inline";
|
|
128
|
+
if (params.triaged) patch.triaged = true;
|
|
129
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
130
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
131
|
+
return updated;
|
|
132
|
+
}
|
|
133
|
+
case "triage": {
|
|
134
|
+
const patch = { triaged: true };
|
|
135
|
+
if (params.title != null) patch.title = String(params.title);
|
|
136
|
+
if (Array.isArray(params.labels) && params.labels.length) patch.labels = params.labels.map(String);
|
|
137
|
+
if (params.disposition) patch.disposition = params.disposition === "crew" ? "crew" : "inline";
|
|
138
|
+
const v = buildVerify(params);
|
|
139
|
+
if (v) patch.verify = v;
|
|
140
|
+
if (params.body != null) patch.body = String(params.body);
|
|
141
|
+
patch.status = params.backlog ? "backlog" : "ready";
|
|
142
|
+
const updated = updateIssue(root, String(params.id), patch);
|
|
143
|
+
if (!updated) throw new Error(`Issue not found: ${params.id}`);
|
|
144
|
+
return updated;
|
|
145
|
+
}
|
|
146
|
+
default:
|
|
147
|
+
throw new Error(`issue rpc: unknown op "${op}"`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { issueRpc };
|
|
@@ -2791,7 +2791,7 @@ async function registerMachineService(server, machineId, metadata, daemonState,
|
|
|
2791
2791
|
const tunnels = handlers.tunnels;
|
|
2792
2792
|
if (!tunnels) throw new Error("Tunnel management not available");
|
|
2793
2793
|
if (tunnels.has(params.name)) throw new Error(`Tunnel '${params.name}' already running`);
|
|
2794
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
2794
|
+
const { FrpcTunnel } = await import('./frpc-BDZgTsi8.mjs');
|
|
2795
2795
|
const tunnel = new FrpcTunnel({
|
|
2796
2796
|
name: params.name,
|
|
2797
2797
|
ports: params.ports,
|
|
@@ -3238,7 +3238,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3238
3238
|
}
|
|
3239
3239
|
const deps = buildSessionDeps(rpc, { cwd, ownerEmail: owner });
|
|
3240
3240
|
const sender = { name: context?.user?.email || context?.user?.id || "user", kind: "user", verified: true };
|
|
3241
|
-
const { toolsForRole } = await import('./sideband-
|
|
3241
|
+
const { toolsForRole } = await import('./sideband-BYiyQgZR.mjs');
|
|
3242
3242
|
const r2 = await runWiseAgent({ message: params.message, sender, config: { tools: toolsForRole(role2) }, deps, transport, model: resolved.model });
|
|
3243
3243
|
return fmt(r2);
|
|
3244
3244
|
}
|
|
@@ -3337,7 +3337,7 @@ QUESTION: ${params.question || "Summarize this concisely."}` }
|
|
|
3337
3337
|
if (r.error || !r.sender) return { error: r.error || "unauthorized" };
|
|
3338
3338
|
const callId = "call_" + Math.random().toString(16).slice(2, 12);
|
|
3339
3339
|
const rendered = renderMessage(c, { sender: r.sender, body: { message: kwargs.message }, callId });
|
|
3340
|
-
const { queryCore } = await import('./commands-
|
|
3340
|
+
const { queryCore } = await import('./commands-BssfhM-2.mjs');
|
|
3341
3341
|
const timeout = c.reply?.timeout_sec || 120;
|
|
3342
3342
|
let result;
|
|
3343
3343
|
try {
|
|
@@ -4679,6 +4679,17 @@ function createSessionStore(server, sessionId, initialMetadata, initialAgentStat
|
|
|
4679
4679
|
if (!callbacks.onBash) throw new Error("bash not supported");
|
|
4680
4680
|
return await callbacks.onBash(command, cwd, timeout);
|
|
4681
4681
|
},
|
|
4682
|
+
// Native issue/workflow store ops (in-process; no subprocess). Owner-gated like bash/readFile.
|
|
4683
|
+
issue: async (params, context) => {
|
|
4684
|
+
authorizeRequest(context, metadata.sharing, "admin");
|
|
4685
|
+
if (!callbacks.onIssue) throw new Error("issue not supported");
|
|
4686
|
+
return await callbacks.onIssue(params);
|
|
4687
|
+
},
|
|
4688
|
+
workflow: async (params, context) => {
|
|
4689
|
+
authorizeRequest(context, metadata.sharing, "admin");
|
|
4690
|
+
if (!callbacks.onWorkflow) throw new Error("workflow not supported");
|
|
4691
|
+
return await callbacks.onWorkflow(params);
|
|
4692
|
+
},
|
|
4682
4693
|
ripgrep: async (args, cwd, context) => {
|
|
4683
4694
|
authorizeRequest(context, metadata.sharing, "admin");
|
|
4684
4695
|
if (!callbacks.onRipgrep) throw new Error("ripgrep not supported");
|
|
@@ -11896,7 +11907,7 @@ async function startDaemon(options) {
|
|
|
11896
11907
|
saveExposedTunnels(list);
|
|
11897
11908
|
}
|
|
11898
11909
|
async function createExposedTunnel(spec) {
|
|
11899
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
11910
|
+
const { FrpcTunnel } = await import('./frpc-BDZgTsi8.mjs');
|
|
11900
11911
|
const tunnel = new FrpcTunnel({
|
|
11901
11912
|
name: spec.name,
|
|
11902
11913
|
ports: spec.ports,
|
|
@@ -11916,7 +11927,7 @@ async function startDaemon(options) {
|
|
|
11916
11927
|
return tunnel;
|
|
11917
11928
|
}
|
|
11918
11929
|
const tunnelRecreateState = /* @__PURE__ */ new Map();
|
|
11919
|
-
const { ServeManager } = await import('./serveManager-
|
|
11930
|
+
const { ServeManager } = await import('./serveManager-B_Bj1AF4.mjs');
|
|
11920
11931
|
const serveManager = new ServeManager(SVAMP_HOME, (msg) => logger.log(`[SERVE] ${msg}`), hyphaServerUrl);
|
|
11921
11932
|
ensureAutoInstalledSkills(logger).catch(() => {
|
|
11922
11933
|
});
|
|
@@ -13715,6 +13726,14 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
13715
13726
|
});
|
|
13716
13727
|
});
|
|
13717
13728
|
},
|
|
13729
|
+
onIssue: async (params) => {
|
|
13730
|
+
const { issueRpc } = await import('./rpc-gCEvLUNu.mjs');
|
|
13731
|
+
return issueRpc(params?.cwd || directory, params || {});
|
|
13732
|
+
},
|
|
13733
|
+
onWorkflow: async (params) => {
|
|
13734
|
+
const { workflowRpc } = await import('./rpc-CQTahguB.mjs');
|
|
13735
|
+
return workflowRpc(params?.cwd || directory, params || {});
|
|
13736
|
+
},
|
|
13718
13737
|
onRipgrep: async (args, cwd) => {
|
|
13719
13738
|
const { exec } = await import('child_process');
|
|
13720
13739
|
const rgCwd = cwd || directory;
|
|
@@ -14226,6 +14245,14 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
|
|
|
14226
14245
|
});
|
|
14227
14246
|
});
|
|
14228
14247
|
},
|
|
14248
|
+
onIssue: async (params) => {
|
|
14249
|
+
const { issueRpc } = await import('./rpc-gCEvLUNu.mjs');
|
|
14250
|
+
return issueRpc(params?.cwd || directory, params || {});
|
|
14251
|
+
},
|
|
14252
|
+
onWorkflow: async (params) => {
|
|
14253
|
+
const { workflowRpc } = await import('./rpc-CQTahguB.mjs');
|
|
14254
|
+
return workflowRpc(params?.cwd || directory, params || {});
|
|
14255
|
+
},
|
|
14229
14256
|
onRipgrep: async (args, cwd) => {
|
|
14230
14257
|
const { exec } = await import('child_process');
|
|
14231
14258
|
const rgCwd = cwd || directory;
|
|
@@ -15536,4 +15563,4 @@ var run = /*#__PURE__*/Object.freeze({
|
|
|
15536
15563
|
writeStopMarker: writeStopMarker
|
|
15537
15564
|
});
|
|
15538
15565
|
|
|
15539
|
-
export { describeMisconfiguration as $,
|
|
15566
|
+
export { describeMisconfiguration as $, buildMachineInstructions as A, machineToolsForRole as B, buildMachineTools as C, parseFrontmatter as D, getSkillsServer as E, getSkillsWorkspaceName as F, getSkillsCollectionName as G, fetchWithTimeout as H, searchSkills as I, SKILLS_DIR as J, getSkillInfo as K, downloadSkillFile as L, listSkillFiles as M, resolveModel as N, formatHandle as O, normalizeAllowedUser as P, loadSecurityContextConfig as Q, RoutineStore as R, ServeAuth as S, resolveSecurityContext as T, buildSecurityContextFromFlags as U, mergeSecurityContexts as V, buildSessionShareUrl as W, computeOutboundHop as X, buildMachineShareUrl as Y, parseHandle as Z, handleMatchesMetadata as _, createSessionStore as a, buildMachineDeps as a0, composeSessionId as a1, generateFriendlyName as a2, generateHookSettings as a3, projectInfo as a4, DefaultTransport$1 as a5, acpBackend as a6, acpAgentConfig as a7, codexMcpBackend as a8, GeminiTransport$1 as a9, claudeAuth as aa, instanceConfig as ab, api as ac, run as ad, stopDaemon as b, connectToHypha as c, daemonStatus as d, clearStopMarker as e, stopMarkerExists as f, getHyphaServerUrl$1 as g, getFrpsSubdomainHost as h, getFrpsServerPort as i, getFrpsServerAddr as j, getHyphaServerUrl as k, hasCookieToken as l, resolveProjectRoot as m, getIssue as n, addComment as o, addIssue as p, listIssues as q, registerMachineService as r, startDaemon as s, searchIssues as t, updateIssue as u, summarize as v, RoutineRunner as w, shortId as x, READ_ONLY_TOOLS as y, loadMachineContext as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as composeSessionId, a2 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a3 as generateHookSettings } from './run-
|
|
1
|
+
import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a1 as composeSessionId, a2 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a3 as generateHookSettings } from './run-Buov6wz-.mjs';
|
|
2
2
|
import os from 'node:os';
|
|
3
3
|
import { resolve, join } from 'node:path';
|
|
4
4
|
import { existsSync, readFileSync, watch } from 'node:fs';
|
|
@@ -54,7 +54,7 @@ async function handleServeCommand() {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
async function serveAdd(args, machineId) {
|
|
57
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
57
|
+
const { connectAndGetMachine } = await import('./commands-BssfhM-2.mjs');
|
|
58
58
|
const pos = positionalArgs(args);
|
|
59
59
|
const name = pos[0];
|
|
60
60
|
if (!name) {
|
|
@@ -93,7 +93,7 @@ async function serveAdd(args, machineId) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
async function serveApply(args, machineId) {
|
|
96
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
96
|
+
const { connectAndGetMachine } = await import('./commands-BssfhM-2.mjs');
|
|
97
97
|
const fs = await import('fs');
|
|
98
98
|
const yaml = await import('yaml');
|
|
99
99
|
const file = positionalArgs(args)[0];
|
|
@@ -182,7 +182,7 @@ async function serveApply(args, machineId) {
|
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
async function serveRemove(args, machineId) {
|
|
185
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
185
|
+
const { connectAndGetMachine } = await import('./commands-BssfhM-2.mjs');
|
|
186
186
|
const pos = positionalArgs(args);
|
|
187
187
|
const name = pos[0];
|
|
188
188
|
if (!name) {
|
|
@@ -202,7 +202,7 @@ async function serveRemove(args, machineId) {
|
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
async function serveList(args, machineId) {
|
|
205
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
205
|
+
const { connectAndGetMachine } = await import('./commands-BssfhM-2.mjs');
|
|
206
206
|
const all = hasFlag(args, "--all", "-a");
|
|
207
207
|
const json = hasFlag(args, "--json");
|
|
208
208
|
const sessionId = getFlag(args, "--session");
|
|
@@ -235,7 +235,7 @@ async function serveList(args, machineId) {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
async function serveInfo(machineId) {
|
|
238
|
-
const { connectAndGetMachine } = await import('./commands-
|
|
238
|
+
const { connectAndGetMachine } = await import('./commands-BssfhM-2.mjs');
|
|
239
239
|
const { machine, server } = await connectAndGetMachine(machineId);
|
|
240
240
|
try {
|
|
241
241
|
const info = await machine.serveInfo();
|
|
@@ -4,7 +4,7 @@ import * as fs from 'fs';
|
|
|
4
4
|
import * as http from 'http';
|
|
5
5
|
import * as net from 'net';
|
|
6
6
|
import * as path from 'path';
|
|
7
|
-
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-
|
|
7
|
+
import { k as getHyphaServerUrl, S as ServeAuth, l as hasCookieToken } from './run-Buov6wz-.mjs';
|
|
8
8
|
import 'os';
|
|
9
9
|
import 'fs/promises';
|
|
10
10
|
import 'url';
|
|
@@ -733,7 +733,7 @@ class ServeManager {
|
|
|
733
733
|
const mount = this.mounts.get(mountName);
|
|
734
734
|
const subdomainOverride = mount?.access === "link" && mount.linkToken ? /* @__PURE__ */ new Map([[this.port, buildLinkSubdomain(subdomainSafe, mount.linkToken)]]) : void 0;
|
|
735
735
|
try {
|
|
736
|
-
const { FrpcTunnel } = await import('./frpc-
|
|
736
|
+
const { FrpcTunnel } = await import('./frpc-BDZgTsi8.mjs');
|
|
737
737
|
let tunnel;
|
|
738
738
|
tunnel = new FrpcTunnel({
|
|
739
739
|
name: tunnelName,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { y as READ_ONLY_TOOLS, z as loadMachineContext, A as buildMachineInstructions, B as machineToolsForRole, C as buildMachineTools } from './run-Buov6wz-.mjs';
|
|
2
2
|
import 'node:child_process';
|
|
3
3
|
import 'os';
|
|
4
4
|
import 'fs/promises';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { existsSync, unlinkSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { parse, stringify } from 'yaml';
|
|
4
|
+
|
|
5
|
+
function workflowsDir(projectRoot) {
|
|
6
|
+
return join(projectRoot, ".svamp", "workflows");
|
|
7
|
+
}
|
|
8
|
+
function workflowPath(projectRoot, name) {
|
|
9
|
+
return join(workflowsDir(projectRoot), `${name}.yaml`);
|
|
10
|
+
}
|
|
11
|
+
function parseWorkflow(content) {
|
|
12
|
+
try {
|
|
13
|
+
const o = parse(content);
|
|
14
|
+
if (!o || typeof o !== "object" || !o.name) return null;
|
|
15
|
+
const jobs = Array.isArray(o.jobs) ? o.jobs.map((j) => ({ run: String(j?.run ?? "") })).filter((j) => j.run) : [];
|
|
16
|
+
return { name: String(o.name), on: o.on && typeof o.on === "object" ? o.on : void 0, jobs, session: o.session ?? null };
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function serializeWorkflow(wf) {
|
|
22
|
+
const clean = { name: wf.name };
|
|
23
|
+
if (wf.session) clean.session = wf.session;
|
|
24
|
+
if (wf.on && Object.keys(wf.on).length) clean.on = wf.on;
|
|
25
|
+
clean.jobs = wf.jobs.map((j) => ({ run: j.run }));
|
|
26
|
+
return stringify(clean);
|
|
27
|
+
}
|
|
28
|
+
function listWorkflows(projectRoot) {
|
|
29
|
+
const dir = workflowsDir(projectRoot);
|
|
30
|
+
if (!existsSync(dir)) return [];
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const name of readdirSync(dir)) {
|
|
33
|
+
if (!name.endsWith(".yaml") && !name.endsWith(".yml")) continue;
|
|
34
|
+
try {
|
|
35
|
+
const wf = parseWorkflow(readFileSync(join(dir, name), "utf-8"));
|
|
36
|
+
if (wf) out.push(wf);
|
|
37
|
+
} catch {
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
41
|
+
}
|
|
42
|
+
function getWorkflow(projectRoot, name) {
|
|
43
|
+
const p = workflowPath(projectRoot, name);
|
|
44
|
+
if (!existsSync(p)) return null;
|
|
45
|
+
try {
|
|
46
|
+
return parseWorkflow(readFileSync(p, "utf-8"));
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function rawWorkflow(projectRoot, name) {
|
|
52
|
+
const p = workflowPath(projectRoot, name);
|
|
53
|
+
return existsSync(p) ? readFileSync(p, "utf-8") : null;
|
|
54
|
+
}
|
|
55
|
+
function saveWorkflow(projectRoot, wf) {
|
|
56
|
+
const dir = workflowsDir(projectRoot);
|
|
57
|
+
mkdirSync(dir, { recursive: true });
|
|
58
|
+
const path = workflowPath(projectRoot, wf.name);
|
|
59
|
+
const tmp = `${path}.tmp-${process.pid}`;
|
|
60
|
+
writeFileSync(tmp, serializeWorkflow(wf));
|
|
61
|
+
renameSync(tmp, path);
|
|
62
|
+
}
|
|
63
|
+
function removeWorkflow(projectRoot, name) {
|
|
64
|
+
const p = workflowPath(projectRoot, name);
|
|
65
|
+
if (!existsSync(p)) return false;
|
|
66
|
+
try {
|
|
67
|
+
unlinkSync(p);
|
|
68
|
+
return true;
|
|
69
|
+
} catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { rawWorkflow as a, getWorkflow as g, listWorkflows as l, removeWorkflow as r, saveWorkflow as s };
|