svamp-cli 0.2.174 → 0.2.176

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.
Files changed (26) hide show
  1. package/dist/{agentCommands-XAGMtjRQ.mjs → agentCommands-kchQlyIS.mjs} +5 -5
  2. package/dist/{auth-fEMoSUUD.mjs → auth-oH2upjHc.mjs} +1 -1
  3. package/dist/cli.mjs +61 -61
  4. package/dist/{commands-7wZGSXe5.mjs → commands-9LT5p45A.mjs} +2 -2
  5. package/dist/{commands-BVyi7762.mjs → commands-CXtkDntj.mjs} +2 -2
  6. package/dist/{commands-Di_HYoeZ.mjs → commands-CbrJ16x7.mjs} +5 -5
  7. package/dist/{commands-CPHMhYnp.mjs → commands-Cu6nPOsD.mjs} +1 -1
  8. package/dist/{commands-3mxZi6dQ.mjs → commands-DBi7fxGX.mjs} +2 -2
  9. package/dist/{commands-NdHufk_2.mjs → commands-DGkX7Kcr.mjs} +1 -1
  10. package/dist/{commands-B3Uk_kN9.mjs → commands-DHbv5qMP.mjs} +22 -84
  11. package/dist/{commands-BaGfFhwa.mjs → commands-USG2Z4XP.mjs} +1 -1
  12. package/dist/{fleet-B2GyUSYJ.mjs → fleet-BcS8xNkk.mjs} +1 -1
  13. package/dist/{frpc-BZmO_6PK.mjs → frpc-Bm7BrLan.mjs} +1 -1
  14. package/dist/{headlessCli-Yeuekh99.mjs → headlessCli-B4CVNI7S.mjs} +2 -2
  15. package/dist/index.mjs +1 -1
  16. package/dist/{package-CmQGdoJz.mjs → package-DndVS0ln.mjs} +2 -2
  17. package/dist/rpc-BbaS0cLh.mjs +151 -0
  18. package/dist/rpc-DVNDMfl8.mjs +80 -0
  19. package/dist/{run-BROwnG-V.mjs → run-BmpyfykC.mjs} +52 -6
  20. package/dist/{run-BE4jYZdk.mjs → run-Cr1yt_tm.mjs} +1 -1
  21. package/dist/scheduler-BusuolPD.mjs +93 -0
  22. package/dist/{serveCommands-C1Lfx-NW.mjs → serveCommands-Crb8ENkv.mjs} +5 -5
  23. package/dist/{serveManager-BdjeAjgf.mjs → serveManager-DQByExEO.mjs} +2 -2
  24. package/dist/{sideband-CQDEJ2q2.mjs → sideband-B4L2zR2U.mjs} +1 -1
  25. package/dist/store-BPL__e4D.mjs +125 -0
  26. package/package.json +2 -2
@@ -1,8 +1,6 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { m as resolveProjectRoot } from './run-BROwnG-V.mjs';
3
- import { existsSync, unlinkSync, readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync } from 'node:fs';
4
- import { join } from 'node:path';
5
- import { parse, stringify } from 'yaml';
2
+ import { m as resolveProjectRoot } from './run-BmpyfykC.mjs';
3
+ import { w as workflowSteps, r as removeWorkflow, g as getWorkflow, l as listWorkflows, s as saveWorkflow, a as rawWorkflow } from './store-BPL__e4D.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);
@@ -113,8 +45,8 @@ function positional(args) {
113
45
  function describeOn(on) {
114
46
  if (!on) return "manual";
115
47
  const parts = [];
116
- if (on.schedule) parts.push(`schedule(${on.schedule})`);
117
- if (on.dispatch) parts.push("dispatch");
48
+ if (on.schedule?.length) parts.push(`schedule(${on.schedule.map((s) => s.cron).join(", ")})`);
49
+ if (on.workflow_dispatch) parts.push("workflow_dispatch");
118
50
  if (on.channel) parts.push(`channel(${on.channel})`);
119
51
  if (on.issue?.length) parts.push(`issue(${on.issue.join("/")})`);
120
52
  return parts.length ? parts.join(" ") : "manual";
@@ -133,16 +65,18 @@ async function workflowCommand(args) {
133
65
  process.exit(1);
134
66
  }
135
67
  const onKinds = allFlags(rest, "--on");
68
+ const crons = allFlags(rest, "--cron");
136
69
  const on = {};
137
- if (onKinds.includes("schedule") || flag(rest, "--cron")) on.schedule = flag(rest, "--cron") || "0 * * * *";
138
- if (onKinds.includes("dispatch")) on.dispatch = true;
70
+ if (onKinds.includes("schedule") || crons.length) on.schedule = (crons.length ? crons : ["0 * * * *"]).map((c) => ({ cron: c }));
71
+ if (onKinds.includes("dispatch") || onKinds.includes("workflow_dispatch")) on.workflow_dispatch = true;
139
72
  if (onKinds.includes("channel") || flag(rest, "--channel")) on.channel = flag(rest, "--channel") || "default";
140
73
  if (onKinds.includes("issue") || flag(rest, "--issue")) on.issue = (flag(rest, "--issue") || "ready").split(",").map((s) => s.trim()).filter(Boolean);
141
74
  const owner = flag(rest, "--session") || process.env.SVAMP_SESSION_ID || null;
142
- const wf = { name, on: Object.keys(on).length ? on : void 0, jobs: runs.map((r) => ({ run: r })), session: owner };
75
+ const wf = { name, on: Object.keys(on).length ? on : void 0, jobs: { run: { steps: runs.map((r) => ({ run: r })) } }, session: owner };
143
76
  saveWorkflow(root, wf);
77
+ const nSteps = workflowSteps(wf).length;
144
78
  if (json) console.log(JSON.stringify(wf));
145
- else console.log(`Saved workflow "${name}" (on: ${describeOn(wf.on)}, ${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"}).`);
79
+ else console.log(`Saved workflow "${name}" (on: ${describeOn(wf.on)}, ${nSteps} step${nSteps === 1 ? "" : "s"}).`);
146
80
  break;
147
81
  }
148
82
  case "list":
@@ -156,7 +90,10 @@ async function workflowCommand(args) {
156
90
  console.log("No workflows.");
157
91
  break;
158
92
  }
159
- for (const wf of all) console.log(`${wf.name} [${describeOn(wf.on)}] ${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"}`);
93
+ for (const wf of all) {
94
+ const n = workflowSteps(wf).length;
95
+ console.log(`${wf.name} [${describeOn(wf.on)}] ${n} step${n === 1 ? "" : "s"}`);
96
+ }
160
97
  break;
161
98
  }
162
99
  case "show": {
@@ -187,10 +124,11 @@ async function workflowCommand(args) {
187
124
  console.error(`Workflow not found: ${name}`);
188
125
  process.exit(1);
189
126
  }
190
- console.log(`\u25B6 running workflow "${wf.name}" (${wf.jobs.length} step${wf.jobs.length === 1 ? "" : "s"})`);
191
- for (let i = 0; i < wf.jobs.length; i++) {
192
- const step = wf.jobs[i];
193
- console.log(` [${i + 1}/${wf.jobs.length}] $ ${step.run}`);
127
+ const steps = workflowSteps(wf);
128
+ console.log(`\u25B6 running workflow "${wf.name}" (${steps.length} step${steps.length === 1 ? "" : "s"})`);
129
+ for (let i = 0; i < steps.length; i++) {
130
+ const step = steps[i];
131
+ console.log(` [${i + 1}/${steps.length}] $ ${step.run}`);
194
132
  const r = spawnSync("sh", ["-c", step.run], { cwd: root, stdio: "inherit" });
195
133
  if (r.status !== 0) {
196
134
  console.error(` \u2717 step ${i + 1} failed (exit ${r.status ?? "signal"}). Stopping.`);
@@ -1,7 +1,7 @@
1
1
  import os from 'os';
2
2
  import fs__default from 'fs';
3
3
  import { resolve, join, relative } from 'path';
4
- import { y as parseFrontmatter, z as getSkillsServer, A as getSkillsWorkspaceName, B as getSkillsCollectionName, C as fetchWithTimeout, D as searchSkills, E as SKILLS_DIR, F as getSkillInfo, G as downloadSkillFile, H as listSkillFiles } from './run-BROwnG-V.mjs';
4
+ import { E as parseFrontmatter, F as getSkillsServer, G as getSkillsWorkspaceName, H as getSkillsCollectionName, I as fetchWithTimeout, J as searchSkills, K as SKILLS_DIR, L as getSkillInfo, M as downloadSkillFile, N as listSkillFiles } from './run-BmpyfykC.mjs';
5
5
  import 'fs/promises';
6
6
  import 'url';
7
7
  import 'child_process';
@@ -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-BROwnG-V.mjs';
4
+ import { c as connectToHypha } from './run-BmpyfykC.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-BROwnG-V.mjs';
7
+ import { h as getFrpsSubdomainHost, i as getFrpsServerPort, j as getFrpsServerAddr } from './run-BmpyfykC.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-BROwnG-V.mjs';
2
- import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-CQDEJ2q2.mjs';
1
+ import { O as resolveModel, a0 as describeMisconfiguration, a1 as buildMachineDeps } from './run-BmpyfykC.mjs';
2
+ import { handleRealtimeEvent, initMachineVoiceSession } from './sideband-B4L2zR2U.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-BROwnG-V.mjs';
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-BmpyfykC.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.174";
2
+ var version = "0.2.176";
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-workflow-scheduler.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,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-BmpyfykC.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 };
@@ -0,0 +1,80 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { m as resolveProjectRoot } from './run-BmpyfykC.mjs';
3
+ import { g as getWorkflow, w as workflowSteps, r as removeWorkflow, s as saveWorkflow, a as rawWorkflow, l as listWorkflows } from './store-BPL__e4D.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
+ const crons = Array.isArray(params.cron) ? params.cron.map(String) : params.cron ? [String(params.cron)] : [];
39
+ if (crons.length) on.schedule = crons.map((c) => ({ cron: c }));
40
+ if (params.dispatch || params.workflow_dispatch) on.workflow_dispatch = true;
41
+ if (params.channel) on.channel = String(params.channel);
42
+ if (Array.isArray(params.issue) && params.issue.length) on.issue = params.issue.map(String);
43
+ const runs = Array.isArray(params.runs) ? params.runs.map(String).filter(Boolean) : [];
44
+ if (!params.name || !runs.length) throw new Error("workflow add: name and at least one run step required");
45
+ const wf = {
46
+ name: String(params.name),
47
+ on: Object.keys(on).length ? on : void 0,
48
+ jobs: { run: { steps: runs.map((r) => ({ run: r })) } },
49
+ session: params.session || null
50
+ };
51
+ saveWorkflow(root, wf);
52
+ return wf;
53
+ }
54
+ case "remove":
55
+ return { removed: removeWorkflow(root, String(params.name)) };
56
+ case "run": {
57
+ const wf = getWorkflow(root, String(params.name));
58
+ if (!wf) throw new Error(`Workflow not found: ${params.name}`);
59
+ const steps = workflowSteps(wf);
60
+ const out = [`\u25B6 running workflow "${wf.name}" (${steps.length} step${steps.length === 1 ? "" : "s"})`];
61
+ for (let i = 0; i < steps.length; i++) {
62
+ const step = steps[i];
63
+ out.push(` [${i + 1}/${steps.length}] $ ${step.run}`);
64
+ const r = spawnSync("sh", ["-c", step.run], { cwd: root, encoding: "utf-8", timeout: 12e4 });
65
+ if (r.stdout) out.push(r.stdout.trimEnd());
66
+ if (r.stderr) out.push(r.stderr.trimEnd());
67
+ if (r.status !== 0) {
68
+ out.push(` \u2717 step ${i + 1} failed (exit ${r.status ?? "signal"}). Stopping.`);
69
+ return { ok: false, output: out.join("\n") };
70
+ }
71
+ }
72
+ out.push(`\u2713 workflow "${wf.name}" completed.`);
73
+ return { ok: true, output: out.join("\n") };
74
+ }
75
+ default:
76
+ throw new Error(`workflow rpc: unknown op "${op}"`);
77
+ }
78
+ }
79
+
80
+ export { workflowRpc };
@@ -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-BZmO_6PK.mjs');
2794
+ const { FrpcTunnel } = await import('./frpc-Bm7BrLan.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-CQDEJ2q2.mjs');
3241
+ const { toolsForRole } = await import('./sideband-B4L2zR2U.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-NdHufk_2.mjs');
3340
+ const { queryCore } = await import('./commands-DGkX7Kcr.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-BZmO_6PK.mjs');
11910
+ const { FrpcTunnel } = await import('./frpc-Bm7BrLan.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-BdjeAjgf.mjs');
11930
+ const { ServeManager } = await import('./serveManager-DQByExEO.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-BbaS0cLh.mjs');
13731
+ return issueRpc(params?.cwd || directory, params || {});
13732
+ },
13733
+ onWorkflow: async (params) => {
13734
+ const { workflowRpc } = await import('./rpc-DVNDMfl8.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-BbaS0cLh.mjs');
14250
+ return issueRpc(params?.cwd || directory, params || {});
14251
+ },
14252
+ onWorkflow: async (params) => {
14253
+ const { workflowRpc } = await import('./rpc-DVNDMfl8.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;
@@ -14976,6 +15003,24 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
14976
15003
  const PING_TIMEOUT_MS = 15e3;
14977
15004
  const POST_RECONNECT_GRACE_MS = 2e4;
14978
15005
  const RECONNECT_JITTER_MS = 2500;
15006
+ const { WorkflowScheduler } = await import('./scheduler-BusuolPD.mjs');
15007
+ const workflowScheduler = new WorkflowScheduler({
15008
+ projectRoots: () => {
15009
+ const dirs = /* @__PURE__ */ new Set();
15010
+ for (const s of pidToTrackedSession.values()) {
15011
+ if (!s.stopped && s.directory) dirs.add(s.directory);
15012
+ }
15013
+ return [...dirs];
15014
+ },
15015
+ log: (m) => logger.log(m)
15016
+ });
15017
+ const workflowSchedulerInterval = setInterval(() => {
15018
+ try {
15019
+ workflowScheduler.tick(/* @__PURE__ */ new Date());
15020
+ } catch (e) {
15021
+ logger.log(`[workflow] scheduler tick error: ${e?.message || e}`);
15022
+ }
15023
+ }, 2e4);
14979
15024
  let heartbeatRunning = false;
14980
15025
  let lastReconnectAt = 0;
14981
15026
  let heartbeatCycle = 0;
@@ -15198,6 +15243,7 @@ ${capturedError}${buildClaudeErrorHint(capturedError)}`;
15198
15243
  const cleanup = async (source) => {
15199
15244
  logger.log(`Cleaning up (source: ${source})...`);
15200
15245
  clearInterval(heartbeatInterval);
15246
+ clearInterval(workflowSchedulerInterval);
15201
15247
  if (proxyTokenRefreshInterval) clearInterval(proxyTokenRefreshInterval);
15202
15248
  if (oauthRefreshInterval) clearInterval(oauthRefreshInterval);
15203
15249
  if (unhandledRejectionResetTimer) clearTimeout(unhandledRejectionResetTimer);
@@ -15536,4 +15582,4 @@ var run = /*#__PURE__*/Object.freeze({
15536
15582
  writeStopMarker: writeStopMarker
15537
15583
  });
15538
15584
 
15539
- export { describeMisconfiguration as $, getSkillsWorkspaceName as A, getSkillsCollectionName as B, fetchWithTimeout as C, searchSkills as D, SKILLS_DIR as E, getSkillInfo as F, downloadSkillFile as G, listSkillFiles as H, READ_ONLY_TOOLS as I, loadMachineContext as J, buildMachineInstructions as K, machineToolsForRole as L, buildMachineTools 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, searchIssues as n, listIssues as o, addComment as p, getIssue as q, registerMachineService as r, startDaemon as s, summarize as t, updateIssue as u, addIssue as v, RoutineRunner as w, shortId as x, parseFrontmatter as y, getSkillsServer as z };
15585
+ export { handleMatchesMetadata as $, loadMachineContext as A, buildMachineInstructions as B, machineToolsForRole as C, buildMachineTools as D, parseFrontmatter as E, getSkillsServer as F, getSkillsWorkspaceName as G, getSkillsCollectionName as H, fetchWithTimeout as I, searchSkills as J, SKILLS_DIR as K, getSkillInfo as L, downloadSkillFile as M, listSkillFiles as N, resolveModel as O, formatHandle as P, normalizeAllowedUser as Q, RoutineStore as R, ServeAuth as S, loadSecurityContextConfig as T, resolveSecurityContext as U, buildSecurityContextFromFlags as V, mergeSecurityContexts as W, buildSessionShareUrl as X, computeOutboundHop as Y, buildMachineShareUrl as Z, parseHandle as _, createSessionStore as a, describeMisconfiguration as a0, buildMachineDeps as a1, composeSessionId as a2, generateFriendlyName as a3, generateHookSettings as a4, projectInfo as a5, DefaultTransport$1 as a6, acpBackend as a7, acpAgentConfig as a8, codexMcpBackend as a9, GeminiTransport$1 as aa, claudeAuth as ab, instanceConfig as ac, api as ad, run as ae, 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, cronMatches as v, summarize as w, RoutineRunner as x, shortId as y, READ_ONLY_TOOLS 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-BROwnG-V.mjs';
1
+ import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import { a2 as composeSessionId, a3 as generateFriendlyName, c as connectToHypha, a as createSessionStore, r as registerMachineService, a4 as generateHookSettings } from './run-BmpyfykC.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';