u-foo 1.9.8 → 2.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 (69) hide show
  1. package/package.json +2 -4
  2. package/src/agent/claudeEventTranslator.js +267 -0
  3. package/src/agent/claudeOauthTokenReader.js +52 -0
  4. package/src/agent/claudeThreadProvider.js +343 -0
  5. package/src/agent/cliRunner.js +4 -16
  6. package/src/agent/codexEventTranslator.js +78 -0
  7. package/src/agent/codexThreadProvider.js +181 -0
  8. package/src/agent/controllerToolExecutor.js +233 -0
  9. package/src/agent/credentials/claude.js +324 -0
  10. package/src/agent/credentials/codex.js +203 -0
  11. package/src/agent/credentials/index.js +106 -0
  12. package/src/agent/defaultBootstrap.js +128 -5
  13. package/src/agent/internalRunner.js +333 -2
  14. package/src/agent/loopObservability.js +190 -0
  15. package/src/agent/loopRuntime.js +457 -0
  16. package/src/agent/ufooAgent.js +178 -120
  17. package/src/agent/upstreamTransport.js +464 -0
  18. package/src/bus/utils.js +3 -2
  19. package/src/chat/dashboardView.js +51 -1
  20. package/src/chat/index.js +3 -1
  21. package/src/config.js +53 -17
  22. package/src/controller/flags.js +160 -0
  23. package/src/controller/gateRouter.js +201 -0
  24. package/src/controller/routerFastPath.js +22 -0
  25. package/src/controller/shadowGuard.js +280 -0
  26. package/src/daemon/index.js +2 -3
  27. package/src/daemon/promptLoop.js +33 -224
  28. package/src/daemon/promptRequest.js +360 -5
  29. package/src/daemon/status.js +2 -0
  30. package/src/history/inputTimeline.js +9 -4
  31. package/src/memory/index.js +24 -0
  32. package/src/providerapi/redactor.js +87 -0
  33. package/src/providerapi/shadowDiff.js +174 -0
  34. package/src/report/store.js +4 -3
  35. package/src/tools/handlers/ackBus.js +26 -0
  36. package/src/tools/handlers/common.js +64 -0
  37. package/src/tools/handlers/dispatchMessage.js +81 -0
  38. package/src/tools/handlers/listAgents.js +14 -0
  39. package/src/tools/handlers/readBusSummary.js +34 -0
  40. package/src/tools/handlers/readOpenDecisions.js +26 -0
  41. package/src/tools/handlers/readProjectRegistry.js +20 -0
  42. package/src/tools/handlers/readPromptHistory.js +123 -0
  43. package/src/tools/handlers/tier2.js +134 -0
  44. package/src/tools/index.js +55 -0
  45. package/src/tools/registry.js +69 -0
  46. package/src/tools/schemaFixtures.js +415 -0
  47. package/src/tools/tier0/listAgents.js +14 -0
  48. package/src/tools/tier0/readBusSummary.js +14 -0
  49. package/src/tools/tier0/readOpenDecisions.js +14 -0
  50. package/src/tools/tier0/readProjectRegistry.js +14 -0
  51. package/src/tools/tier0/readPromptHistory.js +14 -0
  52. package/src/tools/tier1/ackBus.js +14 -0
  53. package/src/tools/tier1/dispatchMessage.js +14 -0
  54. package/src/tools/tier1/routeAgent.js +14 -0
  55. package/src/tools/tier2/closeAgent.js +14 -0
  56. package/src/tools/tier2/launchAgent.js +14 -0
  57. package/src/tools/tier2/manageCron.js +14 -0
  58. package/src/tools/tier2/renameAgent.js +14 -0
  59. package/src/tools/types.js +75 -0
  60. package/src/tools/unimplemented.js +13 -0
  61. package/src/ufoo/paths.js +4 -0
  62. package/bin/ufoo-assistant-agent.js +0 -5
  63. package/bin/ufoo-engine.js +0 -25
  64. package/src/assistant/agent.js +0 -261
  65. package/src/assistant/bridge.js +0 -178
  66. package/src/assistant/constants.js +0 -15
  67. package/src/assistant/engine.js +0 -252
  68. package/src/assistant/stdio.js +0 -58
  69. package/src/assistant/ufooEngineCli.js +0 -312
@@ -0,0 +1,134 @@
1
+ const {
2
+ buildToolError,
3
+ assertControllerTier,
4
+ extractAuditFields,
5
+ } = require("./common");
6
+
7
+ function normalizePositiveInt(value, fallback) {
8
+ const num = Number.parseInt(value, 10);
9
+ if (Number.isFinite(num) && num > 0) return num;
10
+ return fallback;
11
+ }
12
+
13
+ function decorateAudit(result, audit) {
14
+ if (!audit || (!audit.turn_id && !audit.tool_call_id && !audit.caller_tier)) {
15
+ return result;
16
+ }
17
+ return { ...result, audit };
18
+ }
19
+
20
+ function guardInvalidArgs(ctx, toolName, message) {
21
+ throw buildToolError("invalid_arguments", `${toolName} ${message}`, {
22
+ tool_name: toolName,
23
+ ...extractAuditFields(ctx),
24
+ });
25
+ }
26
+
27
+ async function runSingleOp(ctx, op, toolName) {
28
+ if (typeof ctx.handleOps !== "function") {
29
+ throw buildToolError("tool_unavailable", `${toolName} hook is unavailable`, {
30
+ tool_name: toolName,
31
+ ...extractAuditFields(ctx),
32
+ });
33
+ }
34
+ const results = await ctx.handleOps(ctx.projectRoot, [op], ctx.processManager || null);
35
+ return Array.isArray(results) ? results : [];
36
+ }
37
+
38
+ async function launchAgentHandler(ctx = {}, args = {}) {
39
+ assertControllerTier(ctx, "launch_agent");
40
+ const audit = extractAuditFields(ctx);
41
+ const agent = String(args.agent || "").trim().toLowerCase();
42
+ if (!agent) guardInvalidArgs(ctx, "launch_agent", "requires agent");
43
+
44
+ const op = {
45
+ action: "launch",
46
+ agent,
47
+ count: normalizePositiveInt(args.count, 1),
48
+ };
49
+ if (args.nickname) op.nickname = String(args.nickname).trim();
50
+ if (args.prompt_profile) op.prompt_profile = String(args.prompt_profile).trim();
51
+
52
+ const opsResults = await runSingleOp(ctx, op, "launch_agent");
53
+ return decorateAudit({
54
+ ok: true,
55
+ operation: op,
56
+ ops_results: opsResults,
57
+ }, audit);
58
+ }
59
+
60
+ async function renameAgentHandler(ctx = {}, args = {}) {
61
+ assertControllerTier(ctx, "rename_agent");
62
+ const audit = extractAuditFields(ctx);
63
+ const agentId = String(args.agent_id || "").trim();
64
+ const nickname = String(args.nickname || "").trim();
65
+ if (!agentId) guardInvalidArgs(ctx, "rename_agent", "requires agent_id");
66
+ if (!nickname) guardInvalidArgs(ctx, "rename_agent", "requires nickname");
67
+
68
+ const op = {
69
+ action: "rename",
70
+ agent_id: agentId,
71
+ nickname,
72
+ };
73
+
74
+ const opsResults = await runSingleOp(ctx, op, "rename_agent");
75
+ return decorateAudit({
76
+ ok: true,
77
+ operation: op,
78
+ ops_results: opsResults,
79
+ }, audit);
80
+ }
81
+
82
+ async function closeAgentHandler(ctx = {}, args = {}) {
83
+ assertControllerTier(ctx, "close_agent");
84
+ const audit = extractAuditFields(ctx);
85
+ const agentId = String(args.agent_id || args.target || "").trim();
86
+ if (!agentId) guardInvalidArgs(ctx, "close_agent", "requires agent_id");
87
+
88
+ const op = {
89
+ action: "close",
90
+ agent_id: agentId,
91
+ };
92
+
93
+ const opsResults = await runSingleOp(ctx, op, "close_agent");
94
+ return decorateAudit({
95
+ ok: true,
96
+ operation: op,
97
+ ops_results: opsResults,
98
+ }, audit);
99
+ }
100
+
101
+ async function manageCronHandler(ctx = {}, args = {}) {
102
+ assertControllerTier(ctx, "manage_cron");
103
+ const audit = extractAuditFields(ctx);
104
+ const operation = String(args.operation || "").trim().toLowerCase();
105
+ if (!operation) guardInvalidArgs(ctx, "manage_cron", "requires operation");
106
+
107
+ const op = {
108
+ action: "cron",
109
+ operation,
110
+ };
111
+ if (args.id) op.id = String(args.id).trim();
112
+ if (args.every) op.every = String(args.every).trim();
113
+ if (args.at) op.at = String(args.at).trim();
114
+ if (args.target) op.target = String(args.target).trim();
115
+ if (Array.isArray(args.targets)) op.targets = args.targets.slice();
116
+ if (args.prompt) op.prompt = String(args.prompt).trim();
117
+ if (args.title) op.title = String(args.title).trim();
118
+ if (Number.isFinite(Number(args.interval_ms))) op.interval_ms = Math.floor(Number(args.interval_ms));
119
+ if (Number.isFinite(Number(args.once_at_ms))) op.once_at_ms = Math.floor(Number(args.once_at_ms));
120
+
121
+ const opsResults = await runSingleOp(ctx, op, "manage_cron");
122
+ return decorateAudit({
123
+ ok: true,
124
+ operation: op,
125
+ ops_results: opsResults,
126
+ }, audit);
127
+ }
128
+
129
+ module.exports = {
130
+ launchAgentHandler,
131
+ renameAgentHandler,
132
+ closeAgentHandler,
133
+ manageCronHandler,
134
+ };
@@ -0,0 +1,55 @@
1
+ const {
2
+ SHARED_TOOL_REGISTRY,
3
+ getSharedToolRegistry,
4
+ getToolDefinition,
5
+ listToolsForCallerTier,
6
+ assertToolAllowedForCallerTier,
7
+ buildCallerTierError,
8
+ } = require("./registry");
9
+ const {
10
+ SCHEMA_VERSION,
11
+ READ_BUS_SUMMARY_SCHEMA,
12
+ READ_PROMPT_HISTORY_SCHEMA,
13
+ READ_OPEN_DECISIONS_SCHEMA,
14
+ LIST_AGENTS_SCHEMA,
15
+ READ_PROJECT_REGISTRY_SCHEMA,
16
+ ROUTE_AGENT_SCHEMA,
17
+ DISPATCH_MESSAGE_SCHEMA,
18
+ ACK_BUS_SCHEMA,
19
+ LAUNCH_AGENT_SCHEMA,
20
+ RENAME_AGENT_SCHEMA,
21
+ CLOSE_AGENT_SCHEMA,
22
+ MANAGE_CRON_SCHEMA,
23
+ PHASE0_TOOL_SCHEMAS,
24
+ } = require("./schemaFixtures");
25
+ const {
26
+ TOOL_TIERS,
27
+ CALLER_TIERS,
28
+ assertCallerTierAllowed,
29
+ } = require("./types");
30
+
31
+ module.exports = {
32
+ SHARED_TOOL_REGISTRY,
33
+ getSharedToolRegistry,
34
+ getToolDefinition,
35
+ listToolsForCallerTier,
36
+ assertToolAllowedForCallerTier,
37
+ assertCallerTierAllowed,
38
+ buildCallerTierError,
39
+ SCHEMA_VERSION,
40
+ READ_BUS_SUMMARY_SCHEMA,
41
+ READ_PROMPT_HISTORY_SCHEMA,
42
+ READ_OPEN_DECISIONS_SCHEMA,
43
+ LIST_AGENTS_SCHEMA,
44
+ READ_PROJECT_REGISTRY_SCHEMA,
45
+ ROUTE_AGENT_SCHEMA,
46
+ DISPATCH_MESSAGE_SCHEMA,
47
+ ACK_BUS_SCHEMA,
48
+ LAUNCH_AGENT_SCHEMA,
49
+ RENAME_AGENT_SCHEMA,
50
+ CLOSE_AGENT_SCHEMA,
51
+ MANAGE_CRON_SCHEMA,
52
+ PHASE0_TOOL_SCHEMAS,
53
+ TOOL_TIERS,
54
+ CALLER_TIERS,
55
+ };
@@ -0,0 +1,69 @@
1
+ const listAgents = require("./tier0/listAgents");
2
+ const readBusSummary = require("./tier0/readBusSummary");
3
+ const readOpenDecisions = require("./tier0/readOpenDecisions");
4
+ const readProjectRegistry = require("./tier0/readProjectRegistry");
5
+ const readPromptHistory = require("./tier0/readPromptHistory");
6
+ const ackBus = require("./tier1/ackBus");
7
+ const dispatchMessage = require("./tier1/dispatchMessage");
8
+ const routeAgent = require("./tier1/routeAgent");
9
+ const closeAgent = require("./tier2/closeAgent");
10
+ const launchAgent = require("./tier2/launchAgent");
11
+ const manageCron = require("./tier2/manageCron");
12
+ const renameAgent = require("./tier2/renameAgent");
13
+ const {
14
+ CALLER_TIERS,
15
+ assertCallerTierAllowed,
16
+ buildCallerTierError,
17
+ normalizeCallerTier,
18
+ } = require("./types");
19
+
20
+ const SHARED_TOOL_REGISTRY = Object.freeze([
21
+ readBusSummary,
22
+ readPromptHistory,
23
+ readOpenDecisions,
24
+ listAgents,
25
+ readProjectRegistry,
26
+ routeAgent,
27
+ dispatchMessage,
28
+ ackBus,
29
+ launchAgent,
30
+ renameAgent,
31
+ closeAgent,
32
+ manageCron,
33
+ ]);
34
+
35
+ function getSharedToolRegistry() {
36
+ return SHARED_TOOL_REGISTRY.slice();
37
+ }
38
+
39
+ function getToolDefinition(name = "") {
40
+ const target = String(name || "").trim();
41
+ return SHARED_TOOL_REGISTRY.find((tool) => tool.name === target) || null;
42
+ }
43
+
44
+ function listToolsForCallerTier(callerTier = CALLER_TIERS.CONTROLLER) {
45
+ const normalizedTier = normalizeCallerTier(callerTier);
46
+ return SHARED_TOOL_REGISTRY.filter((tool) => tool.allowed_tiers.includes(normalizedTier));
47
+ }
48
+
49
+ function assertToolAllowedForCallerTier(toolName, callerTier, auditCtx = {}) {
50
+ const toolDef = getToolDefinition(toolName);
51
+ if (!toolDef) {
52
+ const err = new Error(`unknown tool: ${toolName}`);
53
+ err.code = "unsupported_tool";
54
+ if (auditCtx && auditCtx.turn_id) err.turn_id = String(auditCtx.turn_id);
55
+ if (auditCtx && auditCtx.tool_call_id) err.tool_call_id = String(auditCtx.tool_call_id);
56
+ throw err;
57
+ }
58
+ assertCallerTierAllowed(toolDef, callerTier, auditCtx);
59
+ return toolDef;
60
+ }
61
+
62
+ module.exports = {
63
+ SHARED_TOOL_REGISTRY,
64
+ getSharedToolRegistry,
65
+ getToolDefinition,
66
+ listToolsForCallerTier,
67
+ assertToolAllowedForCallerTier,
68
+ buildCallerTierError,
69
+ };
@@ -0,0 +1,415 @@
1
+ const SCHEMA_VERSION = "1.0";
2
+
3
+ const CALLER_TIERS_READ_COORD = Object.freeze(["controller", "worker"]);
4
+ const CALLER_TIERS_CONTROLLER_ONLY = Object.freeze(["controller"]);
5
+
6
+ const READ_BUS_SUMMARY_SCHEMA = Object.freeze({
7
+ schema_version: SCHEMA_VERSION,
8
+ name: "read_bus_summary",
9
+ tier: "tier0-read",
10
+ allowed_tiers: CALLER_TIERS_READ_COORD,
11
+ description: "Read the current project bus, unread, decisions, report, cron, and group summary.",
12
+ input_schema: Object.freeze({
13
+ type: "object",
14
+ properties: Object.freeze({}),
15
+ additionalProperties: false,
16
+ }),
17
+ output_schema: Object.freeze({
18
+ type: "object",
19
+ required: ["project_root", "summary"],
20
+ properties: Object.freeze({
21
+ project_root: Object.freeze({ type: "string" }),
22
+ summary: Object.freeze({
23
+ type: "object",
24
+ required: ["active_count", "busy_count", "ready_count", "unread_total", "decisions_open"],
25
+ properties: Object.freeze({
26
+ active_count: Object.freeze({ type: "integer" }),
27
+ busy_count: Object.freeze({ type: "integer" }),
28
+ ready_count: Object.freeze({ type: "integer" }),
29
+ unread_total: Object.freeze({ type: "integer" }),
30
+ decisions_open: Object.freeze({ type: "integer" }),
31
+ reports_pending_total: Object.freeze({ type: "integer" }),
32
+ controller_pending_total: Object.freeze({ type: "integer" }),
33
+ cron_count: Object.freeze({ type: "integer" }),
34
+ groups_active: Object.freeze({ type: "integer" }),
35
+ }),
36
+ additionalProperties: false,
37
+ }),
38
+ active_agents: Object.freeze({
39
+ type: "array",
40
+ items: Object.freeze({ type: "object", additionalProperties: true }),
41
+ }),
42
+ }),
43
+ additionalProperties: false,
44
+ }),
45
+ });
46
+
47
+ const READ_PROMPT_HISTORY_SCHEMA = Object.freeze({
48
+ schema_version: SCHEMA_VERSION,
49
+ name: "read_prompt_history",
50
+ tier: "tier0-read",
51
+ allowed_tiers: CALLER_TIERS_READ_COORD,
52
+ description: "Read recent prompt-history summaries for active agents from bus events.",
53
+ input_schema: Object.freeze({
54
+ type: "object",
55
+ properties: Object.freeze({
56
+ target: Object.freeze({ type: "string" }),
57
+ per_agent_limit: Object.freeze({ type: "integer", minimum: 1 }),
58
+ max_files: Object.freeze({ type: "integer", minimum: 1 }),
59
+ }),
60
+ additionalProperties: false,
61
+ }),
62
+ output_schema: Object.freeze({
63
+ type: "object",
64
+ required: ["scanned_files", "matched_events", "per_agent"],
65
+ properties: Object.freeze({
66
+ scanned_files: Object.freeze({ type: "integer" }),
67
+ matched_events: Object.freeze({ type: "integer" }),
68
+ per_agent: Object.freeze({
69
+ type: "array",
70
+ items: Object.freeze({ type: "object", additionalProperties: true }),
71
+ }),
72
+ }),
73
+ additionalProperties: false,
74
+ }),
75
+ });
76
+
77
+ const READ_OPEN_DECISIONS_SCHEMA = Object.freeze({
78
+ schema_version: SCHEMA_VERSION,
79
+ name: "read_open_decisions",
80
+ tier: "tier0-read",
81
+ allowed_tiers: CALLER_TIERS_READ_COORD,
82
+ description: "List open decisions for the current project.",
83
+ input_schema: Object.freeze({
84
+ type: "object",
85
+ properties: Object.freeze({
86
+ limit: Object.freeze({ type: "integer", minimum: 1 }),
87
+ }),
88
+ additionalProperties: false,
89
+ }),
90
+ output_schema: Object.freeze({
91
+ type: "object",
92
+ required: ["count", "decisions"],
93
+ properties: Object.freeze({
94
+ count: Object.freeze({ type: "integer" }),
95
+ decisions: Object.freeze({
96
+ type: "array",
97
+ items: Object.freeze({ type: "object", additionalProperties: true }),
98
+ }),
99
+ }),
100
+ additionalProperties: false,
101
+ }),
102
+ });
103
+
104
+ const LIST_AGENTS_SCHEMA = Object.freeze({
105
+ schema_version: SCHEMA_VERSION,
106
+ name: "list_agents",
107
+ tier: "tier0-read",
108
+ allowed_tiers: CALLER_TIERS_READ_COORD,
109
+ description: "List active agents with nickname, status, and activity metadata.",
110
+ input_schema: Object.freeze({
111
+ type: "object",
112
+ properties: Object.freeze({}),
113
+ additionalProperties: false,
114
+ }),
115
+ output_schema: Object.freeze({
116
+ type: "object",
117
+ required: ["count", "agents"],
118
+ properties: Object.freeze({
119
+ count: Object.freeze({ type: "integer" }),
120
+ agents: Object.freeze({
121
+ type: "array",
122
+ items: Object.freeze({ type: "object", additionalProperties: true }),
123
+ }),
124
+ }),
125
+ additionalProperties: false,
126
+ }),
127
+ });
128
+
129
+ const READ_PROJECT_REGISTRY_SCHEMA = Object.freeze({
130
+ schema_version: SCHEMA_VERSION,
131
+ name: "read_project_registry",
132
+ tier: "tier0-read",
133
+ allowed_tiers: CALLER_TIERS_READ_COORD,
134
+ description: "Read the cross-project runtime registry.",
135
+ input_schema: Object.freeze({
136
+ type: "object",
137
+ properties: Object.freeze({
138
+ validate: Object.freeze({ type: "boolean" }),
139
+ cleanup_tmp: Object.freeze({ type: "boolean" }),
140
+ }),
141
+ additionalProperties: false,
142
+ }),
143
+ output_schema: Object.freeze({
144
+ type: "object",
145
+ required: ["count", "projects"],
146
+ properties: Object.freeze({
147
+ count: Object.freeze({ type: "integer" }),
148
+ projects: Object.freeze({
149
+ type: "array",
150
+ items: Object.freeze({ type: "object", additionalProperties: true }),
151
+ }),
152
+ }),
153
+ additionalProperties: false,
154
+ }),
155
+ });
156
+
157
+ const ROUTE_AGENT_SCHEMA = Object.freeze({
158
+ schema_version: SCHEMA_VERSION,
159
+ name: "route_agent",
160
+ tier: "tier1-coordination",
161
+ allowed_tiers: CALLER_TIERS_READ_COORD,
162
+ description: "Pick the best agent or nickname for the user request.",
163
+ input_schema: Object.freeze({
164
+ type: "object",
165
+ required: ["request"],
166
+ properties: Object.freeze({
167
+ request: Object.freeze({ type: "string" }),
168
+ context_hint: Object.freeze({ type: "string" }),
169
+ }),
170
+ additionalProperties: false,
171
+ }),
172
+ output_schema: Object.freeze({
173
+ type: "object",
174
+ required: ["target"],
175
+ properties: Object.freeze({
176
+ target: Object.freeze({ type: "string" }),
177
+ nickname: Object.freeze({ type: "string" }),
178
+ reason: Object.freeze({ type: "string" }),
179
+ confidence: Object.freeze({ type: "number" }),
180
+ }),
181
+ additionalProperties: false,
182
+ }),
183
+ });
184
+
185
+ const DISPATCH_MESSAGE_SCHEMA = Object.freeze({
186
+ schema_version: SCHEMA_VERSION,
187
+ name: "dispatch_message",
188
+ tier: "tier1-coordination",
189
+ allowed_tiers: CALLER_TIERS_READ_COORD,
190
+ description: "Send a message to a target agent, nickname, or broadcast queue.",
191
+ input_schema: Object.freeze({
192
+ type: "object",
193
+ required: ["target", "message"],
194
+ properties: Object.freeze({
195
+ target: Object.freeze({ type: "string" }),
196
+ message: Object.freeze({ type: "string" }),
197
+ mode: Object.freeze({
198
+ type: "string",
199
+ enum: Object.freeze(["immediate", "queued"]),
200
+ }),
201
+ source: Object.freeze({ type: "string" }),
202
+ }),
203
+ additionalProperties: false,
204
+ }),
205
+ output_schema: Object.freeze({
206
+ type: "object",
207
+ required: ["ok"],
208
+ properties: Object.freeze({
209
+ ok: Object.freeze({ type: "boolean" }),
210
+ delivered: Object.freeze({ type: "integer" }),
211
+ queued: Object.freeze({ type: "integer" }),
212
+ targets: Object.freeze({
213
+ type: "array",
214
+ items: Object.freeze({ type: "string" }),
215
+ }),
216
+ }),
217
+ additionalProperties: false,
218
+ }),
219
+ });
220
+
221
+ const ACK_BUS_SCHEMA = Object.freeze({
222
+ schema_version: SCHEMA_VERSION,
223
+ name: "ack_bus",
224
+ tier: "tier1-coordination",
225
+ allowed_tiers: CALLER_TIERS_READ_COORD,
226
+ description: "Acknowledge pending bus messages for the caller-owned queue only.",
227
+ input_schema: Object.freeze({
228
+ type: "object",
229
+ properties: Object.freeze({
230
+ subscriber: Object.freeze({ type: "string" }),
231
+ }),
232
+ additionalProperties: false,
233
+ }),
234
+ output_schema: Object.freeze({
235
+ type: "object",
236
+ required: ["ok", "subscriber", "acknowledged"],
237
+ properties: Object.freeze({
238
+ ok: Object.freeze({ type: "boolean" }),
239
+ subscriber: Object.freeze({ type: "string" }),
240
+ acknowledged: Object.freeze({ type: "integer" }),
241
+ }),
242
+ additionalProperties: false,
243
+ }),
244
+ });
245
+
246
+ const LAUNCH_AGENT_SCHEMA = Object.freeze({
247
+ schema_version: SCHEMA_VERSION,
248
+ name: "launch_agent",
249
+ tier: "tier2-orchestration",
250
+ allowed_tiers: CALLER_TIERS_CONTROLLER_ONLY,
251
+ description: "Launch one or more worker agents for controller orchestration.",
252
+ input_schema: Object.freeze({
253
+ type: "object",
254
+ required: ["agent"],
255
+ properties: Object.freeze({
256
+ agent: Object.freeze({
257
+ type: "string",
258
+ enum: Object.freeze(["codex", "claude", "ucode"]),
259
+ }),
260
+ count: Object.freeze({ type: "integer", minimum: 1 }),
261
+ nickname: Object.freeze({ type: "string" }),
262
+ prompt_profile: Object.freeze({ type: "string" }),
263
+ }),
264
+ additionalProperties: false,
265
+ }),
266
+ output_schema: Object.freeze({
267
+ type: "object",
268
+ required: ["ok"],
269
+ properties: Object.freeze({
270
+ ok: Object.freeze({ type: "boolean" }),
271
+ launched: Object.freeze({ type: "integer" }),
272
+ agent_ids: Object.freeze({
273
+ type: "array",
274
+ items: Object.freeze({ type: "string" }),
275
+ }),
276
+ }),
277
+ additionalProperties: false,
278
+ }),
279
+ });
280
+
281
+ const RENAME_AGENT_SCHEMA = Object.freeze({
282
+ schema_version: SCHEMA_VERSION,
283
+ name: "rename_agent",
284
+ tier: "tier2-orchestration",
285
+ allowed_tiers: CALLER_TIERS_CONTROLLER_ONLY,
286
+ description: "Rename an existing agent session.",
287
+ input_schema: Object.freeze({
288
+ type: "object",
289
+ required: ["agent_id", "nickname"],
290
+ properties: Object.freeze({
291
+ agent_id: Object.freeze({ type: "string" }),
292
+ nickname: Object.freeze({ type: "string" }),
293
+ }),
294
+ additionalProperties: false,
295
+ }),
296
+ output_schema: Object.freeze({
297
+ type: "object",
298
+ required: ["ok"],
299
+ properties: Object.freeze({
300
+ ok: Object.freeze({ type: "boolean" }),
301
+ operation: Object.freeze({ type: "object", additionalProperties: true }),
302
+ ops_results: Object.freeze({
303
+ type: "array",
304
+ items: Object.freeze({ type: "object", additionalProperties: true }),
305
+ }),
306
+ }),
307
+ additionalProperties: false,
308
+ }),
309
+ });
310
+
311
+ const CLOSE_AGENT_SCHEMA = Object.freeze({
312
+ schema_version: SCHEMA_VERSION,
313
+ name: "close_agent",
314
+ tier: "tier2-orchestration",
315
+ allowed_tiers: CALLER_TIERS_CONTROLLER_ONLY,
316
+ description: "Close an existing agent session.",
317
+ input_schema: Object.freeze({
318
+ type: "object",
319
+ required: ["agent_id"],
320
+ properties: Object.freeze({
321
+ agent_id: Object.freeze({ type: "string" }),
322
+ target: Object.freeze({ type: "string" }),
323
+ }),
324
+ additionalProperties: false,
325
+ }),
326
+ output_schema: Object.freeze({
327
+ type: "object",
328
+ required: ["ok"],
329
+ properties: Object.freeze({
330
+ ok: Object.freeze({ type: "boolean" }),
331
+ operation: Object.freeze({ type: "object", additionalProperties: true }),
332
+ ops_results: Object.freeze({
333
+ type: "array",
334
+ items: Object.freeze({ type: "object", additionalProperties: true }),
335
+ }),
336
+ }),
337
+ additionalProperties: false,
338
+ }),
339
+ });
340
+
341
+ const MANAGE_CRON_SCHEMA = Object.freeze({
342
+ schema_version: SCHEMA_VERSION,
343
+ name: "manage_cron",
344
+ tier: "tier2-orchestration",
345
+ allowed_tiers: CALLER_TIERS_CONTROLLER_ONLY,
346
+ description: "Create, list, or stop controller cron tasks.",
347
+ input_schema: Object.freeze({
348
+ type: "object",
349
+ required: ["operation"],
350
+ properties: Object.freeze({
351
+ operation: Object.freeze({
352
+ type: "string",
353
+ enum: Object.freeze(["start", "list", "stop"]),
354
+ }),
355
+ id: Object.freeze({ type: "string" }),
356
+ every: Object.freeze({ type: "string" }),
357
+ interval_ms: Object.freeze({ type: "integer" }),
358
+ at: Object.freeze({ type: "string" }),
359
+ once_at_ms: Object.freeze({ type: "integer" }),
360
+ target: Object.freeze({ type: "string" }),
361
+ targets: Object.freeze({
362
+ type: "array",
363
+ items: Object.freeze({ type: "string" }),
364
+ }),
365
+ prompt: Object.freeze({ type: "string" }),
366
+ title: Object.freeze({ type: "string" }),
367
+ }),
368
+ additionalProperties: false,
369
+ }),
370
+ output_schema: Object.freeze({
371
+ type: "object",
372
+ required: ["ok"],
373
+ properties: Object.freeze({
374
+ ok: Object.freeze({ type: "boolean" }),
375
+ operation: Object.freeze({ type: "object", additionalProperties: true }),
376
+ ops_results: Object.freeze({
377
+ type: "array",
378
+ items: Object.freeze({ type: "object", additionalProperties: true }),
379
+ }),
380
+ }),
381
+ additionalProperties: false,
382
+ }),
383
+ });
384
+
385
+ const PHASE0_TOOL_SCHEMAS = Object.freeze({
386
+ read_bus_summary: READ_BUS_SUMMARY_SCHEMA,
387
+ read_prompt_history: READ_PROMPT_HISTORY_SCHEMA,
388
+ read_open_decisions: READ_OPEN_DECISIONS_SCHEMA,
389
+ list_agents: LIST_AGENTS_SCHEMA,
390
+ read_project_registry: READ_PROJECT_REGISTRY_SCHEMA,
391
+ route_agent: ROUTE_AGENT_SCHEMA,
392
+ dispatch_message: DISPATCH_MESSAGE_SCHEMA,
393
+ ack_bus: ACK_BUS_SCHEMA,
394
+ launch_agent: LAUNCH_AGENT_SCHEMA,
395
+ rename_agent: RENAME_AGENT_SCHEMA,
396
+ close_agent: CLOSE_AGENT_SCHEMA,
397
+ manage_cron: MANAGE_CRON_SCHEMA,
398
+ });
399
+
400
+ module.exports = {
401
+ SCHEMA_VERSION,
402
+ READ_BUS_SUMMARY_SCHEMA,
403
+ READ_PROMPT_HISTORY_SCHEMA,
404
+ READ_OPEN_DECISIONS_SCHEMA,
405
+ LIST_AGENTS_SCHEMA,
406
+ READ_PROJECT_REGISTRY_SCHEMA,
407
+ ROUTE_AGENT_SCHEMA,
408
+ DISPATCH_MESSAGE_SCHEMA,
409
+ ACK_BUS_SCHEMA,
410
+ LAUNCH_AGENT_SCHEMA,
411
+ RENAME_AGENT_SCHEMA,
412
+ CLOSE_AGENT_SCHEMA,
413
+ MANAGE_CRON_SCHEMA,
414
+ PHASE0_TOOL_SCHEMAS,
415
+ };
@@ -0,0 +1,14 @@
1
+ const { LIST_AGENTS_SCHEMA } = require("../schemaFixtures");
2
+ const { CALLER_TIERS, TOOL_TIERS, createToolDefinition } = require("../types");
3
+ const { listAgentsHandler } = require("../handlers/listAgents");
4
+
5
+ module.exports = createToolDefinition({
6
+ name: LIST_AGENTS_SCHEMA.name,
7
+ description: LIST_AGENTS_SCHEMA.description,
8
+ tier: TOOL_TIERS.TIER_0,
9
+ allowedCallerTiers: [CALLER_TIERS.CONTROLLER, CALLER_TIERS.WORKER],
10
+ inputSchema: LIST_AGENTS_SCHEMA.input_schema,
11
+ outputSchema: LIST_AGENTS_SCHEMA.output_schema,
12
+ schemaVersion: LIST_AGENTS_SCHEMA.schema_version,
13
+ handler: listAgentsHandler,
14
+ });
@@ -0,0 +1,14 @@
1
+ const { READ_BUS_SUMMARY_SCHEMA } = require("../schemaFixtures");
2
+ const { CALLER_TIERS, TOOL_TIERS, createToolDefinition } = require("../types");
3
+ const { readBusSummaryHandler } = require("../handlers/readBusSummary");
4
+
5
+ module.exports = createToolDefinition({
6
+ name: READ_BUS_SUMMARY_SCHEMA.name,
7
+ description: READ_BUS_SUMMARY_SCHEMA.description,
8
+ tier: TOOL_TIERS.TIER_0,
9
+ allowedCallerTiers: [CALLER_TIERS.CONTROLLER, CALLER_TIERS.WORKER],
10
+ inputSchema: READ_BUS_SUMMARY_SCHEMA.input_schema,
11
+ outputSchema: READ_BUS_SUMMARY_SCHEMA.output_schema,
12
+ schemaVersion: READ_BUS_SUMMARY_SCHEMA.schema_version,
13
+ handler: readBusSummaryHandler,
14
+ });