@enderfga/claw-orchestrator 6.5.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/mcp-server.js +5 -3
- package/dist/bin/mcp-server.js.map +1 -1
- package/dist/src/autoloop/dispatcher.d.ts +37 -3
- package/dist/src/autoloop/dispatcher.js +171 -30
- package/dist/src/autoloop/dispatcher.js.map +1 -1
- package/dist/src/autoloop/messages.d.ts +19 -1
- package/dist/src/autoloop/messages.js +4 -0
- package/dist/src/autoloop/messages.js.map +1 -1
- package/dist/src/autoloop/runner.d.ts +57 -2
- package/dist/src/autoloop/runner.js +260 -26
- package/dist/src/autoloop/runner.js.map +1 -1
- package/dist/src/autoloop/types.d.ts +62 -2
- package/dist/src/autoloop/types.js +63 -0
- package/dist/src/autoloop/types.js.map +1 -1
- package/dist/src/embedded-server.d.ts +8 -0
- package/dist/src/embedded-server.js +65 -4
- package/dist/src/embedded-server.js.map +1 -1
- package/dist/src/index.d.ts +9 -7
- package/dist/src/index.js +120 -80
- package/dist/src/index.js.map +1 -1
- package/dist/src/kernel/engine.js +19 -14
- package/dist/src/kernel/engine.js.map +1 -1
- package/dist/src/session-manager.d.ts +6 -0
- package/dist/src/session-manager.js +246 -13
- package/dist/src/session-manager.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/SKILL.md +1 -1
- package/skills/references/autoloop.md +34 -3
- package/skills/references/multi-engine.md +1 -1
- package/skills/references/tools.md +23 -2
package/dist/src/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import { ENGINE_TYPES, } from './types.js';
|
|
|
16
16
|
import { councilWorkflow, fanoutWorkflow, solveWorkflow } from './kernel/templates/index.js';
|
|
17
17
|
import { readEvents as readKernelEvents } from './kernel/store.js';
|
|
18
18
|
import { resolveSecretRefs } from './kernel/secrets.js';
|
|
19
|
+
import { AUTOLOOP_TIMEOUT_SCHEMA, validateAutoloopTimeoutConfig } from './autoloop/types.js';
|
|
19
20
|
// ─── Standalone Export ───────────────────────────────────────────────────────
|
|
20
21
|
export { SessionManager } from './session-manager.js';
|
|
21
22
|
export { PersistentClaudeSession } from './persistent-session.js';
|
|
@@ -37,6 +38,22 @@ export { createConsoleLogger, nullLogger } from './logger.js';
|
|
|
37
38
|
export { CircuitBreaker } from './circuit-breaker.js';
|
|
38
39
|
export { InboxManager } from './inbox-manager.js';
|
|
39
40
|
export * from './types.js';
|
|
41
|
+
function isAgentToolResult(result) {
|
|
42
|
+
return (typeof result === 'object' &&
|
|
43
|
+
result !== null &&
|
|
44
|
+
'content' in result &&
|
|
45
|
+
Array.isArray(result.content) &&
|
|
46
|
+
'details' in result);
|
|
47
|
+
}
|
|
48
|
+
function normalizeToolResult(result) {
|
|
49
|
+
if (isAgentToolResult(result))
|
|
50
|
+
return result;
|
|
51
|
+
const text = JSON.stringify(result, (_key, value) => (typeof value === 'bigint' ? value.toString() : value), 2);
|
|
52
|
+
return {
|
|
53
|
+
content: [{ type: 'text', text: text ?? 'null' }],
|
|
54
|
+
details: result,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
40
57
|
const CUSTOM_ENGINE_SCHEMA = {
|
|
41
58
|
type: 'object',
|
|
42
59
|
description: 'Custom engine config (required when the corresponding engine is "custom").',
|
|
@@ -93,6 +110,12 @@ const plugin = {
|
|
|
93
110
|
description: 'Run Claude Code, Codex, Gemini, Cursor Agent and custom coding CLIs as one unified runtime — persistent sessions, multi-agent council, worktree isolation, multi-model proxy',
|
|
94
111
|
register(api) {
|
|
95
112
|
const rawConfig = (api.pluginConfig || {});
|
|
113
|
+
const registerTool = (definition) => {
|
|
114
|
+
api.registerTool({
|
|
115
|
+
...definition,
|
|
116
|
+
execute: async (toolCallId, params) => normalizeToolResult(await definition.execute(toolCallId, params)),
|
|
117
|
+
});
|
|
118
|
+
};
|
|
96
119
|
// ─── Lazy Init ────────────────────────────────────────────────────────
|
|
97
120
|
//
|
|
98
121
|
// Neither SessionManager nor EmbeddedServer is created at plugin load
|
|
@@ -165,7 +188,7 @@ const plugin = {
|
|
|
165
188
|
}
|
|
166
189
|
}
|
|
167
190
|
// ─── Tool: session_start ──────────────────────────────────────────────
|
|
168
|
-
|
|
191
|
+
registerTool({
|
|
169
192
|
name: 'session_start',
|
|
170
193
|
description: 'Start a persistent coding session. Supports multiple engines: claude (default) for Claude Code CLI, codex for OpenAI Codex CLI, gemini for Google Gemini CLI, agy for Google Antigravity CLI, cursor for Cursor Agent CLI, opencode for sst/opencode CLI, or custom for any user-configured coding agent CLI.',
|
|
171
194
|
parameters: {
|
|
@@ -311,7 +334,7 @@ const plugin = {
|
|
|
311
334
|
},
|
|
312
335
|
});
|
|
313
336
|
// ─── Tool: session_send ───────────────────────────────────────────────
|
|
314
|
-
|
|
337
|
+
registerTool({
|
|
315
338
|
name: 'session_send',
|
|
316
339
|
description: 'Send a message to a persistent coding session and get the response',
|
|
317
340
|
parameters: {
|
|
@@ -356,7 +379,7 @@ const plugin = {
|
|
|
356
379
|
},
|
|
357
380
|
});
|
|
358
381
|
// ─── Tool: session_stop ───────────────────────────────────────────────
|
|
359
|
-
|
|
382
|
+
registerTool({
|
|
360
383
|
name: 'session_stop',
|
|
361
384
|
description: 'Stop a persistent coding session',
|
|
362
385
|
parameters: {
|
|
@@ -370,7 +393,7 @@ const plugin = {
|
|
|
370
393
|
},
|
|
371
394
|
});
|
|
372
395
|
// ─── Tool: session_list ───────────────────────────────────────────────
|
|
373
|
-
|
|
396
|
+
registerTool({
|
|
374
397
|
name: 'session_list',
|
|
375
398
|
description: 'List all active coding sessions',
|
|
376
399
|
parameters: { type: 'object', properties: {} },
|
|
@@ -381,7 +404,7 @@ const plugin = {
|
|
|
381
404
|
},
|
|
382
405
|
});
|
|
383
406
|
// ─── Tool: sessions_overview ──────────────────────────────────────────
|
|
384
|
-
|
|
407
|
+
registerTool({
|
|
385
408
|
name: 'sessions_overview',
|
|
386
409
|
description: 'Get an aggregate overview of all active coding sessions — readiness, busy/paused state, cost, context usage, and last activity for each. Use this for a dashboard view across all sessions. For single-session detail, use coding_session_status instead.',
|
|
387
410
|
parameters: { type: 'object', properties: {} },
|
|
@@ -399,7 +422,7 @@ const plugin = {
|
|
|
399
422
|
},
|
|
400
423
|
});
|
|
401
424
|
// ─── Tool: coding_session_status ──────────────────────────────────────
|
|
402
|
-
|
|
425
|
+
registerTool({
|
|
403
426
|
name: 'coding_session_status',
|
|
404
427
|
description: 'Get detailed status of a coding session (context %, tokens, cost, uptime)',
|
|
405
428
|
parameters: {
|
|
@@ -413,7 +436,7 @@ const plugin = {
|
|
|
413
436
|
},
|
|
414
437
|
});
|
|
415
438
|
// ─── Tool: session_grep ───────────────────────────────────────────────
|
|
416
|
-
|
|
439
|
+
registerTool({
|
|
417
440
|
name: 'session_grep',
|
|
418
441
|
description: 'Search session history for events matching a regex pattern',
|
|
419
442
|
parameters: {
|
|
@@ -432,7 +455,7 @@ const plugin = {
|
|
|
432
455
|
},
|
|
433
456
|
});
|
|
434
457
|
// ─── Tool: session_compact ────────────────────────────────────────────
|
|
435
|
-
|
|
458
|
+
registerTool({
|
|
436
459
|
name: 'session_compact',
|
|
437
460
|
description: 'Compact a session to reclaim context window space',
|
|
438
461
|
parameters: {
|
|
@@ -449,7 +472,7 @@ const plugin = {
|
|
|
449
472
|
},
|
|
450
473
|
});
|
|
451
474
|
// ─── Tool: coding_agents_list ─────────────────────────────────────────
|
|
452
|
-
|
|
475
|
+
registerTool({
|
|
453
476
|
name: 'coding_agents_list',
|
|
454
477
|
description: 'List agent definitions from .claude/agents/',
|
|
455
478
|
parameters: {
|
|
@@ -462,7 +485,7 @@ const plugin = {
|
|
|
462
485
|
},
|
|
463
486
|
});
|
|
464
487
|
// ─── Tool: team_list ──────────────────────────────────────────────────
|
|
465
|
-
|
|
488
|
+
registerTool({
|
|
466
489
|
name: 'team_list',
|
|
467
490
|
description: 'List teammates in an agent team session (requires enableAgentTeams)',
|
|
468
491
|
parameters: {
|
|
@@ -476,7 +499,7 @@ const plugin = {
|
|
|
476
499
|
},
|
|
477
500
|
});
|
|
478
501
|
// ─── Tool: team_send ──────────────────────────────────────────────────
|
|
479
|
-
|
|
502
|
+
registerTool({
|
|
480
503
|
name: 'team_send',
|
|
481
504
|
description: 'Send a message to a specific teammate in an agent team session',
|
|
482
505
|
parameters: {
|
|
@@ -494,7 +517,7 @@ const plugin = {
|
|
|
494
517
|
},
|
|
495
518
|
});
|
|
496
519
|
// ─── Tool: session_update_tools ───────────────────────────────────────
|
|
497
|
-
|
|
520
|
+
registerTool({
|
|
498
521
|
name: 'session_update_tools',
|
|
499
522
|
description: 'Update allowedTools or disallowedTools for a running session. Restarts the session process with --resume to apply the new tool constraints while preserving conversation history. Rejects if the session is currently busy.',
|
|
500
523
|
parameters: {
|
|
@@ -531,7 +554,7 @@ const plugin = {
|
|
|
531
554
|
},
|
|
532
555
|
});
|
|
533
556
|
// ─── Tool: session_switch_model ───────────────────────────────────────
|
|
534
|
-
|
|
557
|
+
registerTool({
|
|
535
558
|
name: 'session_switch_model',
|
|
536
559
|
description: 'Switch the model for a running session immediately. Restarts the session process with --resume so the new model takes effect on the next message while preserving conversation history.',
|
|
537
560
|
parameters: {
|
|
@@ -548,7 +571,7 @@ const plugin = {
|
|
|
548
571
|
},
|
|
549
572
|
});
|
|
550
573
|
// ─── Tool: project_purge (CLI 2.1.126) ────────────────────────────────
|
|
551
|
-
|
|
574
|
+
registerTool({
|
|
552
575
|
name: 'project_purge',
|
|
553
576
|
description: 'Delete Claude Code project state (transcripts, tasks, file history, config entry) via `claude project purge`. Defaults to dry-run for safety — pass dry_run=false to actually delete. Use all=true to purge every project.',
|
|
554
577
|
parameters: {
|
|
@@ -578,7 +601,7 @@ const plugin = {
|
|
|
578
601
|
},
|
|
579
602
|
});
|
|
580
603
|
// ─── Tool: plugin_details (CLI 2.1.139) ─────────────────────────────
|
|
581
|
-
|
|
604
|
+
registerTool({
|
|
582
605
|
name: 'plugin_details',
|
|
583
606
|
description: "Show a plugin's component inventory (commands, hooks, MCP servers, agents, skills) plus the per-session token cost of loading it. Wraps `claude plugin details <name>` (CLI 2.1.139+).",
|
|
584
607
|
parameters: {
|
|
@@ -604,7 +627,7 @@ const plugin = {
|
|
|
604
627
|
// These tools just pre-format the slash text and send it via the
|
|
605
628
|
// normal session channel — there is no separate goal-state event to
|
|
606
629
|
// intercept (unlike Codex). Engine must be "claude".
|
|
607
|
-
|
|
630
|
+
registerTool({
|
|
608
631
|
name: 'claude_goal_set',
|
|
609
632
|
description: 'Set a goal condition on a claude session. Claude Code keeps working across turns until the condition is met, evaluating after each turn via Haiku. Sends `/goal <objective>`. Requires engine: "claude".',
|
|
610
633
|
parameters: {
|
|
@@ -623,7 +646,7 @@ const plugin = {
|
|
|
623
646
|
return await getManager().claudeGoalSet(args.name, args.objective, args.timeout);
|
|
624
647
|
},
|
|
625
648
|
});
|
|
626
|
-
|
|
649
|
+
registerTool({
|
|
627
650
|
name: 'claude_goal_clear',
|
|
628
651
|
description: 'Clear the active goal on a claude session. Sends `/goal clear`. Requires engine: "claude".',
|
|
629
652
|
parameters: {
|
|
@@ -638,7 +661,7 @@ const plugin = {
|
|
|
638
661
|
return await getManager().claudeGoalClear(args.name, args.timeout);
|
|
639
662
|
},
|
|
640
663
|
});
|
|
641
|
-
|
|
664
|
+
registerTool({
|
|
642
665
|
name: 'claude_goal_status',
|
|
643
666
|
description: 'Query the active goal on a claude session (objective, elapsed, turns, tokens). Sends bare `/goal` and returns the assistant reply. Requires engine: "claude".',
|
|
644
667
|
parameters: {
|
|
@@ -654,7 +677,7 @@ const plugin = {
|
|
|
654
677
|
},
|
|
655
678
|
});
|
|
656
679
|
// ─── Tool: codex_resume (Codex 0.119+) ──────────────────────────────
|
|
657
|
-
|
|
680
|
+
registerTool({
|
|
658
681
|
name: 'codex_resume',
|
|
659
682
|
description: 'Resume a previously recorded Codex thread by UUID/name, or pick the most recent with last=true. Spawns `codex exec resume` with --json so the output is parsed into structured fields. Independent of session manager state — useful for cross-process continuity.',
|
|
660
683
|
parameters: {
|
|
@@ -681,7 +704,7 @@ const plugin = {
|
|
|
681
704
|
},
|
|
682
705
|
});
|
|
683
706
|
// ─── Tool: codex_review ─────────────────────────────────────────────
|
|
684
|
-
|
|
707
|
+
registerTool({
|
|
685
708
|
name: 'codex_review',
|
|
686
709
|
description: 'Run a non-interactive Codex code review (`codex review`). Pick exactly one diff scope: uncommitted (working-tree changes), base (vs branch), or commit (vs SHA). Output is plain text — Codex `review` does not emit JSON.',
|
|
687
710
|
parameters: {
|
|
@@ -726,7 +749,7 @@ const plugin = {
|
|
|
726
749
|
// tools are convenience wrappers around that pattern, scoped to sessions
|
|
727
750
|
// started with engine: "codex-app". Calls against any other engine
|
|
728
751
|
// surface a clear error rather than silently no-op'ing.
|
|
729
|
-
|
|
752
|
+
registerTool({
|
|
730
753
|
name: 'codex_goal_set',
|
|
731
754
|
description: 'Set a long-horizon objective on a codex-app session. Sends `/goal <objective>` via the app-server slash command. Requires engine: "codex-app".',
|
|
732
755
|
parameters: {
|
|
@@ -745,7 +768,7 @@ const plugin = {
|
|
|
745
768
|
return await getManager().codexGoalCommand(args.name, args.objective, args.timeout);
|
|
746
769
|
},
|
|
747
770
|
});
|
|
748
|
-
|
|
771
|
+
registerTool({
|
|
749
772
|
name: 'codex_goal_get',
|
|
750
773
|
description: 'Read the cached goal state on a codex-app session (objective, status, tokensUsed, timeUsedSeconds, tokenBudget). Returns null if no goal is active. Pure read — does not send any turn.',
|
|
751
774
|
parameters: {
|
|
@@ -757,7 +780,7 @@ const plugin = {
|
|
|
757
780
|
return getManager().codexGoalGet(args.name);
|
|
758
781
|
},
|
|
759
782
|
});
|
|
760
|
-
|
|
783
|
+
registerTool({
|
|
761
784
|
name: 'codex_goal_pause',
|
|
762
785
|
description: 'Pause goal pursuit on a codex-app session. Sends `/goal pause`.',
|
|
763
786
|
parameters: {
|
|
@@ -772,7 +795,7 @@ const plugin = {
|
|
|
772
795
|
return await getManager().codexGoalCommand(args.name, 'pause', args.timeout);
|
|
773
796
|
},
|
|
774
797
|
});
|
|
775
|
-
|
|
798
|
+
registerTool({
|
|
776
799
|
name: 'codex_goal_resume',
|
|
777
800
|
description: 'Resume a paused goal on a codex-app session. Sends `/goal resume`.',
|
|
778
801
|
parameters: {
|
|
@@ -787,7 +810,7 @@ const plugin = {
|
|
|
787
810
|
return await getManager().codexGoalCommand(args.name, 'resume', args.timeout);
|
|
788
811
|
},
|
|
789
812
|
});
|
|
790
|
-
|
|
813
|
+
registerTool({
|
|
791
814
|
name: 'codex_goal_clear',
|
|
792
815
|
description: 'Clear the active goal on a codex-app session. Sends `/goal clear`.',
|
|
793
816
|
parameters: {
|
|
@@ -803,7 +826,7 @@ const plugin = {
|
|
|
803
826
|
},
|
|
804
827
|
});
|
|
805
828
|
// ─── Codex app-server v2 RPC tools (codex-app engine, Codex 0.137) ────
|
|
806
|
-
|
|
829
|
+
registerTool({
|
|
807
830
|
name: 'codex_interrupt',
|
|
808
831
|
description: 'Cancel the in-flight turn on a codex-app session (`turn/interrupt`).',
|
|
809
832
|
parameters: {
|
|
@@ -813,7 +836,7 @@ const plugin = {
|
|
|
813
836
|
},
|
|
814
837
|
execute: async (_id, args) => getManager().codexInterrupt(args.name),
|
|
815
838
|
});
|
|
816
|
-
|
|
839
|
+
registerTool({
|
|
817
840
|
name: 'codex_steer',
|
|
818
841
|
description: 'Add input to the in-flight turn on a codex-app session without restarting it (`turn/steer`). Falls back to a normal turn when idle.',
|
|
819
842
|
parameters: {
|
|
@@ -826,7 +849,7 @@ const plugin = {
|
|
|
826
849
|
},
|
|
827
850
|
execute: async (_id, args) => getManager().codexSteer(args.name, args.message),
|
|
828
851
|
});
|
|
829
|
-
|
|
852
|
+
registerTool({
|
|
830
853
|
name: 'codex_fork',
|
|
831
854
|
description: 'Branch a codex-app thread into a new one (`thread/fork`); returns the forked thread id.',
|
|
832
855
|
parameters: {
|
|
@@ -836,7 +859,7 @@ const plugin = {
|
|
|
836
859
|
},
|
|
837
860
|
execute: async (_id, args) => getManager().codexForkThread(args.name),
|
|
838
861
|
});
|
|
839
|
-
|
|
862
|
+
registerTool({
|
|
840
863
|
name: 'codex_rollback',
|
|
841
864
|
description: 'Drop the last N turns from a codex-app thread (`thread/rollback`).',
|
|
842
865
|
parameters: {
|
|
@@ -849,7 +872,7 @@ const plugin = {
|
|
|
849
872
|
},
|
|
850
873
|
execute: async (_id, args) => getManager().codexRollback(args.name, args.numTurns),
|
|
851
874
|
});
|
|
852
|
-
|
|
875
|
+
registerTool({
|
|
853
876
|
name: 'codex_models',
|
|
854
877
|
description: 'List models available to a codex-app session (`model/list`), incl. supported reasoning efforts.',
|
|
855
878
|
parameters: {
|
|
@@ -859,8 +882,8 @@ const plugin = {
|
|
|
859
882
|
},
|
|
860
883
|
execute: async (_id, args) => getManager().codexModels(args.name),
|
|
861
884
|
});
|
|
862
|
-
|
|
863
|
-
name: '
|
|
885
|
+
registerTool({
|
|
886
|
+
name: 'codex_thread_list',
|
|
864
887
|
description: 'List Codex threads visible to a codex-app session (`thread/list`), with optional filters.',
|
|
865
888
|
parameters: {
|
|
866
889
|
type: 'object',
|
|
@@ -883,7 +906,7 @@ const plugin = {
|
|
|
883
906
|
}),
|
|
884
907
|
});
|
|
885
908
|
// ─── Tool: claude_agents_list (Claude CLI 2.1.x, claude engine) ───────
|
|
886
|
-
|
|
909
|
+
registerTool({
|
|
887
910
|
name: 'claude_agents_list',
|
|
888
911
|
description: 'List Claude Code background agent sessions via `claude agents --json` (state/model/title/progress). One-shot, not tied to a managed session.',
|
|
889
912
|
parameters: {
|
|
@@ -896,7 +919,7 @@ const plugin = {
|
|
|
896
919
|
execute: async (_id, args) => getManager().claudeAgentsList({ all: args.all, cwd: args.cwd }),
|
|
897
920
|
});
|
|
898
921
|
// ─── Fan-out tools (parallel multi-engine task, no consensus) ─────────
|
|
899
|
-
|
|
922
|
+
registerTool({
|
|
900
923
|
name: 'fanout_start',
|
|
901
924
|
description: 'Run one task across N engine/model agents IN PARALLEL and collect their answers (optional synthesis). Cross-engine best-of-N / diverse-perspective primitive. No rounds, votes, or worktrees — use council for isolated parallel edits. Runs in background; poll with fanout_status.',
|
|
902
925
|
parameters: {
|
|
@@ -957,7 +980,7 @@ const plugin = {
|
|
|
957
980
|
return { ok: true, ...session, note: 'Fan-out running in background. Poll with fanout_status.' };
|
|
958
981
|
},
|
|
959
982
|
});
|
|
960
|
-
|
|
983
|
+
registerTool({
|
|
961
984
|
name: 'fanout_status',
|
|
962
985
|
description: 'Poll a running or finished fan-out by id; returns per-agent results and any synthesis.',
|
|
963
986
|
parameters: {
|
|
@@ -967,7 +990,7 @@ const plugin = {
|
|
|
967
990
|
},
|
|
968
991
|
execute: async (_id, args) => ({ ok: true, ...getManager().fanoutStatus(args.id) }),
|
|
969
992
|
});
|
|
970
|
-
|
|
993
|
+
registerTool({
|
|
971
994
|
name: 'fanout_abort',
|
|
972
995
|
description: 'Abort a running fan-out by id (already-started agents finish; synthesis is skipped).',
|
|
973
996
|
parameters: {
|
|
@@ -981,7 +1004,7 @@ const plugin = {
|
|
|
981
1004
|
},
|
|
982
1005
|
});
|
|
983
1006
|
// ─── Tools: workflow_* (durable run kernel) ─────────────────────────
|
|
984
|
-
|
|
1007
|
+
registerTool({
|
|
985
1008
|
name: 'workflow_start',
|
|
986
1009
|
description: "Start a durable workflow run. Nodes: agent | fanout | council | verifier | human_gate | router | subflow. Every state transition is checkpointed to disk, so a run survives a process restart and can be resumed. When a contract is supplied the run cannot reach `completed` unless the runtime's own checks pass — without one it completes as `unverified`, which means nothing checked it. Runs in background; poll with workflow_status.",
|
|
987
1010
|
parameters: {
|
|
@@ -1137,7 +1160,7 @@ const plugin = {
|
|
|
1137
1160
|
};
|
|
1138
1161
|
},
|
|
1139
1162
|
});
|
|
1140
|
-
|
|
1163
|
+
registerTool({
|
|
1141
1164
|
name: 'workflow_status',
|
|
1142
1165
|
description: 'Poll a workflow run. Returns state, per-node status, and the outcome: `verified` (a contract passed), `refuted` (it failed), or `unverified` (none was declared — nothing checked the work).',
|
|
1143
1166
|
parameters: {
|
|
@@ -1167,7 +1190,7 @@ const plugin = {
|
|
|
1167
1190
|
};
|
|
1168
1191
|
},
|
|
1169
1192
|
});
|
|
1170
|
-
|
|
1193
|
+
registerTool({
|
|
1171
1194
|
name: 'workflow_list',
|
|
1172
1195
|
description: 'List workflow runs on this machine, newest first. Survives restarts.',
|
|
1173
1196
|
parameters: {
|
|
@@ -1190,7 +1213,7 @@ const plugin = {
|
|
|
1190
1213
|
}),
|
|
1191
1214
|
}),
|
|
1192
1215
|
});
|
|
1193
|
-
|
|
1216
|
+
registerTool({
|
|
1194
1217
|
name: 'workflow_resume',
|
|
1195
1218
|
description: 'Re-attach to a workflow whose process died. Nodes already marked succeeded are not re-run; the node that was in flight is retried, because a half-finished node left no result to trust.',
|
|
1196
1219
|
parameters: {
|
|
@@ -1213,13 +1236,13 @@ const plugin = {
|
|
|
1213
1236
|
return { ok: true, runId: record.runId, state: record.state, currentNode: record.currentNode };
|
|
1214
1237
|
},
|
|
1215
1238
|
});
|
|
1216
|
-
|
|
1239
|
+
registerTool({
|
|
1217
1240
|
name: 'workflow_cancel',
|
|
1218
1241
|
description: 'Cancel a running workflow. The current node is asked to stop; the run ends in `cancelled`.',
|
|
1219
1242
|
parameters: { type: 'object', properties: { runId: { type: 'string' } }, required: ['runId'] },
|
|
1220
1243
|
execute: async (_id, args) => ({ ok: true, ...getManager().workflowCancel(args.runId) }),
|
|
1221
1244
|
});
|
|
1222
|
-
|
|
1245
|
+
registerTool({
|
|
1223
1246
|
name: 'workflow_steer',
|
|
1224
1247
|
description: "Queue a correction for a running workflow. The text is prepended to the next agent node's prompt — corrections belong before the task, not after it.",
|
|
1225
1248
|
parameters: {
|
|
@@ -1232,7 +1255,7 @@ const plugin = {
|
|
|
1232
1255
|
...getManager().workflowSteer(args.runId, args.text),
|
|
1233
1256
|
}),
|
|
1234
1257
|
});
|
|
1235
|
-
|
|
1258
|
+
registerTool({
|
|
1236
1259
|
name: 'workflow_approve',
|
|
1237
1260
|
description: 'Answer a workflow parked at a human_gate node.',
|
|
1238
1261
|
parameters: {
|
|
@@ -1245,7 +1268,7 @@ const plugin = {
|
|
|
1245
1268
|
...getManager().workflowApprove(args.runId, args.approved),
|
|
1246
1269
|
}),
|
|
1247
1270
|
});
|
|
1248
|
-
|
|
1271
|
+
registerTool({
|
|
1249
1272
|
name: 'verify_run',
|
|
1250
1273
|
description: 'Run an acceptance contract against a directory and return the evidence bundle. Use it to check work that did not come through a workflow — a plain session that edited a repo, say. The contract is yours; nothing is taken from agent output.',
|
|
1251
1274
|
parameters: {
|
|
@@ -1333,7 +1356,7 @@ const plugin = {
|
|
|
1333
1356
|
},
|
|
1334
1357
|
});
|
|
1335
1358
|
// ─── Tool: council_start ────────────────────────────────────────────
|
|
1336
|
-
|
|
1359
|
+
registerTool({
|
|
1337
1360
|
name: 'council_start',
|
|
1338
1361
|
description: 'Start a multi-agent council that collaborates on a task using git worktree isolation, round-based execution, and consensus voting. Agents can use different engines (Claude, Codex) and models.',
|
|
1339
1362
|
parameters: {
|
|
@@ -1402,7 +1425,7 @@ const plugin = {
|
|
|
1402
1425
|
},
|
|
1403
1426
|
});
|
|
1404
1427
|
// ─── Tool: council_status ───────────────────────────────────────────
|
|
1405
|
-
|
|
1428
|
+
registerTool({
|
|
1406
1429
|
name: 'council_status',
|
|
1407
1430
|
description: 'Get the status of a running council session',
|
|
1408
1431
|
parameters: {
|
|
@@ -1418,7 +1441,7 @@ const plugin = {
|
|
|
1418
1441
|
},
|
|
1419
1442
|
});
|
|
1420
1443
|
// ─── Tool: council_abort ────────────────────────────────────────────
|
|
1421
|
-
|
|
1444
|
+
registerTool({
|
|
1422
1445
|
name: 'council_abort',
|
|
1423
1446
|
description: 'Abort a running council, stopping all agent sessions',
|
|
1424
1447
|
parameters: {
|
|
@@ -1432,7 +1455,7 @@ const plugin = {
|
|
|
1432
1455
|
},
|
|
1433
1456
|
});
|
|
1434
1457
|
// ─── Tool: council_inject ───────────────────────────────────────────
|
|
1435
|
-
|
|
1458
|
+
registerTool({
|
|
1436
1459
|
name: 'council_inject',
|
|
1437
1460
|
description: 'Inject a user message into the next round of a running council. The message will be appended to all agent prompts in the next round.',
|
|
1438
1461
|
parameters: {
|
|
@@ -1449,7 +1472,7 @@ const plugin = {
|
|
|
1449
1472
|
},
|
|
1450
1473
|
});
|
|
1451
1474
|
// ─── Tool: council_review ──────────────────────────────────────────
|
|
1452
|
-
|
|
1475
|
+
registerTool({
|
|
1453
1476
|
name: 'council_review',
|
|
1454
1477
|
description: 'Review a completed council session. Returns a structured report of all changed files, branches, worktrees, plan.md status, review files, and agent summaries. Does not modify any state — purely informational. Use this before deciding to accept or reject.',
|
|
1455
1478
|
parameters: {
|
|
@@ -1463,7 +1486,7 @@ const plugin = {
|
|
|
1463
1486
|
},
|
|
1464
1487
|
});
|
|
1465
1488
|
// ─── Tool: council_accept ──────────────────────────────────────────
|
|
1466
|
-
|
|
1489
|
+
registerTool({
|
|
1467
1490
|
name: 'council_accept',
|
|
1468
1491
|
description: 'Accept and finalize council work. Cleans up all council scaffolding: removes worktrees, deletes council/* branches, removes plan.md and reviews/ directory. Only call after reviewing with council_review.',
|
|
1469
1492
|
parameters: {
|
|
@@ -1477,7 +1500,7 @@ const plugin = {
|
|
|
1477
1500
|
},
|
|
1478
1501
|
});
|
|
1479
1502
|
// ─── Tool: council_reject ──────────────────────────────────────────
|
|
1480
|
-
|
|
1503
|
+
registerTool({
|
|
1481
1504
|
name: 'council_reject',
|
|
1482
1505
|
description: 'Reject council work and provide feedback. Rewrites plan.md with rejection feedback and commits it. Does NOT delete any worktrees or branches — the council can be restarted to retry. Use this when the council output is incomplete or broken.',
|
|
1483
1506
|
parameters: {
|
|
@@ -1497,7 +1520,7 @@ const plugin = {
|
|
|
1497
1520
|
},
|
|
1498
1521
|
});
|
|
1499
1522
|
// ─── Tool: session_send_to ────────────────────────────────────────────
|
|
1500
|
-
|
|
1523
|
+
registerTool({
|
|
1501
1524
|
name: 'session_send_to',
|
|
1502
1525
|
description: 'Send a cross-session message from one session to another. If the target is idle, the message is delivered immediately. If busy, it is queued in the inbox for later delivery. Use "*" as target to broadcast to all other sessions.',
|
|
1503
1526
|
parameters: {
|
|
@@ -1516,7 +1539,7 @@ const plugin = {
|
|
|
1516
1539
|
},
|
|
1517
1540
|
});
|
|
1518
1541
|
// ─── Tool: session_inbox ──────────────────────────────────────────────
|
|
1519
|
-
|
|
1542
|
+
registerTool({
|
|
1520
1543
|
name: 'session_inbox',
|
|
1521
1544
|
description: 'Read inbox messages for a session. Returns unread messages by default.',
|
|
1522
1545
|
parameters: {
|
|
@@ -1533,7 +1556,7 @@ const plugin = {
|
|
|
1533
1556
|
},
|
|
1534
1557
|
});
|
|
1535
1558
|
// ─── Tool: session_deliver_inbox ──────────────────────────────────────
|
|
1536
|
-
|
|
1559
|
+
registerTool({
|
|
1537
1560
|
name: 'session_deliver_inbox',
|
|
1538
1561
|
description: 'Deliver all queued inbox messages to an idle session. Call this when a session finishes a task to process waiting messages.',
|
|
1539
1562
|
parameters: {
|
|
@@ -1547,7 +1570,7 @@ const plugin = {
|
|
|
1547
1570
|
},
|
|
1548
1571
|
});
|
|
1549
1572
|
// ─── Tool: ultraplan_start ──────────────────────────────────────
|
|
1550
|
-
|
|
1573
|
+
registerTool({
|
|
1551
1574
|
name: 'ultraplan_start',
|
|
1552
1575
|
description: 'Start an Ultraplan session: a dedicated Opus planning session that explores your project for up to 30 minutes and produces a detailed implementation plan. Runs in background.',
|
|
1553
1576
|
parameters: {
|
|
@@ -1570,7 +1593,7 @@ const plugin = {
|
|
|
1570
1593
|
},
|
|
1571
1594
|
});
|
|
1572
1595
|
// ─── Tool: ultraplan_status ─────────────────────────────────────
|
|
1573
|
-
|
|
1596
|
+
registerTool({
|
|
1574
1597
|
name: 'ultraplan_status',
|
|
1575
1598
|
description: 'Get the status of an Ultraplan session. Returns the plan text when completed.',
|
|
1576
1599
|
parameters: {
|
|
@@ -1586,7 +1609,7 @@ const plugin = {
|
|
|
1586
1609
|
},
|
|
1587
1610
|
});
|
|
1588
1611
|
// ─── Tool: ultrareview_start ────────────────────────────────────
|
|
1589
|
-
|
|
1612
|
+
registerTool({
|
|
1590
1613
|
name: 'ultrareview_start',
|
|
1591
1614
|
description: 'Start an Ultrareview: a fleet of bug-hunting agents (5-20) that review your codebase from different angles in parallel. Each agent specializes in a different area (security, performance, logic, types, etc.). Runs in background.',
|
|
1592
1615
|
parameters: {
|
|
@@ -1620,7 +1643,7 @@ const plugin = {
|
|
|
1620
1643
|
},
|
|
1621
1644
|
});
|
|
1622
1645
|
// ─── Tool: ultrareview_status ───────────────────────────────────
|
|
1623
|
-
|
|
1646
|
+
registerTool({
|
|
1624
1647
|
name: 'ultrareview_status',
|
|
1625
1648
|
description: 'Get the status of an Ultrareview. Returns all findings when completed.',
|
|
1626
1649
|
parameters: {
|
|
@@ -1640,7 +1663,7 @@ const plugin = {
|
|
|
1640
1663
|
// v2 architecture: three persistent agents (Planner / Coder / Reviewer).
|
|
1641
1664
|
// Starting a run only launches the Planner — Coder and Reviewer are
|
|
1642
1665
|
// spawned later by the Planner once the user approves the plan (S3).
|
|
1643
|
-
|
|
1666
|
+
registerTool({
|
|
1644
1667
|
name: 'autoloop_start',
|
|
1645
1668
|
description: 'Start a v2 autoloop run in chat mode. Planner, Coder, and Reviewer default to Claude (opus/sonnet/sonnet) but each role can use a different engine/model. Coder and Reviewer are spawned later by the Planner after plan approval. Returns a run_id and the Planner session name.',
|
|
1646
1669
|
parameters: {
|
|
@@ -1673,11 +1696,28 @@ const plugin = {
|
|
|
1673
1696
|
description: 'Default Reviewer model (default: sonnet for Claude; engine default otherwise)',
|
|
1674
1697
|
},
|
|
1675
1698
|
reviewer_custom_engine: CUSTOM_ENGINE_SCHEMA,
|
|
1676
|
-
send_timeout_ms: {
|
|
1699
|
+
send_timeout_ms: {
|
|
1700
|
+
...AUTOLOOP_TIMEOUT_SCHEMA.sendTimeoutMs,
|
|
1701
|
+
description: 'Per-agent send wall-clock cap in milliseconds (default 600000; inclusive range 5000–7200000)',
|
|
1702
|
+
},
|
|
1703
|
+
activity_lease_ms: {
|
|
1704
|
+
...AUTOLOOP_TIMEOUT_SCHEMA.activityLeaseMs,
|
|
1705
|
+
description: 'Inactivity lease in milliseconds, renewed by qualified progress (default 1800000; inclusive range 60000–7200000)',
|
|
1706
|
+
},
|
|
1707
|
+
autoloop_hard_timeout_ms: {
|
|
1708
|
+
...AUTOLOOP_TIMEOUT_SCHEMA.autoloopHardTimeoutMs,
|
|
1709
|
+
description: 'Absolute non-renewable run deadline in milliseconds (default 86400000; inclusive range 600000–259200000)',
|
|
1710
|
+
},
|
|
1677
1711
|
},
|
|
1678
1712
|
required: ['run_id', 'workspace'],
|
|
1679
1713
|
},
|
|
1680
1714
|
execute: async (_id, args) => {
|
|
1715
|
+
const timeoutConfig = {
|
|
1716
|
+
sendTimeoutMs: args.send_timeout_ms,
|
|
1717
|
+
activityLeaseMs: args.activity_lease_ms,
|
|
1718
|
+
autoloopHardTimeoutMs: args.autoloop_hard_timeout_ms,
|
|
1719
|
+
};
|
|
1720
|
+
validateAutoloopTimeoutConfig(timeoutConfig);
|
|
1681
1721
|
const result = await getManager().autoloopStart({
|
|
1682
1722
|
runId: args.run_id,
|
|
1683
1723
|
workspace: sanitizeCwd(args.workspace),
|
|
@@ -1690,7 +1730,7 @@ const plugin = {
|
|
|
1690
1730
|
reviewerEngine: args.reviewer_engine,
|
|
1691
1731
|
reviewerModel: args.reviewer_model,
|
|
1692
1732
|
reviewerCustomEngine: args.reviewer_custom_engine,
|
|
1693
|
-
|
|
1733
|
+
...timeoutConfig,
|
|
1694
1734
|
});
|
|
1695
1735
|
return {
|
|
1696
1736
|
ok: true,
|
|
@@ -1700,7 +1740,7 @@ const plugin = {
|
|
|
1700
1740
|
},
|
|
1701
1741
|
});
|
|
1702
1742
|
// ─── Tool: autoloop_chat ─────────────────────────────────────
|
|
1703
|
-
|
|
1743
|
+
registerTool({
|
|
1704
1744
|
name: 'autoloop_chat',
|
|
1705
1745
|
description: "Send a chat message to the Planner of a v2 autoloop run. Returns the Planner's natural-language reply. Blocking: resolves after the Planner finishes its turn.",
|
|
1706
1746
|
parameters: {
|
|
@@ -1717,7 +1757,7 @@ const plugin = {
|
|
|
1717
1757
|
},
|
|
1718
1758
|
});
|
|
1719
1759
|
// ─── Tool: autoloop_status ───────────────────────────────────
|
|
1720
|
-
|
|
1760
|
+
registerTool({
|
|
1721
1761
|
name: 'autoloop_status',
|
|
1722
1762
|
description: 'Get current state of a v2 autoloop run (status, iter, push count, subagents_spawned).',
|
|
1723
1763
|
parameters: {
|
|
@@ -1733,7 +1773,7 @@ const plugin = {
|
|
|
1733
1773
|
},
|
|
1734
1774
|
});
|
|
1735
1775
|
// ─── Tool: autoloop_list ─────────────────────────────────────
|
|
1736
|
-
|
|
1776
|
+
registerTool({
|
|
1737
1777
|
name: 'autoloop_list',
|
|
1738
1778
|
description: 'List all v2 autoloop runs in this manager process.',
|
|
1739
1779
|
parameters: { type: 'object', properties: {} },
|
|
@@ -1744,7 +1784,7 @@ const plugin = {
|
|
|
1744
1784
|
},
|
|
1745
1785
|
});
|
|
1746
1786
|
// ─── Tool: autoloop_reset_agent ──────────────────────────────
|
|
1747
|
-
|
|
1787
|
+
registerTool({
|
|
1748
1788
|
name: 'autoloop_reset_agent',
|
|
1749
1789
|
description: 'Reset a single subagent (Coder or Reviewer) on a v2 run. Stops its persistent session; the next directive/review_request will re-prime from the system prompt + ledger artifacts. Use when an agent has drifted (repeated rejects, hallucinated context, token bloat). Planner reset requires force=true because it discards chat history with the user.',
|
|
1750
1790
|
parameters: {
|
|
@@ -1771,7 +1811,7 @@ const plugin = {
|
|
|
1771
1811
|
},
|
|
1772
1812
|
});
|
|
1773
1813
|
// ─── Tool: autoloop_stop ─────────────────────────────────────
|
|
1774
|
-
|
|
1814
|
+
registerTool({
|
|
1775
1815
|
name: 'autoloop_stop',
|
|
1776
1816
|
description: 'Terminate a v2 autoloop run. Stops Planner (and Coder/Reviewer once spawned).',
|
|
1777
1817
|
parameters: {
|
|
@@ -1790,7 +1830,7 @@ const plugin = {
|
|
|
1790
1830
|
},
|
|
1791
1831
|
});
|
|
1792
1832
|
// ─── ultraapp (read-only) ─────────────────────────────────────────────
|
|
1793
|
-
|
|
1833
|
+
registerTool({
|
|
1794
1834
|
name: 'ultraapp_list',
|
|
1795
1835
|
description: 'List all ultraapp runs (interview/build/done) with title, mode, and timestamps. Read-only — to start a new run, open the Forge dashboard tab.',
|
|
1796
1836
|
parameters: { type: 'object', properties: {} },
|
|
@@ -1800,7 +1840,7 @@ const plugin = {
|
|
|
1800
1840
|
return { ok: true, runs };
|
|
1801
1841
|
},
|
|
1802
1842
|
});
|
|
1803
|
-
|
|
1843
|
+
registerTool({
|
|
1804
1844
|
name: 'ultraapp_get',
|
|
1805
1845
|
description: 'Get the AppSpec, chat history, and state for one ultraapp run. Pass `runId` from ultraapp_list.',
|
|
1806
1846
|
parameters: {
|
|
@@ -1819,7 +1859,7 @@ const plugin = {
|
|
|
1819
1859
|
return { ok: true, spec, chat, state };
|
|
1820
1860
|
},
|
|
1821
1861
|
});
|
|
1822
|
-
|
|
1862
|
+
registerTool({
|
|
1823
1863
|
name: 'ultraapp_status',
|
|
1824
1864
|
description: 'Get the run state (mode, failure reason if any) for one ultraapp run. Cheap; no chat or spec data.',
|
|
1825
1865
|
parameters: {
|
|
@@ -1834,7 +1874,7 @@ const plugin = {
|
|
|
1834
1874
|
},
|
|
1835
1875
|
});
|
|
1836
1876
|
// ─── ultraapp (write) ─────────────────────────────────────────────────
|
|
1837
|
-
|
|
1877
|
+
registerTool({
|
|
1838
1878
|
name: 'ultraapp_new',
|
|
1839
1879
|
description: 'Start a new ultraapp run. Spawns the interview Claude Opus session; the first question lands on the SSE stream / next ultraapp_get call. Returns the runId.',
|
|
1840
1880
|
parameters: { type: 'object', properties: {} },
|
|
@@ -1844,7 +1884,7 @@ const plugin = {
|
|
|
1844
1884
|
return { ok: true, runId };
|
|
1845
1885
|
},
|
|
1846
1886
|
});
|
|
1847
|
-
|
|
1887
|
+
registerTool({
|
|
1848
1888
|
name: 'ultraapp_answer',
|
|
1849
1889
|
description: 'Submit an answer to the current interview question. Either pick `value` (one of the option values from the latest question) or pass `freeform` text — both can be used together for "selected X with caveat".',
|
|
1850
1890
|
parameters: {
|
|
@@ -1865,7 +1905,7 @@ const plugin = {
|
|
|
1865
1905
|
return { ok: true };
|
|
1866
1906
|
},
|
|
1867
1907
|
});
|
|
1868
|
-
|
|
1908
|
+
registerTool({
|
|
1869
1909
|
name: 'ultraapp_add_file',
|
|
1870
1910
|
description: 'Reference a local example file by absolute path (under $HOME or /tmp; symlinks and dotfiles rejected). Use this to attach reference inputs the interview can extract metadata from. For binary uploads from a browser, use the dashboard.',
|
|
1871
1911
|
parameters: {
|
|
@@ -1885,7 +1925,7 @@ const plugin = {
|
|
|
1885
1925
|
return { ok: true, ...r };
|
|
1886
1926
|
},
|
|
1887
1927
|
});
|
|
1888
|
-
|
|
1928
|
+
registerTool({
|
|
1889
1929
|
name: 'ultraapp_spec_edit',
|
|
1890
1930
|
description: 'Manually edit the AppSpec via a JSON Patch (RFC 6902). Use sparingly — the interview engine produces and updates the spec automatically. Useful to correct a slot before clicking build.',
|
|
1891
1931
|
parameters: {
|
|
@@ -1906,7 +1946,7 @@ const plugin = {
|
|
|
1906
1946
|
return { ok: true };
|
|
1907
1947
|
},
|
|
1908
1948
|
});
|
|
1909
|
-
|
|
1949
|
+
registerTool({
|
|
1910
1950
|
name: 'ultraapp_build_start',
|
|
1911
1951
|
description: 'Enqueue a build for the run. Builds run serially. Watch ultraapp_status for transitions: queued → building → build-complete (or → deploying → done if a router is wired).',
|
|
1912
1952
|
parameters: {
|
|
@@ -1920,7 +1960,7 @@ const plugin = {
|
|
|
1920
1960
|
return { ok: true };
|
|
1921
1961
|
},
|
|
1922
1962
|
});
|
|
1923
|
-
|
|
1963
|
+
registerTool({
|
|
1924
1964
|
name: 'ultraapp_build_cancel',
|
|
1925
1965
|
description: 'Cancel a queued or in-flight build. Best-effort for in-flight; the worker is expected to honour its own cancellation signal (v0.2 only emits the event).',
|
|
1926
1966
|
parameters: {
|
|
@@ -1934,7 +1974,7 @@ const plugin = {
|
|
|
1934
1974
|
return { ok: true };
|
|
1935
1975
|
},
|
|
1936
1976
|
});
|
|
1937
|
-
|
|
1977
|
+
registerTool({
|
|
1938
1978
|
name: 'ultraapp_feedback',
|
|
1939
1979
|
description: 'Submit a done-mode feedback message (after the run reaches `done`). The text is classified by Haiku into cosmetic / spec-delta / structural and routed: cosmetic runs the patcher (Opus diff + validate + auto-revert + version snapshot); spec-delta flips the run back to `interview` with a focused bootstrap; structural posts a "start fresh" suggestion.',
|
|
1940
1980
|
parameters: {
|
|
@@ -1951,7 +1991,7 @@ const plugin = {
|
|
|
1951
1991
|
return { ok: true };
|
|
1952
1992
|
},
|
|
1953
1993
|
});
|
|
1954
|
-
|
|
1994
|
+
registerTool({
|
|
1955
1995
|
name: 'ultraapp_promote_version',
|
|
1956
1996
|
description: "Atomically swap which previously-built version is currently deployed. Stops the old container, starts the target version's container, updates the router map. Requires a router to be wired (see clawo serve).",
|
|
1957
1997
|
parameters: {
|
|
@@ -1968,7 +2008,7 @@ const plugin = {
|
|
|
1968
2008
|
return r;
|
|
1969
2009
|
},
|
|
1970
2010
|
});
|
|
1971
|
-
|
|
2011
|
+
registerTool({
|
|
1972
2012
|
name: 'ultraapp_start_container',
|
|
1973
2013
|
description: 'Start the deployed container for a run (e.g., after `ultraapp_stop_container` or after orchestrator restart with a stopped container). Re-registers the slug on the router.',
|
|
1974
2014
|
parameters: {
|
|
@@ -1982,7 +2022,7 @@ const plugin = {
|
|
|
1982
2022
|
return r;
|
|
1983
2023
|
},
|
|
1984
2024
|
});
|
|
1985
|
-
|
|
2025
|
+
registerTool({
|
|
1986
2026
|
name: 'ultraapp_stop_container',
|
|
1987
2027
|
description: 'Stop the deployed container and deregister the slug from the router. URL returns 404 until ultraapp_start_container.',
|
|
1988
2028
|
parameters: {
|
|
@@ -1996,7 +2036,7 @@ const plugin = {
|
|
|
1996
2036
|
return r;
|
|
1997
2037
|
},
|
|
1998
2038
|
});
|
|
1999
|
-
|
|
2039
|
+
registerTool({
|
|
2000
2040
|
name: 'ultraapp_delete',
|
|
2001
2041
|
description: 'Delete a run completely: stops the container, removes the image, deregisters the slug, and removes the on-disk run dir at ~/.claw-orchestrator/ultraapps/<runId>/. Irreversible.',
|
|
2002
2042
|
parameters: {
|