praxis-agent 0.35.0 → 0.37.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 (111) hide show
  1. package/README.md +20 -2
  2. package/dist/application/background-agent-manager.d.ts +16 -6
  3. package/dist/application/background-agent-manager.js +139 -97
  4. package/dist/application/context-engine.d.ts +56 -0
  5. package/dist/application/context-engine.js +129 -0
  6. package/dist/application/durable-follow-up.d.ts +14 -0
  7. package/dist/application/durable-follow-up.js +52 -0
  8. package/dist/application/native-session-transcript.d.ts +72 -0
  9. package/dist/application/native-session-transcript.js +351 -0
  10. package/dist/application/native-sidechain-transcript.d.ts +34 -0
  11. package/dist/application/native-sidechain-transcript.js +156 -0
  12. package/dist/application/session-service.d.ts +23 -4
  13. package/dist/application/session-service.js +1130 -494
  14. package/dist/application/subagent-service.d.ts +5 -1
  15. package/dist/application/subagent-service.js +749 -320
  16. package/dist/application/team-agent-runtime.d.ts +29 -0
  17. package/dist/application/team-agent-runtime.js +169 -0
  18. package/dist/application/team-capability.d.ts +27 -0
  19. package/dist/application/team-capability.js +41 -0
  20. package/dist/application/team-lead-operations.d.ts +38 -0
  21. package/dist/application/team-lead-operations.js +155 -0
  22. package/dist/application/team-mailbox.d.ts +54 -0
  23. package/dist/application/team-mailbox.js +196 -0
  24. package/dist/application/team-manager.d.ts +113 -0
  25. package/dist/application/team-manager.js +681 -0
  26. package/dist/application/team-workspace.d.ts +29 -0
  27. package/dist/application/team-workspace.js +197 -0
  28. package/dist/application/top-level-agent-manager.d.ts +1 -0
  29. package/dist/application/top-level-agent-manager.js +1025 -403
  30. package/dist/application/transcript-projection.d.ts +35 -0
  31. package/dist/application/transcript-projection.js +139 -0
  32. package/dist/application/turn-lifecycle.d.ts +2 -0
  33. package/dist/application/turn-memory-coordinator.d.ts +43 -0
  34. package/dist/application/turn-memory-coordinator.js +98 -0
  35. package/dist/cli/agents-dashboard.js +10 -5
  36. package/dist/cli/interactive.d.ts +7 -0
  37. package/dist/cli/interactive.js +645 -334
  38. package/dist/cli/tui/claude-style.d.ts +8 -25
  39. package/dist/cli/tui/claude-style.js +299 -277
  40. package/dist/cli/tui/decision-surface-model.d.ts +71 -0
  41. package/dist/cli/tui/decision-surface-model.js +131 -0
  42. package/dist/cli/tui/decision-surface.d.ts +7 -0
  43. package/dist/cli/tui/decision-surface.js +41 -0
  44. package/dist/cli/tui/help-surface-model.d.ts +68 -0
  45. package/dist/cli/tui/help-surface-model.js +131 -0
  46. package/dist/cli/tui/mcp-panel.js +1 -2
  47. package/dist/cli/tui/permission-surface-model.d.ts +195 -0
  48. package/dist/cli/tui/permission-surface-model.js +360 -0
  49. package/dist/cli/tui/permission-surface.d.ts +7 -0
  50. package/dist/cli/tui/permission-surface.js +69 -0
  51. package/dist/cli/tui/presentation-environment.d.ts +32 -0
  52. package/dist/cli/tui/presentation-environment.js +149 -0
  53. package/dist/cli/tui/task-panel.js +10 -1
  54. package/dist/cli/tui/theme.d.ts +46 -3
  55. package/dist/cli/tui/theme.js +414 -56
  56. package/dist/cli/tui/tool-permission.js +16 -8
  57. package/dist/cli/tui/transcript-presentation.d.ts +19 -1
  58. package/dist/cli/tui/transcript-presentation.js +26 -6
  59. package/dist/cli/tui/transcript-viewport.d.ts +18 -0
  60. package/dist/cli/tui/transcript-viewport.js +517 -111
  61. package/dist/cli/tui/transcript-window-model.d.ts +108 -0
  62. package/dist/cli/tui/transcript-window-model.js +772 -0
  63. package/dist/cli/tui/tui-interaction-router.d.ts +78 -0
  64. package/dist/cli/tui/tui-interaction-router.js +127 -0
  65. package/dist/cli/tui/tui-screen-model.d.ts +114 -0
  66. package/dist/cli/tui/tui-screen-model.js +210 -0
  67. package/dist/cli/tui/tui-view-model.d.ts +2 -49
  68. package/dist/cli/tui/tui-view-model.js +1 -68
  69. package/dist/cli-runtime.d.ts +4 -2
  70. package/dist/cli-runtime.js +397 -32
  71. package/dist/compatibility/claude/transcript-codec.js +6 -0
  72. package/dist/core/agent-orchestration.d.ts +31 -0
  73. package/dist/core/agent-orchestration.js +235 -0
  74. package/dist/core/permission-policy.d.ts +4 -0
  75. package/dist/core/permission-policy.js +21 -0
  76. package/dist/core/runtime.d.ts +6 -0
  77. package/dist/core/runtime.js +20 -2
  78. package/dist/core/team-mailbox.d.ts +54 -0
  79. package/dist/core/team-mailbox.js +212 -0
  80. package/dist/core/team-ownership.d.ts +84 -0
  81. package/dist/core/team-ownership.js +505 -0
  82. package/dist/core/tool-execution-scheduler.js +6 -1
  83. package/dist/core/transcript-event.d.ts +5 -1
  84. package/dist/core/transcript-event.js +12 -0
  85. package/dist/persistence/claude-job-store.d.ts +58 -0
  86. package/dist/persistence/claude-job-store.js +483 -1
  87. package/dist/persistence/claude-transcript-store.d.ts +2 -1
  88. package/dist/persistence/claude-transcript-store.js +2 -10
  89. package/dist/persistence/native-team-mailbox.d.ts +68 -0
  90. package/dist/persistence/native-team-mailbox.js +542 -0
  91. package/dist/persistence/native-team-store.d.ts +34 -0
  92. package/dist/persistence/native-team-store.js +257 -0
  93. package/dist/persistence/native-transcript-reader.d.ts +53 -0
  94. package/dist/persistence/native-transcript-reader.js +283 -0
  95. package/dist/persistence/native-transcript-store.d.ts +69 -0
  96. package/dist/persistence/native-transcript-store.js +321 -0
  97. package/dist/persistence/subagent-lifecycle-store.d.ts +41 -8
  98. package/dist/persistence/subagent-lifecycle-store.js +373 -146
  99. package/dist/persistence/transcript-file-append.d.ts +2 -0
  100. package/dist/persistence/transcript-file-append.js +10 -0
  101. package/dist/platform/exclusive-file-lease.d.ts +3 -0
  102. package/dist/platform/exclusive-file-lease.js +3 -0
  103. package/dist/tools/claude-capabilities.d.ts +4 -0
  104. package/dist/tools/claude-capabilities.js +18 -2
  105. package/dist/tools/team-lead-tools.d.ts +19 -0
  106. package/dist/tools/team-lead-tools.js +479 -0
  107. package/dist/tools/team-member-tools.d.ts +21 -0
  108. package/dist/tools/team-member-tools.js +259 -0
  109. package/package.json +1 -1
  110. package/dist/cli/tui/fullscreen-renderer.d.ts +0 -14
  111. package/dist/cli/tui/fullscreen-renderer.js +0 -13
@@ -45,6 +45,9 @@ export class ExclusiveFileLease {
45
45
  if (!owner)
46
46
  return null;
47
47
  return {
48
+ token: owner.token,
49
+ pid: owner.pid,
50
+ createdAt: owner.createdAt,
48
51
  release: () => this.releaseOwned(this.lockFile, owner.token),
49
52
  };
50
53
  }
@@ -25,6 +25,7 @@ export interface ClaudeToolCapabilityInput {
25
25
  readonly agentTriggers?: boolean;
26
26
  readonly backgroundAgents?: boolean;
27
27
  readonly subagents?: boolean;
28
+ readonly teams?: boolean;
28
29
  /** Explicit allow-list for capability-gated tools; never enables a gate. */
29
30
  readonly tools?: readonly string[];
30
31
  /** Always wins over the allow-list and the default rules. */
@@ -35,6 +36,7 @@ export interface ClaudeToolCapabilityInput {
35
36
  export declare const CLAUDE_CODE_ENABLE_TASKS = "CLAUDE_CODE_ENABLE_TASKS";
36
37
  export declare const CLAUDE_CODE_DISABLE_CRON = "CLAUDE_CODE_DISABLE_CRON";
37
38
  export declare const PRAXIS_ENABLE_WORKFLOW_SCRIPTS = "PRAXIS_ENABLE_WORKFLOW_SCRIPTS";
39
+ export declare const PRAXIS_ENABLE_TEAMS = "PRAXIS_ENABLE_TEAMS";
38
40
  /** task-v2 task-board tools, gated by the `tasks` capability. */
39
41
  export declare const CLAUDE_TASK_V2_TOOLS: readonly ["TaskCreate", "TaskGet", "TaskList", "TaskUpdate"];
40
42
  /** Workflow tool, gated by the `workflowScripts` capability. */
@@ -45,6 +47,8 @@ export declare const CLAUDE_AGENT_TRIGGER_TOOLS: readonly ["CronCreate", "CronDe
45
47
  export declare const CLAUDE_AGENT_TOOLS: readonly ["Agent"];
46
48
  /** Background task lifecycle tools, gated by the `backgroundAgents` capability. */
47
49
  export declare const CLAUDE_BACKGROUND_TOOLS: readonly ["TaskOutput", "TaskStop"];
50
+ /** Experimental local Team lifecycle names, gated by `PRAXIS_ENABLE_TEAMS`. */
51
+ export declare const PRAXIS_TEAM_TOOLS: readonly ["TeamCreate", "TeamResume", "TeamList", "TeamAccept", "TeamStop", "TeamSend"];
48
52
  /** Coordination tools advertised by a coordinator only when explicitly enabled. */
49
53
  export declare const CLAUDE_COORDINATION_TOOLS: readonly ["AskUserQuestion", "SendMessage", "SendUserMessage", "Monitor", "PushNotification"];
50
54
  /** Recursively suppressed for worker agents regardless of any allow-list. */
@@ -3,6 +3,7 @@ import { resolveToolSchedulingPolicy } from '../core/tool-scheduling-policy.js';
3
3
  export const CLAUDE_CODE_ENABLE_TASKS = 'CLAUDE_CODE_ENABLE_TASKS';
4
4
  export const CLAUDE_CODE_DISABLE_CRON = 'CLAUDE_CODE_DISABLE_CRON';
5
5
  export const PRAXIS_ENABLE_WORKFLOW_SCRIPTS = 'PRAXIS_ENABLE_WORKFLOW_SCRIPTS';
6
+ export const PRAXIS_ENABLE_TEAMS = 'PRAXIS_ENABLE_TEAMS';
6
7
  /** task-v2 task-board tools, gated by the `tasks` capability. */
7
8
  export const CLAUDE_TASK_V2_TOOLS = [
8
9
  'TaskCreate',
@@ -23,6 +24,15 @@ export const CLAUDE_AGENT_TRIGGER_TOOLS = [
23
24
  export const CLAUDE_AGENT_TOOLS = ['Agent'];
24
25
  /** Background task lifecycle tools, gated by the `backgroundAgents` capability. */
25
26
  export const CLAUDE_BACKGROUND_TOOLS = ['TaskOutput', 'TaskStop'];
27
+ /** Experimental local Team lifecycle names, gated by `PRAXIS_ENABLE_TEAMS`. */
28
+ export const PRAXIS_TEAM_TOOLS = Object.freeze([
29
+ 'TeamCreate',
30
+ 'TeamResume',
31
+ 'TeamList',
32
+ 'TeamAccept',
33
+ 'TeamStop',
34
+ 'TeamSend',
35
+ ]);
26
36
  /** Coordination tools advertised by a coordinator only when explicitly enabled. */
27
37
  export const CLAUDE_COORDINATION_TOOLS = [
28
38
  'AskUserQuestion',
@@ -43,6 +53,7 @@ export const CLAUDE_CAPABILITY_GATED_TOOLS = new Set([
43
53
  ...CLAUDE_AGENT_TRIGGER_TOOLS,
44
54
  ...CLAUDE_AGENT_TOOLS,
45
55
  ...CLAUDE_BACKGROUND_TOOLS,
56
+ ...PRAXIS_TEAM_TOOLS,
46
57
  ...CLAUDE_COORDINATION_TOOLS,
47
58
  ]);
48
59
  const EMPTY_ENV = {};
@@ -91,6 +102,7 @@ export function resolveClaudeToolCapabilities(input) {
91
102
  }
92
103
  const backgroundAgents = input.backgroundAgents ?? false;
93
104
  const subagents = input.subagents ?? false;
105
+ const teams = input.teams ?? envBoolean(env, PRAXIS_ENABLE_TEAMS) ?? false;
94
106
  if (input.tools)
95
107
  validateNames(input.tools, '--tools');
96
108
  if (input.disallowedTools)
@@ -121,13 +133,17 @@ export function resolveClaudeToolCapabilities(input) {
121
133
  for (const name of CLAUDE_BACKGROUND_TOOLS)
122
134
  enabled.add(name);
123
135
  }
136
+ if (teams) {
137
+ for (const name of PRAXIS_TEAM_TOOLS)
138
+ enabled.add(name);
139
+ }
124
140
  if (input.role === 'worker') {
125
- for (const name of CLAUDE_WORKER_RECURSIVE_TOOLS)
141
+ for (const name of [...CLAUDE_WORKER_RECURSIVE_TOOLS, ...PRAXIS_TEAM_TOOLS])
126
142
  enabled.delete(name);
127
143
  }
128
144
  else if (input.role === 'coordinator') {
129
145
  const explicit = new Set(input.tools ?? []);
130
- for (const name of CLAUDE_COORDINATION_TOOLS) {
146
+ for (const name of [...CLAUDE_COORDINATION_TOOLS, ...PRAXIS_TEAM_TOOLS]) {
131
147
  if (!explicit.has(name))
132
148
  enabled.delete(name);
133
149
  }
@@ -0,0 +1,19 @@
1
+ import type { ModelToolCall, ModelToolDefinition, ToolExecutionContext, ToolExecutionResult, ToolRegistry } from '../core/runtime.js';
2
+ import type { TeamLeadOperations } from '../application/team-lead-operations.js';
3
+ /** Tools a Coordinator Lead may use; all other base/MCP tools are denied. */
4
+ export declare const COORDINATOR_LEAD_ALLOWLIST: readonly ["Agent", "TaskOutput", "TaskStop", "TaskCreate", "TaskGet", "TaskList", "TaskUpdate", "AskUserQuestion", "EnterPlanMode", "ExitPlanMode", "SendMessage", "SendUserMessage", "Monitor", "PushNotification", "TeamCreate", "TeamResume", "TeamList", "TeamAccept", "TeamStop", "TeamSend"];
5
+ export declare class TeamLeadToolRegistry implements ToolRegistry {
6
+ private readonly base;
7
+ private readonly operations;
8
+ private readonly sessionId;
9
+ private readonly enabled;
10
+ constructor(base: ToolRegistry, operations: TeamLeadOperations, sessionId: string, toolNames: readonly string[]);
11
+ definitions(): readonly ModelToolDefinition[];
12
+ schedulingPolicy(call: ModelToolCall): import("../core/runtime.js").ToolSchedulingPolicy;
13
+ prepare(call: ModelToolCall, context: ToolExecutionContext): Promise<ModelToolCall>;
14
+ execute(call: ModelToolCall, context: ToolExecutionContext): Promise<ToolExecutionResult>;
15
+ private isAllowed;
16
+ private assertLeadPolicyAllows;
17
+ private result;
18
+ }
19
+ //# sourceMappingURL=team-lead-tools.d.ts.map
@@ -0,0 +1,479 @@
1
+ import { parseTeamMailboxPayload, } from '../core/team-mailbox.js';
2
+ import { parseTeamBudgetOverrides } from '../core/team-ownership.js';
3
+ const names = [
4
+ 'TeamCreate',
5
+ 'TeamResume',
6
+ 'TeamList',
7
+ 'TeamAccept',
8
+ 'TeamStop',
9
+ 'TeamSend',
10
+ ];
11
+ /** Tools a Coordinator Lead may use; all other base/MCP tools are denied. */
12
+ export const COORDINATOR_LEAD_ALLOWLIST = Object.freeze([
13
+ 'Agent',
14
+ 'TaskOutput',
15
+ 'TaskStop',
16
+ 'TaskCreate',
17
+ 'TaskGet',
18
+ 'TaskList',
19
+ 'TaskUpdate',
20
+ 'AskUserQuestion',
21
+ 'EnterPlanMode',
22
+ 'ExitPlanMode',
23
+ 'SendMessage',
24
+ 'SendUserMessage',
25
+ 'Monitor',
26
+ 'PushNotification',
27
+ ...names,
28
+ ]);
29
+ const coordinatorAllowlist = new Set(COORDINATOR_LEAD_ALLOWLIST);
30
+ const teamPayloadSchema = {
31
+ oneOf: [
32
+ {
33
+ type: 'object',
34
+ additionalProperties: false,
35
+ required: ['kind', 'text'],
36
+ properties: {
37
+ kind: { const: 'text' },
38
+ text: { type: 'string', minLength: 1 },
39
+ summary: { type: 'string', minLength: 1 },
40
+ },
41
+ },
42
+ {
43
+ type: 'object',
44
+ additionalProperties: false,
45
+ required: ['kind', 'phase', 'requestId', 'taskId', 'text'],
46
+ properties: {
47
+ kind: { const: 'task' },
48
+ phase: { const: 'request' },
49
+ requestId: { type: 'string', minLength: 1 },
50
+ taskId: { type: 'string', minLength: 1 },
51
+ text: { type: 'string', minLength: 1 },
52
+ },
53
+ },
54
+ {
55
+ type: 'object',
56
+ additionalProperties: false,
57
+ required: ['kind', 'phase', 'requestId', 'taskId', 'status'],
58
+ properties: {
59
+ kind: { const: 'task' },
60
+ phase: { const: 'response' },
61
+ requestId: { type: 'string', minLength: 1 },
62
+ taskId: { type: 'string', minLength: 1 },
63
+ status: { enum: ['accepted', 'rejected', 'completed', 'failed'] },
64
+ text: { type: 'string', minLength: 1 },
65
+ },
66
+ },
67
+ {
68
+ type: 'object',
69
+ additionalProperties: false,
70
+ required: ['kind', 'phase', 'requestId'],
71
+ properties: {
72
+ kind: { const: 'shutdown' },
73
+ phase: { const: 'request' },
74
+ requestId: { type: 'string', minLength: 1 },
75
+ reason: { type: 'string', minLength: 1 },
76
+ },
77
+ },
78
+ {
79
+ type: 'object',
80
+ additionalProperties: false,
81
+ required: ['kind', 'phase', 'requestId', 'approved'],
82
+ properties: {
83
+ kind: { const: 'shutdown' },
84
+ phase: { const: 'response' },
85
+ requestId: { type: 'string', minLength: 1 },
86
+ approved: { type: 'boolean' },
87
+ reason: { type: 'string', minLength: 1 },
88
+ },
89
+ },
90
+ {
91
+ type: 'object',
92
+ additionalProperties: false,
93
+ required: ['kind', 'phase', 'requestId', 'plan'],
94
+ properties: {
95
+ kind: { const: 'plan' },
96
+ phase: { const: 'request' },
97
+ requestId: { type: 'string', minLength: 1 },
98
+ plan: { type: 'string', minLength: 1 },
99
+ },
100
+ },
101
+ {
102
+ type: 'object',
103
+ additionalProperties: false,
104
+ required: ['kind', 'phase', 'requestId', 'approved'],
105
+ properties: {
106
+ kind: { const: 'plan' },
107
+ phase: { const: 'response' },
108
+ requestId: { type: 'string', minLength: 1 },
109
+ approved: { type: 'boolean' },
110
+ feedback: { type: 'string', minLength: 1 },
111
+ },
112
+ },
113
+ ],
114
+ };
115
+ const definitions = [
116
+ {
117
+ name: 'TeamCreate',
118
+ description: 'Create a local Team.',
119
+ inputSchema: {
120
+ type: 'object',
121
+ additionalProperties: false,
122
+ required: ['teamId', 'name', 'roster', 'tasks'],
123
+ properties: {
124
+ teamId: { type: 'string' },
125
+ name: { type: 'string' },
126
+ roster: {
127
+ type: 'array',
128
+ items: {
129
+ type: 'object',
130
+ additionalProperties: false,
131
+ required: ['name', 'agentType', 'access'],
132
+ properties: {
133
+ name: { type: 'string' },
134
+ agentType: { type: 'string' },
135
+ access: { enum: ['read-only', 'write'] },
136
+ },
137
+ },
138
+ },
139
+ tasks: {
140
+ type: 'array',
141
+ items: {
142
+ type: 'object',
143
+ additionalProperties: false,
144
+ required: ['id', 'description', 'assignee', 'blockedBy', 'claims'],
145
+ properties: {
146
+ id: { type: 'string' },
147
+ description: { type: 'string' },
148
+ assignee: { type: 'string' },
149
+ blockedBy: { type: 'array', items: { type: 'string' } },
150
+ claims: {
151
+ type: 'object',
152
+ additionalProperties: false,
153
+ required: [
154
+ 'files',
155
+ 'publicContracts',
156
+ 'generatedArtifacts',
157
+ 'migrations',
158
+ 'mergeTargets',
159
+ ],
160
+ properties: Object.fromEntries([
161
+ 'files',
162
+ 'publicContracts',
163
+ 'generatedArtifacts',
164
+ 'migrations',
165
+ 'mergeTargets',
166
+ ].map((key) => [
167
+ key,
168
+ { type: 'array', items: { type: 'string' } },
169
+ ])),
170
+ },
171
+ },
172
+ },
173
+ },
174
+ leadPolicy: { enum: ['hybrid', 'coordinator'] },
175
+ executionPolicy: { enum: ['sequential', 'swarm'] },
176
+ commitPolicy: { enum: ['lead'] },
177
+ budgets: {
178
+ type: 'object',
179
+ additionalProperties: false,
180
+ properties: {
181
+ maxAgents: { type: 'integer', minimum: 1 },
182
+ maxConcurrent: { type: 'integer', minimum: 1 },
183
+ maxTokens: { type: 'integer', minimum: 1 },
184
+ maxDurationMs: { type: 'integer', minimum: 1 },
185
+ shutdownDrainMs: { type: 'integer', minimum: 0, maximum: 600000 },
186
+ },
187
+ },
188
+ },
189
+ },
190
+ },
191
+ {
192
+ name: 'TeamResume',
193
+ description: 'Resume a local Team.',
194
+ inputSchema: {
195
+ type: 'object',
196
+ additionalProperties: false,
197
+ required: ['teamId'],
198
+ properties: { teamId: { type: 'string' } },
199
+ },
200
+ },
201
+ {
202
+ name: 'TeamList',
203
+ description: 'List local Teams.',
204
+ inputSchema: {
205
+ type: 'object',
206
+ additionalProperties: false,
207
+ properties: {},
208
+ },
209
+ },
210
+ {
211
+ name: 'TeamAccept',
212
+ description: 'Accept or reject a completed Team task.',
213
+ inputSchema: {
214
+ type: 'object',
215
+ additionalProperties: false,
216
+ required: ['teamId', 'taskId'],
217
+ properties: {
218
+ teamId: { type: 'string' },
219
+ taskId: { type: 'string' },
220
+ generation: { type: 'integer', minimum: 0 },
221
+ decision: { enum: ['accepted', 'rejected'], default: 'accepted' },
222
+ },
223
+ },
224
+ },
225
+ {
226
+ name: 'TeamStop',
227
+ description: 'Stop a local Team.',
228
+ inputSchema: {
229
+ type: 'object',
230
+ additionalProperties: false,
231
+ required: ['teamId'],
232
+ properties: {
233
+ teamId: { type: 'string' },
234
+ drainMs: { type: 'integer', minimum: 0, maximum: 600000 },
235
+ },
236
+ },
237
+ },
238
+ {
239
+ name: 'TeamSend',
240
+ description: 'Send a typed message through a local Team mailbox.',
241
+ inputSchema: {
242
+ type: 'object',
243
+ additionalProperties: false,
244
+ required: ['teamId', 'to', 'payload'],
245
+ properties: {
246
+ teamId: { type: 'string' },
247
+ to: {
248
+ anyOf: [
249
+ { type: 'string' },
250
+ { type: 'array', items: { type: 'string' }, minItems: 1 },
251
+ { const: 'broadcast' },
252
+ ],
253
+ },
254
+ payload: teamPayloadSchema,
255
+ },
256
+ },
257
+ },
258
+ ];
259
+ function objectInput(input, allowed) {
260
+ if (!input || typeof input !== 'object' || Array.isArray(input))
261
+ throw new Error('Team tool input must be an object');
262
+ for (const key of Object.keys(input))
263
+ if (!allowed.includes(key))
264
+ throw new Error(`Unknown Team field: ${key}`);
265
+ }
266
+ function stringValue(input, key) {
267
+ const value = input[key];
268
+ if (typeof value !== 'string' || value.trim() === '')
269
+ throw new Error(`Invalid ${key}`);
270
+ return value;
271
+ }
272
+ function validate(input, name) {
273
+ if (name === 'TeamCreate') {
274
+ objectInput(input, [
275
+ 'teamId',
276
+ 'name',
277
+ 'roster',
278
+ 'tasks',
279
+ 'leadPolicy',
280
+ 'executionPolicy',
281
+ 'commitPolicy',
282
+ 'budgets',
283
+ ]);
284
+ stringValue(input, 'teamId');
285
+ stringValue(input, 'name');
286
+ if (!Array.isArray(input.roster) || !Array.isArray(input.tasks))
287
+ throw new Error('Invalid Team roster or tasks');
288
+ if (input.leadPolicy !== undefined &&
289
+ input.leadPolicy !== 'hybrid' &&
290
+ input.leadPolicy !== 'coordinator')
291
+ throw new Error('Invalid leadPolicy');
292
+ if (input.executionPolicy !== undefined &&
293
+ input.executionPolicy !== 'sequential' &&
294
+ input.executionPolicy !== 'swarm')
295
+ throw new Error('Invalid executionPolicy');
296
+ if (input.commitPolicy !== undefined && input.commitPolicy !== 'lead')
297
+ throw new Error('Invalid commitPolicy');
298
+ if (input.budgets !== undefined) {
299
+ if (!input.budgets ||
300
+ typeof input.budgets !== 'object' ||
301
+ Array.isArray(input.budgets))
302
+ throw new Error('Invalid Team budgets');
303
+ parseTeamBudgetOverrides(input.budgets);
304
+ }
305
+ for (const member of input.roster) {
306
+ if (!member || typeof member !== 'object' || Array.isArray(member))
307
+ throw new Error('Invalid Team member');
308
+ objectInput(member, [
309
+ 'name',
310
+ 'agentType',
311
+ 'access',
312
+ ]);
313
+ }
314
+ for (const task of input.tasks) {
315
+ if (!task || typeof task !== 'object' || Array.isArray(task))
316
+ throw new Error('Invalid Team task');
317
+ const value = task;
318
+ objectInput(value, [
319
+ 'id',
320
+ 'description',
321
+ 'assignee',
322
+ 'blockedBy',
323
+ 'claims',
324
+ ]);
325
+ if (!value.claims ||
326
+ typeof value.claims !== 'object' ||
327
+ Array.isArray(value.claims))
328
+ throw new Error('Invalid Team claims');
329
+ objectInput(value.claims, [
330
+ 'files',
331
+ 'publicContracts',
332
+ 'generatedArtifacts',
333
+ 'migrations',
334
+ 'mergeTargets',
335
+ ]);
336
+ }
337
+ return input;
338
+ }
339
+ if (name === 'TeamList') {
340
+ objectInput(input, []);
341
+ return {};
342
+ }
343
+ if (name === 'TeamResume') {
344
+ objectInput(input, ['teamId']);
345
+ stringValue(input, 'teamId');
346
+ return input;
347
+ }
348
+ if (name === 'TeamAccept') {
349
+ objectInput(input, ['teamId', 'taskId', 'generation', 'decision']);
350
+ stringValue(input, 'teamId');
351
+ stringValue(input, 'taskId');
352
+ if (input.generation !== undefined &&
353
+ (!Number.isSafeInteger(input.generation) ||
354
+ input.generation < 0))
355
+ throw new Error('Invalid generation');
356
+ if (input.decision !== undefined &&
357
+ input.decision !== 'accepted' &&
358
+ input.decision !== 'rejected')
359
+ throw new Error('Invalid decision');
360
+ return {
361
+ ...input,
362
+ ...(input.decision === undefined ? { decision: 'accepted' } : {}),
363
+ };
364
+ }
365
+ if (name === 'TeamSend') {
366
+ objectInput(input, ['teamId', 'to', 'payload']);
367
+ stringValue(input, 'teamId');
368
+ if (input.to !== 'broadcast') {
369
+ if (typeof input.to === 'string') {
370
+ stringValue(input, 'to');
371
+ }
372
+ else if (Array.isArray(input.to)) {
373
+ if (input.to.length === 0 ||
374
+ input.to.some((value) => typeof value !== 'string' || value.trim() === ''))
375
+ throw new Error('Invalid Team recipients');
376
+ }
377
+ else
378
+ throw new Error('Invalid Team recipients');
379
+ }
380
+ return { ...input, payload: parseTeamMailboxPayload(input.payload) };
381
+ }
382
+ objectInput(input, ['teamId', 'drainMs']);
383
+ stringValue(input, 'teamId');
384
+ if (input.drainMs !== undefined &&
385
+ (typeof input.drainMs !== 'number' ||
386
+ !Number.isFinite(input.drainMs) ||
387
+ input.drainMs < 0 ||
388
+ input.drainMs > 600000))
389
+ throw new Error('Invalid drainMs');
390
+ if (input.drainMs !== undefined && !Number.isSafeInteger(input.drainMs))
391
+ throw new Error('Invalid drainMs');
392
+ return input;
393
+ }
394
+ export class TeamLeadToolRegistry {
395
+ base;
396
+ operations;
397
+ sessionId;
398
+ enabled;
399
+ constructor(base, operations, sessionId, toolNames) {
400
+ this.base = base;
401
+ this.operations = operations;
402
+ this.sessionId = sessionId;
403
+ this.enabled = new Set(toolNames.filter((name) => names.includes(name)));
404
+ }
405
+ definitions() {
406
+ return [
407
+ ...this.base
408
+ .definitions()
409
+ .filter((definition) => this.isAllowed(definition.name)),
410
+ ...definitions.filter((definition) => this.enabled.has(definition.name) && this.isAllowed(definition.name)),
411
+ ];
412
+ }
413
+ schedulingPolicy(call) {
414
+ this.assertLeadPolicyAllows(call.name);
415
+ if (names.includes(call.name)) {
416
+ if (!this.enabled.has(call.name))
417
+ throw new Error(`Tool ${call.name} is unavailable`);
418
+ return { concurrency: 'exclusive', cancelOnInterrupt: true };
419
+ }
420
+ return (this.base.schedulingPolicy?.(call) ?? {
421
+ concurrency: 'concurrent',
422
+ });
423
+ }
424
+ async prepare(call, context) {
425
+ this.assertLeadPolicyAllows(call.name);
426
+ if (names.includes(call.name) && !this.enabled.has(call.name))
427
+ throw new Error(`Tool ${call.name} is unavailable`);
428
+ if (!this.enabled.has(call.name))
429
+ return this.base.prepare(call, context);
430
+ return { ...call, input: validate(call.input, call.name) };
431
+ }
432
+ async execute(call, context) {
433
+ this.assertLeadPolicyAllows(call.name);
434
+ if (names.includes(call.name) && !this.enabled.has(call.name))
435
+ throw new Error(`Tool ${call.name} is unavailable`);
436
+ if (!this.enabled.has(call.name))
437
+ return this.base.execute(call, context);
438
+ if (context.signal?.aborted)
439
+ throw new Error('Team tool interrupted');
440
+ const input = validate(call.input, call.name);
441
+ let value;
442
+ switch (call.name) {
443
+ case 'TeamCreate':
444
+ value = await this.operations.create(input, this.sessionId);
445
+ break;
446
+ case 'TeamResume':
447
+ value = await this.operations.resume(input.teamId, this.sessionId);
448
+ break;
449
+ case 'TeamList':
450
+ return this.result({ teams: await this.operations.list() });
451
+ case 'TeamAccept':
452
+ value = await this.operations.accept(input, this.sessionId);
453
+ break;
454
+ case 'TeamStop':
455
+ value = await this.operations.stop(input, this.sessionId);
456
+ break;
457
+ case 'TeamSend':
458
+ value = await this.operations.send(input, this.sessionId, call.id);
459
+ return this.result({ message: value });
460
+ }
461
+ return this.result({ team: value });
462
+ }
463
+ isAllowed(name) {
464
+ return (this.operations.activeLeadPolicy(this.sessionId) !== 'coordinator' ||
465
+ coordinatorAllowlist.has(name));
466
+ }
467
+ assertLeadPolicyAllows(name) {
468
+ if (!this.isAllowed(name))
469
+ throw new Error(`Tool ${name} is unavailable for Coordinator Lead`);
470
+ }
471
+ result(value) {
472
+ return {
473
+ content: JSON.stringify(value),
474
+ isError: false,
475
+ nativeToolUseResult: value,
476
+ };
477
+ }
478
+ }
479
+ //# sourceMappingURL=team-lead-tools.js.map
@@ -0,0 +1,21 @@
1
+ import type { ModelToolCall, ModelToolDefinition, ToolExecutionContext, ToolExecutionResult, ToolRegistry, ToolSchedulingPolicy } from '../core/runtime.js';
2
+ export interface TeamMemberToolRegistryOptions {
3
+ readonly base: ToolRegistry;
4
+ readonly access: 'read-only' | 'write';
5
+ readonly cwd: string;
6
+ }
7
+ export declare class TeamMemberToolRegistry implements ToolRegistry {
8
+ private readonly options;
9
+ private readonly allowed;
10
+ private readonly canonicalCwdPromise;
11
+ constructor(options: TeamMemberToolRegistryOptions);
12
+ definitions(): readonly ModelToolDefinition[];
13
+ schedulingPolicy(call: ModelToolCall): ToolSchedulingPolicy;
14
+ prepare(call: ModelToolCall, context: ToolExecutionContext): Promise<ModelToolCall>;
15
+ execute(call: ModelToolCall, context: ToolExecutionContext): Promise<ToolExecutionResult>;
16
+ private validateCallShape;
17
+ private validate;
18
+ private validateNormalizedCommand;
19
+ private hasInlineInterpreter;
20
+ }
21
+ //# sourceMappingURL=team-member-tools.d.ts.map