@puzzmo/cli 1.0.35 → 1.0.36

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.
@@ -1,6 +1,4 @@
1
1
  import type { Agent } from "./types.js";
2
- /**
3
- * Codex adapter wraps `@openai/codex-sdk`, which itself shells out to the
4
- * user's installed `codex` CLI and reuses its ChatGPT subscription auth.
5
- */
2
+ /** Codex adapter — wraps the local `codex` CLI in `exec --json` mode so the
3
+ * user's existing ChatGPT subscription auth keeps working. */
6
4
  export declare const codexAgent: Agent;
@@ -1,92 +1,63 @@
1
- import { Codex } from "@openai/codex-sdk";
2
- /**
3
- * Codex adapter wraps `@openai/codex-sdk`, which itself shells out to the
4
- * user's installed `codex` CLI and reuses its ChatGPT subscription auth.
5
- */
1
+ import { runStreamJsonCli } from "./stream-json-cli.js";
2
+ /** Codex adapter — wraps the local `codex` CLI in `exec --json` mode so the
3
+ * user's existing ChatGPT subscription auth keeps working. */
6
4
  export const codexAgent = {
7
5
  name: "codex",
8
- run(input) {
9
- return runCodex(input);
10
- },
6
+ run: (input) => runStreamJsonCli({
7
+ cmd: "codex",
8
+ buildArgs: (prompt) => ["exec", "--json", "--skip-git-repo-check", prompt],
9
+ parseLine: parseCodexLine,
10
+ }, input),
11
11
  };
12
- const runCodex = async function* (input) {
13
- const codex = new Codex();
14
- let thread;
12
+ /** Map one JSONL event from `codex exec --json` to an AgentEvent. Schema matches
13
+ * the `ThreadEvent` union in `@openai/codex-sdk`. */
14
+ const parseCodexLine = (line) => {
15
+ let event;
15
16
  try {
16
- thread = codex.startThread({
17
- workingDirectory: input.cwd ?? process.cwd(),
18
- skipGitRepoCheck: true,
19
- });
17
+ event = JSON.parse(line);
20
18
  }
21
- catch (e) {
22
- yield { type: "error", message: `Failed to start codex thread: ${e.message}` };
23
- return;
19
+ catch {
20
+ return { type: "system", text: line };
24
21
  }
25
- let streamed;
26
- try {
27
- streamed = await thread.runStreamed(input.prompt, { signal: input.signal });
28
- }
29
- catch (e) {
30
- yield { type: "error", message: `Codex run failed: ${e.message}` };
31
- return;
32
- }
33
- try {
34
- for await (const event of streamed.events) {
35
- const mapped = mapCodexEvent(event);
36
- for (const m of mapped)
37
- yield m;
38
- }
39
- }
40
- catch (e) {
41
- yield { type: "error", message: e.message ?? String(e) };
42
- return;
43
- }
44
- };
45
- const mapCodexEvent = (event) => {
46
22
  if (event.type === "item.completed" || event.type === "item.updated") {
47
23
  const item = event.item;
48
24
  if (!item)
49
- return [];
25
+ return null;
50
26
  if (item.type === "agent_message" && event.type === "item.completed")
51
- return [{ type: "text", text: appendNL(item.text ?? "") }];
27
+ return { type: "text", text: appendNL(item.text ?? "") };
52
28
  if (item.type === "reasoning" && event.type === "item.completed")
53
- return [{ type: "thinking", text: appendNL(item.text ?? "") }];
29
+ return { type: "thinking", text: appendNL(item.text ?? "") };
54
30
  if (item.type === "command_execution") {
55
31
  if (item.status === "in_progress" && event.type === "item.updated")
56
- return [];
32
+ return null;
57
33
  if (item.status === "completed" || item.status === "failed")
58
- return [{ type: "tool_result", ok: item.status === "completed", summary: item.command ?? "" }];
59
- return [{ type: "tool_use", name: "Bash", summary: item.command ?? "" }];
34
+ return { type: "tool_result", ok: item.status === "completed", summary: item.command ?? "" };
35
+ return { type: "tool_use", name: "Bash", summary: item.command ?? "" };
60
36
  }
61
37
  if (item.type === "file_change") {
62
38
  const summary = (item.changes ?? []).map((c) => `${c.kind} ${c.path}`).join(", ");
63
- return [{ type: "tool_result", ok: item.status === "completed", summary }];
39
+ return { type: "tool_result", ok: item.status === "completed", summary };
64
40
  }
65
41
  if (item.type === "mcp_tool_call") {
66
42
  if (item.status === "in_progress")
67
- return [{ type: "tool_use", name: `${item.server}/${item.tool}`, summary: "" }];
68
- return [{ type: "tool_result", ok: item.status === "completed", summary: item.error?.message ?? "" }];
43
+ return { type: "tool_use", name: `${item.server}/${item.tool}`, summary: "" };
44
+ return { type: "tool_result", ok: item.status === "completed", summary: item.error?.message ?? "" };
69
45
  }
70
46
  if (item.type === "web_search")
71
- return [{ type: "tool_use", name: "WebSearch", summary: item.query ?? "" }];
72
- if (item.type === "todo_list")
73
- return [];
47
+ return { type: "tool_use", name: "WebSearch", summary: item.query ?? "" };
74
48
  if (item.type === "error")
75
- return [{ type: "error", message: item.message ?? "" }];
76
- return [];
49
+ return { type: "error", message: item.message ?? "" };
50
+ return null;
77
51
  }
78
52
  if (event.type === "turn.completed")
79
- return [{ type: "result", ok: true }];
53
+ return { type: "result", ok: true };
80
54
  if (event.type === "turn.failed")
81
- return [
82
- { type: "error", message: event.error?.message ?? "turn failed" },
83
- { type: "result", ok: false },
84
- ];
55
+ return { type: "error", message: event.error?.message ?? "turn failed" };
85
56
  if (event.type === "thread.started")
86
- return [{ type: "system", text: "Thread started" }];
57
+ return { type: "system", text: "Thread started" };
87
58
  if (event.type === "error")
88
- return [{ type: "error", message: event.message ?? "" }];
89
- return [];
59
+ return { type: "error", message: event.message ?? "" };
60
+ return null;
90
61
  };
91
62
  const appendNL = (s) => (s.endsWith("\n") ? s : s + "\n");
92
63
  //# sourceMappingURL=codex.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/agents/codex.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  import type { Agent } from "./types.js";
2
- /**
3
- * Copilot adapter wraps `@github/copilot-sdk`, which spawns the bundled
4
- * `@github/copilot` CLI and reuses its OAuth/Copilot Pro subscription auth.
5
- */
2
+ /** Copilot adapter — wraps the local `copilot` CLI (`@github/copilot`) in
3
+ * `--output-format json` mode so the user's existing OAuth/Copilot Pro
4
+ * subscription auth keeps working. */
6
5
  export declare const copilotAgent: Agent;
@@ -1,115 +1,45 @@
1
- import { CopilotClient, approveAll } from "@github/copilot-sdk";
2
- /**
3
- * Copilot adapter wraps `@github/copilot-sdk`, which spawns the bundled
4
- * `@github/copilot` CLI and reuses its OAuth/Copilot Pro subscription auth.
5
- */
1
+ import { runStreamJsonCli } from "./stream-json-cli.js";
2
+ /** Copilot adapter — wraps the local `copilot` CLI (`@github/copilot`) in
3
+ * `--output-format json` mode so the user's existing OAuth/Copilot Pro
4
+ * subscription auth keeps working. */
6
5
  export const copilotAgent = {
7
6
  name: "copilot",
8
- run(input) {
9
- return runCopilot(input);
10
- },
7
+ run: (input) => runStreamJsonCli({
8
+ cmd: "copilot",
9
+ buildArgs: (prompt) => ["-p", prompt, "--output-format", "json", "--stream", "on", "--allow-all-tools"],
10
+ parseLine: parseCopilotLine,
11
+ }, input),
11
12
  };
12
- const runCopilot = async function* (input) {
13
- const client = new CopilotClient({ cwd: input.cwd ?? process.cwd() });
13
+ /** Map one JSONL event from `copilot --output-format json` to an AgentEvent.
14
+ * Schema: `node_modules/@github/copilot/schemas/session-events.schema.json`. */
15
+ const parseCopilotLine = (line) => {
16
+ let event;
14
17
  try {
15
- await client.start();
16
- }
17
- catch (e) {
18
- yield { type: "error", message: `Copilot client failed to start: ${e.message}` };
19
- return;
20
- }
21
- const events = [];
22
- let waiting = null;
23
- const push = (e) => {
24
- events.push(e);
25
- waiting?.();
26
- waiting = null;
27
- };
28
- let session;
29
- try {
30
- session = await client.createSession({
31
- streaming: true,
32
- workingDirectory: input.cwd ?? process.cwd(),
33
- onPermissionRequest: approveAll,
34
- onEvent: (event) => {
35
- const mapped = mapCopilotEvent(event);
36
- for (const m of mapped)
37
- push(m);
38
- },
39
- });
40
- }
41
- catch (e) {
42
- yield { type: "error", message: `Copilot session creation failed: ${e.message}` };
43
- await safeStop(client);
44
- return;
45
- }
46
- const cancel = () => {
47
- session.disconnect().catch(() => { });
48
- };
49
- if (input.signal)
50
- input.signal.addEventListener("abort", cancel);
51
- let runError = null;
52
- let runDone = false;
53
- session
54
- .sendAndWait({ prompt: input.prompt }, 600_000)
55
- .catch((e) => {
56
- runError = e;
57
- })
58
- .finally(() => {
59
- runDone = true;
60
- waiting?.();
61
- waiting = null;
62
- });
63
- try {
64
- while (true) {
65
- if (events.length > 0) {
66
- yield events.shift();
67
- continue;
68
- }
69
- if (runDone) {
70
- if (runError)
71
- yield { type: "error", message: runError.message };
72
- yield { type: "result", ok: !runError };
73
- return;
74
- }
75
- await new Promise((r) => (waiting = r));
76
- }
77
- }
78
- finally {
79
- await session.disconnect().catch(() => { });
80
- await safeStop(client);
81
- }
82
- };
83
- const safeStop = async (client) => {
84
- try {
85
- await client.stop();
18
+ event = JSON.parse(line);
86
19
  }
87
20
  catch {
88
- /* ignore */
21
+ return { type: "system", text: line };
89
22
  }
90
- };
91
- const mapCopilotEvent = (event) => {
92
23
  if (event.type === "assistant.message_delta")
93
- return [{ type: "text", text: event.data?.deltaContent ?? "" }];
24
+ return { type: "text", text: event.data?.deltaContent ?? "" };
94
25
  if (event.type === "assistant.reasoning_delta")
95
- return [{ type: "thinking", text: event.data?.deltaContent ?? event.data?.delta ?? "" }];
26
+ return { type: "thinking", text: event.data?.deltaContent ?? event.data?.delta ?? "" };
96
27
  if (event.type === "tool.execution_start") {
97
28
  const name = event.data?.toolName ?? "tool";
98
- const args = event.data?.arguments;
99
- return [{ type: "tool_use", name, summary: summarizeToolArgs(name, args) }];
29
+ return { type: "tool_use", name, summary: summarizeToolArgs(event.data?.arguments) };
100
30
  }
101
31
  if (event.type === "tool.execution_complete") {
102
32
  const ok = event.data?.success === true;
103
33
  const summary = event.data?.result?.content?.slice(0, 200) ?? event.data?.error?.message ?? "";
104
- return [{ type: "tool_result", ok, summary }];
34
+ return { type: "tool_result", ok, summary };
105
35
  }
106
36
  if (event.type === "session.error")
107
- return [{ type: "error", message: event.data?.message ?? "session error" }];
108
- if (event.type === "session.start")
109
- return [{ type: "system", text: "Session started" }];
110
- return [];
37
+ return { type: "error", message: event.data?.message ?? "session error" };
38
+ if (event.type === "assistant.turn_end")
39
+ return { type: "result", ok: true };
40
+ return null;
111
41
  };
112
- const summarizeToolArgs = (name, args) => {
42
+ const summarizeToolArgs = (args) => {
113
43
  if (!args || typeof args !== "object")
114
44
  return "";
115
45
  if (typeof args.command === "string")
@@ -1 +1 @@
1
- {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/agents/copilot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/agents/copilot.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puzzmo/cli",
3
- "version": "1.0.35",
3
+ "version": "1.0.36",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "puzzmo": "./lib/index.js"
@@ -23,8 +23,6 @@
23
23
  "dependencies": {
24
24
  "@cfworker/json-schema": "^4.1.1",
25
25
  "@clack/prompts": "^1.1.0",
26
- "@github/copilot-sdk": "0.2.2",
27
- "@openai/codex-sdk": "0.122.0",
28
26
  "@opencode-ai/sdk": "1.14.20",
29
27
  "@puzzmo/agent-cli-detect": "*"
30
28
  }
@@ -1,84 +1,59 @@
1
- import { Codex } from "@openai/codex-sdk"
1
+ import { runStreamJsonCli } from "./stream-json-cli.js"
2
+ import type { AgentEvent, Agent } from "./types.js"
2
3
 
3
- import type { Agent, AgentEvent, RunInput } from "./types.js"
4
-
5
- /**
6
- * Codex adapter — wraps `@openai/codex-sdk`, which itself shells out to the
7
- * user's installed `codex` CLI and reuses its ChatGPT subscription auth.
8
- */
4
+ /** Codex adapter wraps the local `codex` CLI in `exec --json` mode so the
5
+ * user's existing ChatGPT subscription auth keeps working. */
9
6
  export const codexAgent: Agent = {
10
7
  name: "codex",
11
- run(input) {
12
- return runCodex(input)
13
- },
8
+ run: (input) =>
9
+ runStreamJsonCli(
10
+ {
11
+ cmd: "codex",
12
+ buildArgs: (prompt) => ["exec", "--json", "--skip-git-repo-check", prompt],
13
+ parseLine: parseCodexLine,
14
+ },
15
+ input,
16
+ ),
14
17
  }
15
18
 
16
- const runCodex = async function* (input: RunInput): AsyncIterable<AgentEvent> {
17
- const codex = new Codex()
18
- let thread
19
+ /** Map one JSONL event from `codex exec --json` to an AgentEvent. Schema matches
20
+ * the `ThreadEvent` union in `@openai/codex-sdk`. */
21
+ const parseCodexLine = (line: string): AgentEvent | null => {
22
+ let event: any
19
23
  try {
20
- thread = codex.startThread({
21
- workingDirectory: input.cwd ?? process.cwd(),
22
- skipGitRepoCheck: true,
23
- })
24
- } catch (e: any) {
25
- yield { type: "error", message: `Failed to start codex thread: ${e.message}` }
26
- return
24
+ event = JSON.parse(line)
25
+ } catch {
26
+ return { type: "system", text: line }
27
27
  }
28
28
 
29
- let streamed
30
- try {
31
- streamed = await thread.runStreamed(input.prompt, { signal: input.signal })
32
- } catch (e: any) {
33
- yield { type: "error", message: `Codex run failed: ${e.message}` }
34
- return
35
- }
36
-
37
- try {
38
- for await (const event of streamed.events) {
39
- const mapped = mapCodexEvent(event)
40
- for (const m of mapped) yield m
41
- }
42
- } catch (e: any) {
43
- yield { type: "error", message: e.message ?? String(e) }
44
- return
45
- }
46
- }
47
-
48
- const mapCodexEvent = (event: any): AgentEvent[] => {
49
29
  if (event.type === "item.completed" || event.type === "item.updated") {
50
30
  const item = event.item
51
- if (!item) return []
52
- if (item.type === "agent_message" && event.type === "item.completed") return [{ type: "text", text: appendNL(item.text ?? "") }]
53
- if (item.type === "reasoning" && event.type === "item.completed") return [{ type: "thinking", text: appendNL(item.text ?? "") }]
31
+ if (!item) return null
32
+ if (item.type === "agent_message" && event.type === "item.completed") return { type: "text", text: appendNL(item.text ?? "") }
33
+ if (item.type === "reasoning" && event.type === "item.completed") return { type: "thinking", text: appendNL(item.text ?? "") }
54
34
  if (item.type === "command_execution") {
55
- if (item.status === "in_progress" && event.type === "item.updated") return []
35
+ if (item.status === "in_progress" && event.type === "item.updated") return null
56
36
  if (item.status === "completed" || item.status === "failed")
57
- return [{ type: "tool_result", ok: item.status === "completed", summary: item.command ?? "" }]
58
- return [{ type: "tool_use", name: "Bash", summary: item.command ?? "" }]
37
+ return { type: "tool_result", ok: item.status === "completed", summary: item.command ?? "" }
38
+ return { type: "tool_use", name: "Bash", summary: item.command ?? "" }
59
39
  }
60
40
  if (item.type === "file_change") {
61
41
  const summary = (item.changes ?? []).map((c: any) => `${c.kind} ${c.path}`).join(", ")
62
- return [{ type: "tool_result", ok: item.status === "completed", summary }]
42
+ return { type: "tool_result", ok: item.status === "completed", summary }
63
43
  }
64
44
  if (item.type === "mcp_tool_call") {
65
- if (item.status === "in_progress") return [{ type: "tool_use", name: `${item.server}/${item.tool}`, summary: "" }]
66
- return [{ type: "tool_result", ok: item.status === "completed", summary: item.error?.message ?? "" }]
45
+ if (item.status === "in_progress") return { type: "tool_use", name: `${item.server}/${item.tool}`, summary: "" }
46
+ return { type: "tool_result", ok: item.status === "completed", summary: item.error?.message ?? "" }
67
47
  }
68
- if (item.type === "web_search") return [{ type: "tool_use", name: "WebSearch", summary: item.query ?? "" }]
69
- if (item.type === "todo_list") return []
70
- if (item.type === "error") return [{ type: "error", message: item.message ?? "" }]
71
- return []
48
+ if (item.type === "web_search") return { type: "tool_use", name: "WebSearch", summary: item.query ?? "" }
49
+ if (item.type === "error") return { type: "error", message: item.message ?? "" }
50
+ return null
72
51
  }
73
- if (event.type === "turn.completed") return [{ type: "result", ok: true }]
74
- if (event.type === "turn.failed")
75
- return [
76
- { type: "error", message: event.error?.message ?? "turn failed" },
77
- { type: "result", ok: false },
78
- ]
79
- if (event.type === "thread.started") return [{ type: "system", text: "Thread started" }]
80
- if (event.type === "error") return [{ type: "error", message: event.message ?? "" }]
81
- return []
52
+ if (event.type === "turn.completed") return { type: "result", ok: true }
53
+ if (event.type === "turn.failed") return { type: "error", message: event.error?.message ?? "turn failed" }
54
+ if (event.type === "thread.started") return { type: "system", text: "Thread started" }
55
+ if (event.type === "error") return { type: "error", message: event.message ?? "" }
56
+ return null
82
57
  }
83
58
 
84
59
  const appendNL = (s: string) => (s.endsWith("\n") ? s : s + "\n")
@@ -1,116 +1,49 @@
1
- import { CopilotClient, approveAll } from "@github/copilot-sdk"
1
+ import { runStreamJsonCli } from "./stream-json-cli.js"
2
+ import type { Agent, AgentEvent } from "./types.js"
2
3
 
3
- import type { Agent, AgentEvent, RunInput } from "./types.js"
4
-
5
- /**
6
- * Copilot adapter — wraps `@github/copilot-sdk`, which spawns the bundled
7
- * `@github/copilot` CLI and reuses its OAuth/Copilot Pro subscription auth.
8
- */
4
+ /** Copilot adapter wraps the local `copilot` CLI (`@github/copilot`) in
5
+ * `--output-format json` mode so the user's existing OAuth/Copilot Pro
6
+ * subscription auth keeps working. */
9
7
  export const copilotAgent: Agent = {
10
8
  name: "copilot",
11
- run(input) {
12
- return runCopilot(input)
13
- },
14
- }
15
-
16
- const runCopilot = async function* (input: RunInput): AsyncIterable<AgentEvent> {
17
- const client = new CopilotClient({ cwd: input.cwd ?? process.cwd() })
18
- try {
19
- await client.start()
20
- } catch (e: any) {
21
- yield { type: "error", message: `Copilot client failed to start: ${e.message}` }
22
- return
23
- }
24
-
25
- const events: AgentEvent[] = []
26
- let waiting: (() => void) | null = null
27
- const push = (e: AgentEvent) => {
28
- events.push(e)
29
- waiting?.()
30
- waiting = null
31
- }
32
-
33
- let session
34
- try {
35
- session = await client.createSession({
36
- streaming: true,
37
- workingDirectory: input.cwd ?? process.cwd(),
38
- onPermissionRequest: approveAll,
39
- onEvent: (event: any) => {
40
- const mapped = mapCopilotEvent(event)
41
- for (const m of mapped) push(m)
9
+ run: (input) =>
10
+ runStreamJsonCli(
11
+ {
12
+ cmd: "copilot",
13
+ buildArgs: (prompt) => ["-p", prompt, "--output-format", "json", "--stream", "on", "--allow-all-tools"],
14
+ parseLine: parseCopilotLine,
42
15
  },
43
- })
44
- } catch (e: any) {
45
- yield { type: "error", message: `Copilot session creation failed: ${e.message}` }
46
- await safeStop(client)
47
- return
48
- }
49
-
50
- const cancel = () => {
51
- session.disconnect().catch(() => {})
52
- }
53
- if (input.signal) input.signal.addEventListener("abort", cancel)
54
-
55
- let runError = null as Error | null
56
- let runDone = false
57
- session
58
- .sendAndWait({ prompt: input.prompt }, 600_000)
59
- .catch((e: Error) => {
60
- runError = e
61
- })
62
- .finally(() => {
63
- runDone = true
64
- waiting?.()
65
- waiting = null
66
- })
67
-
68
- try {
69
- while (true) {
70
- if (events.length > 0) {
71
- yield events.shift()!
72
- continue
73
- }
74
- if (runDone) {
75
- if (runError) yield { type: "error", message: runError.message }
76
- yield { type: "result", ok: !runError }
77
- return
78
- }
79
- await new Promise<void>((r) => (waiting = r))
80
- }
81
- } finally {
82
- await session.disconnect().catch(() => {})
83
- await safeStop(client)
84
- }
16
+ input,
17
+ ),
85
18
  }
86
19
 
87
- const safeStop = async (client: CopilotClient) => {
20
+ /** Map one JSONL event from `copilot --output-format json` to an AgentEvent.
21
+ * Schema: `node_modules/@github/copilot/schemas/session-events.schema.json`. */
22
+ const parseCopilotLine = (line: string): AgentEvent | null => {
23
+ let event: any
88
24
  try {
89
- await client.stop()
25
+ event = JSON.parse(line)
90
26
  } catch {
91
- /* ignore */
27
+ return { type: "system", text: line }
92
28
  }
93
- }
94
29
 
95
- const mapCopilotEvent = (event: any): AgentEvent[] => {
96
- if (event.type === "assistant.message_delta") return [{ type: "text", text: event.data?.deltaContent ?? "" }]
97
- if (event.type === "assistant.reasoning_delta") return [{ type: "thinking", text: event.data?.deltaContent ?? event.data?.delta ?? "" }]
30
+ if (event.type === "assistant.message_delta") return { type: "text", text: event.data?.deltaContent ?? "" }
31
+ if (event.type === "assistant.reasoning_delta") return { type: "thinking", text: event.data?.deltaContent ?? event.data?.delta ?? "" }
98
32
  if (event.type === "tool.execution_start") {
99
33
  const name = event.data?.toolName ?? "tool"
100
- const args = event.data?.arguments
101
- return [{ type: "tool_use", name, summary: summarizeToolArgs(name, args) }]
34
+ return { type: "tool_use", name, summary: summarizeToolArgs(event.data?.arguments) }
102
35
  }
103
36
  if (event.type === "tool.execution_complete") {
104
37
  const ok = event.data?.success === true
105
38
  const summary = event.data?.result?.content?.slice(0, 200) ?? event.data?.error?.message ?? ""
106
- return [{ type: "tool_result", ok, summary }]
39
+ return { type: "tool_result", ok, summary }
107
40
  }
108
- if (event.type === "session.error") return [{ type: "error", message: event.data?.message ?? "session error" }]
109
- if (event.type === "session.start") return [{ type: "system", text: "Session started" }]
110
- return []
41
+ if (event.type === "session.error") return { type: "error", message: event.data?.message ?? "session error" }
42
+ if (event.type === "assistant.turn_end") return { type: "result", ok: true }
43
+ return null
111
44
  }
112
45
 
113
- const summarizeToolArgs = (name: string, args: any): string => {
46
+ const summarizeToolArgs = (args: any): string => {
114
47
  if (!args || typeof args !== "object") return ""
115
48
  if (typeof args.command === "string") return args.command.slice(0, 200)
116
49
  if (typeof args.file_path === "string") return args.file_path