@robzilla1738/agentswarm 0.2.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/bin/swarm.js +10 -0
  4. package/dist/agent.js +211 -0
  5. package/dist/cli.js +667 -0
  6. package/dist/config.js +289 -0
  7. package/dist/control.js +96 -0
  8. package/dist/deepseek.js +321 -0
  9. package/dist/executor.js +988 -0
  10. package/dist/hub.js +553 -0
  11. package/dist/journal.js +152 -0
  12. package/dist/prompts.js +232 -0
  13. package/dist/providers.js +151 -0
  14. package/dist/run.js +309 -0
  15. package/dist/sandbox.js +505 -0
  16. package/dist/state.js +230 -0
  17. package/dist/terminal.js +298 -0
  18. package/dist/tools.js +491 -0
  19. package/dist/types.js +26 -0
  20. package/dist/util.js +209 -0
  21. package/dist/webtools.js +205 -0
  22. package/package.json +63 -0
  23. package/ui/out/404/index.html +1 -0
  24. package/ui/out/404.html +1 -0
  25. package/ui/out/_next/static/chunks/255-2aa030c9ba2867e3.js +1 -0
  26. package/ui/out/_next/static/chunks/383-289a866b246b41cc.js +1 -0
  27. package/ui/out/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
  28. package/ui/out/_next/static/chunks/619-ba102abea3e3d0e4.js +1 -0
  29. package/ui/out/_next/static/chunks/677-b37981ba0eca75b2.js +1 -0
  30. package/ui/out/_next/static/chunks/app/_not-found/page-2d0982e372f7be41.js +1 -0
  31. package/ui/out/_next/static/chunks/app/layout-37ad32c5fdb26f29.js +1 -0
  32. package/ui/out/_next/static/chunks/app/page-0c9f35bd4aa8e370.js +1 -0
  33. package/ui/out/_next/static/chunks/app/run/page-13dc41a57e34da71.js +1 -0
  34. package/ui/out/_next/static/chunks/app/settings/page-a1763be7f6de888c.js +1 -0
  35. package/ui/out/_next/static/chunks/framework-2c534e0e662575a2.js +1 -0
  36. package/ui/out/_next/static/chunks/main-app-889ed884f8bc78e3.js +1 -0
  37. package/ui/out/_next/static/chunks/main-eb90ae3b35d2fd16.js +1 -0
  38. package/ui/out/_next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
  39. package/ui/out/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
  40. package/ui/out/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  41. package/ui/out/_next/static/chunks/webpack-38639c05c96dbeca.js +1 -0
  42. package/ui/out/_next/static/css/82edaa7a5942f894.css +3 -0
  43. package/ui/out/_next/static/eiQeDU9uBHNsBj0CFkp8M/_buildManifest.js +1 -0
  44. package/ui/out/_next/static/eiQeDU9uBHNsBj0CFkp8M/_ssgManifest.js +1 -0
  45. package/ui/out/_next/static/media/0aa834ed78bf6d07-s.woff2 +0 -0
  46. package/ui/out/_next/static/media/438aa629764e75f3-s.woff2 +0 -0
  47. package/ui/out/_next/static/media/4c9affa5bc8f420e-s.p.woff2 +0 -0
  48. package/ui/out/_next/static/media/51251f8b9793cdb3-s.woff2 +0 -0
  49. package/ui/out/_next/static/media/67957d42bae0796d-s.woff2 +0 -0
  50. package/ui/out/_next/static/media/875ae681bfde4580-s.woff2 +0 -0
  51. package/ui/out/_next/static/media/886030b0b59bc5a7-s.woff2 +0 -0
  52. package/ui/out/_next/static/media/939c4f875ee75fbb-s.woff2 +0 -0
  53. package/ui/out/_next/static/media/bb3ef058b751a6ad-s.p.woff2 +0 -0
  54. package/ui/out/_next/static/media/cc978ac5ee68c2b6-s.woff2 +0 -0
  55. package/ui/out/_next/static/media/e857b654a2caa584-s.woff2 +0 -0
  56. package/ui/out/_next/static/media/f911b923c6adde36-s.woff2 +0 -0
  57. package/ui/out/icon.png +0 -0
  58. package/ui/out/index.html +1 -0
  59. package/ui/out/index.txt +22 -0
  60. package/ui/out/run/index.html +1 -0
  61. package/ui/out/run/index.txt +22 -0
  62. package/ui/out/settings/index.html +1 -0
  63. package/ui/out/settings/index.txt +22 -0
  64. package/ui/out/swarm-mark.png +0 -0
package/dist/run.js ADDED
@@ -0,0 +1,309 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.optionsFromConfig = optionsFromConfig;
37
+ exports.createRun = createRun;
38
+ exports.metaPath = metaPath;
39
+ exports.loadMeta = loadMeta;
40
+ exports.executeRun = executeRun;
41
+ exports.listRuns = listRuns;
42
+ exports.deleteRun = deleteRun;
43
+ exports.resumeInfo = resumeInfo;
44
+ exports.launchDetached = launchDetached;
45
+ exports.loadRunState = loadRunState;
46
+ exports.pidPath = pidPath;
47
+ exports.writePid = writePid;
48
+ exports.clearPid = clearPid;
49
+ exports.readPid = readPid;
50
+ exports.isRunLive = isRunLive;
51
+ const child_process_1 = require("child_process");
52
+ const fs = __importStar(require("fs"));
53
+ const path = __importStar(require("path"));
54
+ const config_1 = require("./config");
55
+ const executor_1 = require("./executor");
56
+ const journal_1 = require("./journal");
57
+ const sandbox_1 = require("./sandbox");
58
+ const state_1 = require("./state");
59
+ const util_1 = require("./util");
60
+ function optionsFromConfig(cfg, overrides = {}) {
61
+ return {
62
+ model: cfg.model,
63
+ conductorModel: cfg.conductorModel,
64
+ maxWorkers: cfg.maxWorkers,
65
+ maxStepsPerTask: cfg.maxStepsPerTask,
66
+ maxTasks: cfg.maxTasks,
67
+ maxTokens: cfg.maxTokensPerRun,
68
+ verification: cfg.verification,
69
+ thinking: cfg.thinking,
70
+ reasoningEffort: cfg.reasoningEffort,
71
+ safeMode: cfg.safeMode,
72
+ // Resolved at launch so the run is reproducible across resume even if
73
+ // the operator later changes the default.
74
+ sandboxRuntime: (0, sandbox_1.resolveSandboxKind)(cfg),
75
+ ...overrides,
76
+ };
77
+ }
78
+ function createRun(input) {
79
+ const id = (0, util_1.rid)("run");
80
+ const dir = (0, config_1.runDir)(id);
81
+ let cwd = path.resolve(input.cwd);
82
+ if (input.sandbox) {
83
+ // Isolated working directory inside the run folder.
84
+ cwd = path.join(dir, "workspace");
85
+ (0, util_1.ensureDir)(cwd);
86
+ }
87
+ const meta = {
88
+ id,
89
+ mission: input.mission,
90
+ createdAt: Date.now(),
91
+ cwd,
92
+ sandbox: input.sandbox,
93
+ options: input.options,
94
+ };
95
+ (0, util_1.ensureDir)(dir);
96
+ (0, util_1.ensureDir)(path.join(dir, "artifacts"));
97
+ (0, util_1.writeJson)(path.join(dir, "meta.json"), meta);
98
+ return meta;
99
+ }
100
+ function metaPath(id) {
101
+ return path.join((0, config_1.runDir)(id), "meta.json");
102
+ }
103
+ function loadMeta(id) {
104
+ try {
105
+ return JSON.parse(fs.readFileSync(metaPath(id), "utf8"));
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ /** Execute a run to completion in this process. */
112
+ async function executeRun(cfg, meta, journal) {
113
+ const ex = new executor_1.Executor(cfg, meta, journal);
114
+ await ex.run();
115
+ return ex;
116
+ }
117
+ /**
118
+ * Re-reducing every journal on every dashboard poll gets expensive once runs
119
+ * accumulate; summaries are pure functions of the journal file, so cache them
120
+ * keyed on (size, mtime).
121
+ */
122
+ const summaryCache = new Map();
123
+ /**
124
+ * Live runs additionally tail their journal incrementally: a multi-hour run's
125
+ * growing events.jsonl costs O(new bytes) per poll instead of a full re-parse.
126
+ */
127
+ const liveCache = new Map();
128
+ const TERMINAL_STATUSES = ["done", "failed", "cancelled"];
129
+ /** Grace before a silent, pid-less run is presumed dead (engine startup, fs lag). */
130
+ const STALE_AFTER_MS = 20_000;
131
+ /**
132
+ * A run whose engine process vanished without writing a terminal status
133
+ * (kill -9, reboot) would otherwise show "running" forever. Presentation-level
134
+ * only — the journal stays untouched.
135
+ */
136
+ function applyLiveness(s) {
137
+ if (s.pid || TERMINAL_STATUSES.includes(s.status))
138
+ return s;
139
+ const lastBeat = s.heartbeatAt || s.updatedAt || s.createdAt;
140
+ if (Date.now() - lastBeat > STALE_AFTER_MS) {
141
+ s.status = "failed";
142
+ s.statusReason = "interrupted — the engine process is no longer running";
143
+ }
144
+ return s;
145
+ }
146
+ function listRuns(pricing) {
147
+ let ids;
148
+ try {
149
+ ids = fs.readdirSync((0, config_1.runsDir)()).filter((d) => d.startsWith("run_"));
150
+ }
151
+ catch {
152
+ return [];
153
+ }
154
+ const out = [];
155
+ for (const id of ids) {
156
+ const meta = loadMeta(id);
157
+ if (!meta)
158
+ continue;
159
+ let stat = null;
160
+ try {
161
+ stat = fs.statSync((0, journal_1.eventsFile)((0, config_1.runDir)(id)));
162
+ }
163
+ catch {
164
+ /* no events yet */
165
+ }
166
+ const cached = summaryCache.get(id);
167
+ let pure;
168
+ if (cached && stat && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) {
169
+ pure = cached.summary;
170
+ }
171
+ else {
172
+ let live = liveCache.get(id);
173
+ if (!live) {
174
+ live = { state: new state_1.RunState(pricing), tail: { offset: 0, carry: "" } };
175
+ liveCache.set(id, live);
176
+ }
177
+ for (const ev of (0, journal_1.readNewEvents)((0, journal_1.eventsFile)((0, config_1.runDir)(id)), live.tail))
178
+ live.state.apply(ev);
179
+ if (!live.state.meta)
180
+ live.state.meta = meta;
181
+ pure = live.state.summary();
182
+ pure.id = id;
183
+ pure.mission = meta.mission;
184
+ pure.model = meta.options.model;
185
+ pure.createdAt = meta.createdAt;
186
+ if (stat)
187
+ summaryCache.set(id, { size: stat.size, mtimeMs: stat.mtimeMs, summary: pure });
188
+ // Terminal runs never change again — the frozen summary suffices.
189
+ if (TERMINAL_STATUSES.includes(pure.status))
190
+ liveCache.delete(id);
191
+ }
192
+ const s = { ...pure, tasks: { ...pure.tasks } };
193
+ s.pid = readPid(id);
194
+ out.push(applyLiveness(s));
195
+ }
196
+ out.sort((a, b) => b.createdAt - a.createdAt);
197
+ return out;
198
+ }
199
+ /** Permanently remove a run's directory (journal, artifacts, workspace). */
200
+ function deleteRun(id) {
201
+ if (isRunLive(id))
202
+ throw new Error("run is live — stop it before deleting");
203
+ // A just-launched engine takes a moment to write its pid file; deleting in
204
+ // that window would yank the directory out from under it. Refuse while the
205
+ // run is non-terminal and fresh enough that the engine may still appear.
206
+ const evs = (0, journal_1.readEvents)((0, config_1.runDir)(id));
207
+ const lastStatus = [...evs].reverse().find((e) => e.type === "run.status");
208
+ const status = String(lastStatus?.status ?? "planning");
209
+ if (!TERMINAL_STATUSES.includes(status)) {
210
+ const lastT = evs.length ? evs[evs.length - 1].t : loadMeta(id)?.createdAt ?? 0;
211
+ if (Date.now() - lastT <= STALE_AFTER_MS) {
212
+ throw new Error("run is still starting — stop it or wait a moment");
213
+ }
214
+ }
215
+ fs.rmSync((0, config_1.runDir)(id), { recursive: true, force: true });
216
+ summaryCache.delete(id);
217
+ liveCache.delete(id);
218
+ }
219
+ /**
220
+ * Whether an interrupted run can be resumed: it must exist, not be live, and
221
+ * its journal must not have reached a terminal status. (A run the liveness
222
+ * layer *presents* as failed/interrupted still has a non-terminal journal.)
223
+ */
224
+ function resumeInfo(id) {
225
+ const meta = loadMeta(id);
226
+ if (!meta)
227
+ return { resumable: false, reason: "run not found" };
228
+ if (isRunLive(id))
229
+ return { resumable: false, reason: "run is already running" };
230
+ const evs = (0, journal_1.readEvents)((0, config_1.runDir)(id));
231
+ if (!evs.length)
232
+ return { resumable: false, reason: "run never started — launch it instead" };
233
+ const last = [...evs].reverse().find((e) => e.type === "run.status");
234
+ const status = String(last?.status ?? "planning");
235
+ if (TERMINAL_STATUSES.includes(status)) {
236
+ return { resumable: false, reason: `run already ended (${status})` };
237
+ }
238
+ return { resumable: true };
239
+ }
240
+ /** Spawn the engine for a run as a detached background process. */
241
+ function launchDetached(id, binPath, resume = false) {
242
+ let out = "ignore";
243
+ try {
244
+ out = fs.openSync(path.join((0, config_1.runDir)(id), "exec.log"), "a");
245
+ }
246
+ catch {
247
+ /* log is best-effort */
248
+ }
249
+ const child = (0, child_process_1.spawn)(process.execPath, [binPath, "_exec", id, ...(resume ? ["--resume"] : [])], {
250
+ detached: true,
251
+ stdio: ["ignore", out, out],
252
+ env: process.env,
253
+ });
254
+ child.unref();
255
+ if (typeof out === "number") {
256
+ try {
257
+ fs.closeSync(out);
258
+ }
259
+ catch {
260
+ /* child holds its own descriptor */
261
+ }
262
+ }
263
+ }
264
+ function loadRunState(id, pricing) {
265
+ const meta = loadMeta(id);
266
+ if (!meta)
267
+ return null;
268
+ const state = new state_1.RunState(pricing);
269
+ for (const ev of (0, journal_1.readEvents)((0, config_1.runDir)(id)))
270
+ state.apply(ev);
271
+ if (!state.meta)
272
+ state.meta = meta;
273
+ return state;
274
+ }
275
+ // ---------- pid tracking (for the hub to know what's live) ----------
276
+ function pidPath(id) {
277
+ return path.join((0, config_1.runDir)(id), "run.pid");
278
+ }
279
+ function writePid(id) {
280
+ try {
281
+ fs.writeFileSync(pidPath(id), String(process.pid), "utf8");
282
+ }
283
+ catch {
284
+ /* best effort */
285
+ }
286
+ }
287
+ function clearPid(id) {
288
+ try {
289
+ fs.unlinkSync(pidPath(id));
290
+ }
291
+ catch {
292
+ /* gone */
293
+ }
294
+ }
295
+ function readPid(id) {
296
+ try {
297
+ const pid = Number(fs.readFileSync(pidPath(id), "utf8").trim());
298
+ if (!pid)
299
+ return null;
300
+ process.kill(pid, 0); // throws if not alive
301
+ return pid;
302
+ }
303
+ catch {
304
+ return null;
305
+ }
306
+ }
307
+ function isRunLive(id) {
308
+ return readPid(id) !== null;
309
+ }