mcp-codex-worker 1.0.7 → 1.0.9

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 (33) hide show
  1. package/dist/src/app.js +11 -9
  2. package/dist/src/app.js.map +1 -1
  3. package/dist/src/execution/codex-event-capture.js +14 -0
  4. package/dist/src/execution/codex-event-capture.js.map +1 -1
  5. package/dist/src/index.js +123 -42
  6. package/dist/src/index.js.map +1 -1
  7. package/dist/src/mcp/next-action-guidance.js +33 -26
  8. package/dist/src/mcp/next-action-guidance.js.map +1 -1
  9. package/dist/src/mcp/resource-renderers.js +10 -4
  10. package/dist/src/mcp/resource-renderers.js.map +1 -1
  11. package/dist/src/mcp/tool-definitions.d.ts +14 -6
  12. package/dist/src/mcp/tool-definitions.js +28 -5
  13. package/dist/src/mcp/tool-definitions.js.map +1 -1
  14. package/dist/src/services/tool-description-banner.js +1 -1
  15. package/dist/src/services/tool-description-banner.js.map +1 -1
  16. package/dist/src/task/task-handle-impl.js +3 -0
  17. package/dist/src/task/task-handle-impl.js.map +1 -1
  18. package/dist/src/task/task-handle.d.ts +7 -0
  19. package/dist/src/task/task-persistence.js +2 -0
  20. package/dist/src/task/task-persistence.js.map +1 -1
  21. package/dist/src/task/task-state.d.ts +6 -0
  22. package/package.json +1 -1
  23. package/src/app.ts +11 -9
  24. package/src/execution/codex-event-capture.ts +15 -0
  25. package/src/index.ts +172 -48
  26. package/src/mcp/next-action-guidance.ts +45 -39
  27. package/src/mcp/resource-renderers.ts +10 -4
  28. package/src/mcp/tool-definitions.ts +39 -5
  29. package/src/services/tool-description-banner.ts +1 -1
  30. package/src/task/task-handle-impl.ts +4 -0
  31. package/src/task/task-handle.ts +3 -0
  32. package/src/task/task-persistence.ts +2 -0
  33. package/src/task/task-state.ts +8 -0
@@ -11,7 +11,11 @@ import { buildStatusBanner, buildRespondBanner } from '../services/tool-descript
11
11
 
12
12
  const reasoningEnum = z.enum(REASONING_OPTIONS);
13
13
 
14
- const spawnTaskSchema = z.object({
14
+ // ---------------------------------------------------------------------------
15
+ // Zod schemas — exported for registerTool (SDK validates input automatically)
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export const spawnTaskSchema = z.object({
15
19
  prompt: z.string().min(1),
16
20
  task_type: z.enum(['coder', 'planner', 'tester', 'researcher', 'general']).default('coder'),
17
21
  provider: z.enum(['codex', 'copilot', 'claude-cli']).optional(),
@@ -28,13 +32,13 @@ const spawnTaskSchema = z.object({
28
32
  })).optional(),
29
33
  });
30
34
 
31
- const waitTaskSchema = z.object({
35
+ export const waitTaskSchema = z.object({
32
36
  task_id: z.string().min(1),
33
37
  timeout_ms: z.number().int().positive().max(300_000).default(30_000).optional(),
34
38
  poll_interval_ms: z.number().int().min(250).max(30_000).default(1000).optional(),
35
39
  });
36
40
 
37
- const respondTaskSchema = z.discriminatedUnion('type', [
41
+ export const respondTaskSchema = z.discriminatedUnion('type', [
38
42
  z.object({
39
43
  task_id: z.string().min(1),
40
44
  type: z.literal('user_input'),
@@ -64,13 +68,13 @@ const respondTaskSchema = z.discriminatedUnion('type', [
64
68
  }),
65
69
  ]);
66
70
 
67
- const messageTaskSchema = z.object({
71
+ export const messageTaskSchema = z.object({
68
72
  task_id: z.string().min(1),
69
73
  message: z.string().min(1),
70
74
  reasoning: reasoningEnum.optional(),
71
75
  });
72
76
 
73
- const cancelTaskSchema = z.object({
77
+ export const cancelTaskSchema = z.object({
74
78
  task_id: z.union([z.string().min(1), z.array(z.string().min(1)).min(1)]),
75
79
  });
76
80
 
@@ -317,3 +321,33 @@ export type WaitTaskInput = z.infer<typeof waitTaskSchema>;
317
321
  export type RespondTaskInput = z.infer<typeof respondTaskSchema>;
318
322
  export type MessageTaskInput = z.infer<typeof messageTaskSchema>;
319
323
  export type CancelTaskInput = z.infer<typeof cancelTaskSchema>;
324
+
325
+ // ---------------------------------------------------------------------------
326
+ // getToolDescriptions — description strings keyed by tool name
327
+ // Used by index.ts McpServer.registerTool which takes description separately
328
+ // ---------------------------------------------------------------------------
329
+
330
+ export function getToolDescriptions(serverVersion?: string): Map<string, string> {
331
+ const tools = createToolDefinitions(serverVersion);
332
+ const map = new Map<string, string>();
333
+ for (const tool of tools) {
334
+ map.set(tool.name, tool.description);
335
+ }
336
+ return map;
337
+ }
338
+
339
+ // ---------------------------------------------------------------------------
340
+ // TOOL_ANNOTATIONS — MCP tool annotations per tool
341
+ // ---------------------------------------------------------------------------
342
+
343
+ export interface ToolAnnotation { title: string; readOnlyHint: boolean; destructiveHint: boolean; idempotentHint: boolean; openWorldHint: boolean }
344
+
345
+ const ANNOTATIONS = new Map<string, ToolAnnotation>([
346
+ ['spawn-task', { title: 'Spawn Task', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }],
347
+ ['wait-task', { title: 'Wait Task', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }],
348
+ ['respond-task', { title: 'Respond Task', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }],
349
+ ['message-task', { title: 'Message Task', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }],
350
+ ['cancel-task', { title: 'Cancel Task', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }],
351
+ ]);
352
+
353
+ export function getToolAnnotation(name: string): ToolAnnotation { return ANNOTATIONS.get(name) ?? { title: name, readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false }; }
@@ -95,7 +95,7 @@ export function buildRespondBanner(allTasks: TaskState[]): string {
95
95
  const firstQ = pq.questions[0]!;
96
96
  let line = `- ${task.id}: "${firstQ.text}"`;
97
97
  if (firstQ.options && firstQ.options.length > 0) {
98
- const choiceStr = firstQ.options.map((c, i) => `${i + 1}) ${c}`).join(' ');
98
+ const choiceStr = firstQ.options.map((c, i) => `${i + 1}) ${String(c)}`).join(' ');
99
99
  line += ` Options: ${choiceStr}`;
100
100
  }
101
101
  parts.push(line);
@@ -164,6 +164,10 @@ export function createTaskHandle(
164
164
  const task = manager.getTask(taskId);
165
165
  return task?.taskType ?? 'general';
166
166
  },
167
+
168
+ setTokenUsage(usage) {
169
+ manager.updateTask(taskId, { tokenUsage: usage });
170
+ },
167
171
  };
168
172
 
169
173
  return handle;
@@ -132,4 +132,7 @@ export interface TaskHandle {
132
132
 
133
133
  /** The task type (coder, planner, tester, etc.). */
134
134
  getTaskType(): TaskTypeName;
135
+
136
+ /** Update the latest token usage snapshot for this task. */
137
+ setTokenUsage(usage: { totalTokens: number; inputTokens: number; outputTokens: number; contextWindow: number | null }): void;
135
138
  }
@@ -82,6 +82,8 @@ export function applyRecovery(task: TaskState, hasCrashRecovery: boolean): TaskS
82
82
  status: TaskStatus.UNKNOWN,
83
83
  error: `Server restarted; ${task.provider} sessions don't survive restarts`,
84
84
  completedAt: now,
85
+ // Auto-expire recovered tasks after 60 seconds (vs 300s default)
86
+ keepAlive: 60_000,
85
87
  output: [
86
88
  ...task.output,
87
89
  `[recovery] Task was ${task.status} when server restarted; marked UNKNOWN`,
@@ -116,6 +116,14 @@ export interface TaskState {
116
116
  exitCode?: number;
117
117
  result?: unknown;
118
118
 
119
+ // Token usage from last thread/tokenUsage/updated event
120
+ tokenUsage?: {
121
+ totalTokens: number;
122
+ inputTokens: number;
123
+ outputTokens: number;
124
+ contextWindow: number | null;
125
+ };
126
+
119
127
  // Recovery markers
120
128
  recovered?: boolean;
121
129
  degraded?: boolean;