agent-worker 0.2.0 → 0.3.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/README.md CHANGED
@@ -52,15 +52,23 @@ agent-worker session end --all
52
52
  ### Sending Messages
53
53
 
54
54
  ```bash
55
- # Send to current session
56
- agent-worker send "What is 2+2?"
55
+ # Send to current session (async by default - returns immediately)
56
+ agent-worker send "Analyze this codebase"
57
57
 
58
58
  # Send to specific session
59
59
  agent-worker send "Explain recursion" --to my-session
60
60
 
61
- # View conversation history
62
- agent-worker history
63
- agent-worker history --last 5
61
+ # Send and wait for response (synchronous mode)
62
+ agent-worker send "What is 2+2?" --wait
63
+
64
+ # Send with debug logging (useful for troubleshooting)
65
+ agent-worker send "Debug this" --debug
66
+
67
+ # View conversation messages
68
+ agent-worker peek # Show last 10 messages (default)
69
+ agent-worker peek --last 5 # Show last 5 messages
70
+ agent-worker peek --all # Show all messages
71
+ agent-worker peek --find "error" # Search messages containing "error"
64
72
 
65
73
  # View token usage
66
74
  agent-worker stats
@@ -68,10 +76,58 @@ agent-worker stats
68
76
  # Export transcript
69
77
  agent-worker export > transcript.json
70
78
 
71
- # Clear history (keep session)
79
+ # Clear messages (keep session)
72
80
  agent-worker clear
73
81
  ```
74
82
 
83
+ **Understanding Message Flow:**
84
+
85
+ The CLI supports two modes for sending messages:
86
+
87
+ 1. **Asynchronous (default)**: The command returns immediately after sending. The agent processes in the background. Use `peek` to view the response.
88
+ ```bash
89
+ # Send message (returns immediately)
90
+ agent-worker send "Analyze this large codebase"
91
+ # Output: "Message sent. Use 'peek' command to view response."
92
+
93
+ # View response later
94
+ agent-worker peek --last 2
95
+ ```
96
+
97
+ 2. **Synchronous (`--wait`)**: The command waits for the agent to fully process the message and return a response. This is best for quick questions when you need immediate results.
98
+ ```bash
99
+ agent-worker send "What is 2+2?" --wait
100
+ # Waits for response, then prints: 4
101
+ ```
102
+
103
+ **Troubleshooting:**
104
+
105
+ If `send` appears stuck or times out, use `--debug` to see what's happening:
106
+
107
+ ```bash
108
+ agent-worker send "test message" --debug
109
+ ```
110
+
111
+ Debug output shows:
112
+ - Session lookup and connection status
113
+ - Socket communication
114
+ - Request/response timing
115
+ - Error details
116
+
117
+ **Backend Limitations:**
118
+
119
+ The CLI supports two backend types:
120
+
121
+ 1. **SDK Backend (default)**: Full-featured, works in all environments. Requires `ANTHROPIC_API_KEY` environment variable.
122
+
123
+ 2. **Claude CLI Backend (`-b claude`)**: Uses `claude -p` for non-interactive mode.
124
+ - **Known limitation**: May not work properly within Claude Code environment itself due to command interception
125
+ - **Timeout**: Async requests timeout after 60 seconds to prevent indefinite hangs
126
+ - **Recommended use**: Normal terminal environments outside Claude Code
127
+ - **For testing**: Use SDK backend instead when developing within Claude Code
128
+
129
+ If you see messages stuck in `(processing...)` state for more than 60 seconds, it indicates a backend issue. The message will automatically update to show a timeout error.
130
+
75
131
  ### Tool Management (SDK Backend Only)
76
132
 
77
133
  ```bash
@@ -357,7 +413,7 @@ process.on('exit', async () => {
357
413
  agent-worker session new -f ./my-prompt.txt -n test
358
414
  agent-worker send "Test case 1: ..." --to test
359
415
  agent-worker send "Test case 2: ..." --to test
360
- agent-worker history --to test
416
+ agent-worker peek --to test
361
417
  agent-worker session end test
362
418
  ```
363
419
 
@@ -198,7 +198,12 @@ var ClaudeCliBackend = class {
198
198
  return new Promise((resolve, reject) => {
199
199
  const proc = spawn("claude", args, {
200
200
  cwd: this.options.cwd,
201
- env: process.env
201
+ env: process.env,
202
+ stdio: [
203
+ "ignore",
204
+ "pipe",
205
+ "pipe"
206
+ ]
202
207
  });
203
208
  let stdout = "";
204
209
  let stderr = "";
@@ -1,3 +1,3 @@
1
- import { a as CursorCliBackend, i as SdkBackend, n as createBackend, o as CodexCliBackend, r as listBackends, s as ClaudeCliBackend, t as checkBackends } from "./backends-BGJk-onJ.mjs";
1
+ import { a as CursorCliBackend, i as SdkBackend, n as createBackend, o as CodexCliBackend, r as listBackends, s as ClaudeCliBackend, t as checkBackends } from "./backends-BZ866Ij9.mjs";
2
2
 
3
3
  export { listBackends };
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { c as FRONTIER_MODELS, f as getDefaultModel, n as createBackend } from "../backends-BGJk-onJ.mjs";
3
- import { a as createSkillsTool, o as SkillsProvider, s as AgentSession, t as SkillImporter } from "../skills-B8z8tFaH.mjs";
2
+ import { c as FRONTIER_MODELS, f as getDefaultModel, n as createBackend } from "../backends-BZ866Ij9.mjs";
3
+ import { a as createSkillsTool, o as SkillsProvider, s as AgentSession, t as SkillImporter } from "../skills-CVdxwuvV.mjs";
4
4
  import { spawn } from "node:child_process";
5
5
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
@@ -270,7 +270,7 @@ async function handleRequest(req) {
270
270
  }
271
271
  };
272
272
  case "send": {
273
- const { message, options } = req.payload;
273
+ const { message, options, async } = req.payload;
274
274
  if (backend) {
275
275
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
276
276
  state.cliHistory.push({
@@ -278,6 +278,35 @@ async function handleRequest(req) {
278
278
  content: message,
279
279
  timestamp
280
280
  });
281
+ if (async) {
282
+ state.cliHistory.push({
283
+ role: "assistant",
284
+ content: "(processing...)",
285
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
286
+ });
287
+ const timeoutMs = 6e4;
288
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error("Request timed out after 60 seconds")), timeoutMs));
289
+ Promise.race([backend.send(message, { system: info.system }), timeoutPromise]).then((result) => {
290
+ const lastMsg = state.cliHistory[state.cliHistory.length - 1];
291
+ if (lastMsg && lastMsg.content === "(processing...)") {
292
+ lastMsg.content = result.content;
293
+ lastMsg.timestamp = (/* @__PURE__ */ new Date()).toISOString();
294
+ }
295
+ }).catch((error) => {
296
+ const lastMsg = state.cliHistory[state.cliHistory.length - 1];
297
+ if (lastMsg && lastMsg.content === "(processing...)") {
298
+ lastMsg.content = `Error: ${error instanceof Error ? error.message : String(error)}`;
299
+ lastMsg.timestamp = (/* @__PURE__ */ new Date()).toISOString();
300
+ }
301
+ });
302
+ return {
303
+ success: true,
304
+ data: {
305
+ async: true,
306
+ message: "Processing in background. Use `peek` to check the response."
307
+ }
308
+ };
309
+ }
281
310
  const result = await backend.send(message, { system: info.system });
282
311
  state.cliHistory.push({
283
312
  role: "assistant",
@@ -299,10 +328,24 @@ async function handleRequest(req) {
299
328
  }
300
329
  };
301
330
  }
302
- if (session) return {
303
- success: true,
304
- data: await session.send(message, options)
305
- };
331
+ if (session) {
332
+ if (async) {
333
+ session.send(message, options).catch((error) => {
334
+ console.error("Background send error:", error);
335
+ });
336
+ return {
337
+ success: true,
338
+ data: {
339
+ async: true,
340
+ message: "Processing in background. Use `peek` to check the response."
341
+ }
342
+ };
343
+ }
344
+ return {
345
+ success: true,
346
+ data: await session.send(message, options)
347
+ };
348
+ }
306
349
  return {
307
350
  success: false,
308
351
  error: "No backend configured"
@@ -648,13 +691,19 @@ async function waitForReady(nameOrId, timeoutMs = 5e3) {
648
691
 
649
692
  //#endregion
650
693
  //#region src/cli/client.ts
651
- /**
652
- * Send a request to a specific session
653
- * @param req - The request to send
654
- * @param target - Session ID or name (optional, uses default if not specified)
655
- */
656
- function sendRequest(req, target) {
694
+ function sendRequest(req, targetOrOptions, options) {
695
+ let target;
696
+ let opts = {};
697
+ if (typeof targetOrOptions === "string") {
698
+ target = targetOrOptions;
699
+ opts = options || {};
700
+ } else if (targetOrOptions) {
701
+ opts = targetOrOptions;
702
+ target = opts.target;
703
+ }
704
+ const debug = opts.debug || false;
657
705
  return new Promise((resolve, reject) => {
706
+ if (debug) console.error(`[DEBUG] Looking up session: ${target || "(default)"}`);
658
707
  const info = getSessionInfo(target);
659
708
  if (!info) {
660
709
  if (target) resolve({
@@ -667,6 +716,10 @@ function sendRequest(req, target) {
667
716
  });
668
717
  return;
669
718
  }
719
+ if (debug) {
720
+ console.error(`[DEBUG] Found session: ${info.id} (${info.backend})`);
721
+ console.error(`[DEBUG] Socket path: ${info.socketPath}`);
722
+ }
670
723
  if (!isSessionRunning(target)) {
671
724
  resolve({
672
725
  success: false,
@@ -674,12 +727,22 @@ function sendRequest(req, target) {
674
727
  });
675
728
  return;
676
729
  }
730
+ if (debug) console.error(`[DEBUG] Connecting to socket...`);
677
731
  const socket = createConnection(info.socketPath);
678
732
  let buffer = "";
733
+ const startTime = Date.now();
679
734
  socket.on("connect", () => {
735
+ if (debug) {
736
+ console.error(`[DEBUG] Connected. Sending request:`);
737
+ console.error(`[DEBUG] ${JSON.stringify(req, null, 2)}`);
738
+ }
680
739
  socket.write(JSON.stringify(req) + "\n");
681
740
  });
682
741
  socket.on("data", (data) => {
742
+ if (debug) {
743
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
744
+ console.error(`[DEBUG] Received data after ${elapsed}s: ${data.toString().substring(0, 100)}...`);
745
+ }
683
746
  buffer += data.toString();
684
747
  const lines = buffer.split("\n");
685
748
  buffer = lines.pop() || "";
@@ -687,22 +750,30 @@ function sendRequest(req, target) {
687
750
  if (!line.trim()) continue;
688
751
  try {
689
752
  const res = JSON.parse(line);
753
+ if (debug) {
754
+ const elapsed = ((Date.now() - startTime) / 1e3).toFixed(2);
755
+ console.error(`[DEBUG] Received response after ${elapsed}s`);
756
+ }
690
757
  socket.end();
691
758
  resolve(res);
692
759
  } catch (error) {
760
+ if (debug) console.error(`[DEBUG] Parse error:`, error);
693
761
  socket.end();
694
762
  reject(error);
695
763
  }
696
764
  }
697
765
  });
698
766
  socket.on("error", (error) => {
767
+ if (debug) console.error(`[DEBUG] Socket error:`, error);
699
768
  reject(error);
700
769
  });
701
770
  socket.on("timeout", () => {
771
+ if (debug) console.error(`[DEBUG] Socket timeout after 60s`);
702
772
  socket.end();
703
773
  reject(/* @__PURE__ */ new Error("Connection timeout"));
704
774
  });
705
775
  socket.setTimeout(6e4);
776
+ if (debug) console.error(`[DEBUG] Waiting for response (60s timeout)...`);
706
777
  });
707
778
  }
708
779
  /**
@@ -821,24 +892,32 @@ sessionCmd.command("end [target]").description("End a session (or all with --all
821
892
  if (res.success) console.log("Session ended");
822
893
  else console.error("Error:", res.error);
823
894
  });
824
- program.command("send <message>").description("Send a message").option("--to <target>", "Target session (name or ID)").option("--json", "Output full JSON response").option("--auto-approve", "Auto-approve all tool calls (default)").option("--no-auto-approve", "Require manual approval").action(async (message, options) => {
895
+ program.command("send <message>").description("Send a message (async by default, use --wait to wait for response)").option("--to <target>", "Target session (name or ID)").option("--json", "Output full JSON response").option("--auto-approve", "Auto-approve all tool calls (default)").option("--no-auto-approve", "Require manual approval").option("--wait", "Wait for response before returning (synchronous mode)").option("--debug", "Show debug information").action(async (message, options) => {
825
896
  const target = options.to;
826
897
  if (!isSessionActive(target)) {
827
898
  if (target) console.error(`Session not found: ${target}`);
828
899
  else console.error("No active session. Create one with: agent-worker session new -m <model>");
829
900
  process.exit(1);
830
901
  }
902
+ const autoApprove = options.autoApprove !== false;
903
+ const async = !options.wait;
831
904
  const res = await sendRequest({
832
905
  action: "send",
833
906
  payload: {
834
907
  message,
835
- options: { autoApprove: options.autoApprove !== false }
908
+ options: { autoApprove },
909
+ async
836
910
  }
837
- }, target);
911
+ }, target, { debug: options.debug });
838
912
  if (!res.success) {
839
913
  console.error("Error:", res.error);
840
914
  process.exit(1);
841
915
  }
916
+ if (async) {
917
+ const asyncData = res.data;
918
+ console.log(asyncData.message);
919
+ return;
920
+ }
842
921
  const response = res.data;
843
922
  if (options.json) console.log(JSON.stringify(response, null, 2));
844
923
  else {
@@ -957,7 +1036,7 @@ toolCmd.command("list").description("List tools").option("--to <target>", "Targe
957
1036
  console.log(` ${t.name}${approval}${mock} - ${t.description}`);
958
1037
  }
959
1038
  });
960
- program.command("history").description("Show conversation history").option("--to <target>", "Target session").option("--json", "Output as JSON").option("-n, --last <count>", "Show last N messages", parseInt).action(async (options) => {
1039
+ program.command("peek").description("View conversation messages (default: last 10)").option("--to <target>", "Target session").option("--json", "Output as JSON").option("--all", "Show all messages").option("-n, --last <count>", "Show last N messages", parseInt).option("--find <text>", "Filter messages containing text (case-insensitive)").action(async (options) => {
961
1040
  const target = options.to;
962
1041
  if (!isSessionActive(target)) {
963
1042
  console.error(target ? `Session not found: ${target}` : "No active session");
@@ -968,15 +1047,22 @@ program.command("history").description("Show conversation history").option("--to
968
1047
  console.error("Error:", res.error);
969
1048
  process.exit(1);
970
1049
  }
971
- let history = res.data;
972
- if (options.last && options.last > 0) history = history.slice(-options.last);
973
- if (options.json) console.log(JSON.stringify(history, null, 2));
1050
+ let messages = res.data;
1051
+ if (options.find) {
1052
+ const searchText = options.find.toLowerCase();
1053
+ messages = messages.filter((msg) => msg.content.toLowerCase().includes(searchText));
1054
+ }
1055
+ if (!options.all) {
1056
+ const count = options.last ?? 10;
1057
+ messages = messages.slice(-count);
1058
+ }
1059
+ if (options.json) console.log(JSON.stringify(messages, null, 2));
974
1060
  else {
975
- if (history.length === 0) {
976
- console.log("No messages");
1061
+ if (messages.length === 0) {
1062
+ console.log(options.find ? "No messages found matching your search" : "No messages");
977
1063
  return;
978
1064
  }
979
- for (const msg of history) {
1065
+ for (const msg of messages) {
980
1066
  const role = msg.role === "user" ? "YOU" : msg.role.toUpperCase();
981
1067
  const status = msg.status === "responding" ? " (responding...)" : "";
982
1068
  console.log(`[${role}${status}] ${msg.content}`);
@@ -1146,7 +1232,7 @@ program.command("providers").description("Check provider availability").action((
1146
1232
  console.log(`\nDefault: ${defaultModel} (when no model specified)`);
1147
1233
  });
1148
1234
  program.command("backends").description("Check available backends (SDK, CLI tools)").action(async () => {
1149
- const { listBackends } = await import("../backends-bvhx4Wb6.mjs");
1235
+ const { listBackends } = await import("../backends-DXpJ7FJI.mjs");
1150
1236
  const backends = await listBackends();
1151
1237
  console.log("Backend Status:\n");
1152
1238
  for (const backend of backends) {
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { a as CursorCliBackend, c as FRONTIER_MODELS, d as createModelAsync, i as SdkBackend, l as SUPPORTED_PROVIDERS, n as createBackend, o as CodexCliBackend, r as listBackends, s as ClaudeCliBackend, t as checkBackends, u as createModel } from "./backends-BGJk-onJ.mjs";
2
- import { a as createSkillsTool, c as createTools, i as parseImportSpec, n as buildGitUrl, o as SkillsProvider, r as getSpecDisplayName, s as AgentSession, t as SkillImporter } from "./skills-B8z8tFaH.mjs";
1
+ import { a as CursorCliBackend, c as FRONTIER_MODELS, d as createModelAsync, i as SdkBackend, l as SUPPORTED_PROVIDERS, n as createBackend, o as CodexCliBackend, r as listBackends, s as ClaudeCliBackend, t as checkBackends, u as createModel } from "./backends-BZ866Ij9.mjs";
2
+ import { a as createSkillsTool, c as createTools, i as parseImportSpec, n as buildGitUrl, o as SkillsProvider, r as getSpecDisplayName, s as AgentSession, t as SkillImporter } from "./skills-CVdxwuvV.mjs";
3
3
  import { createBashTool } from "bash-tool";
4
4
 
5
5
  //#region src/tools/bash.ts
@@ -1,4 +1,4 @@
1
- import { d as createModelAsync } from "./backends-BGJk-onJ.mjs";
1
+ import { d as createModelAsync } from "./backends-BZ866Ij9.mjs";
2
2
  import { ToolLoopAgent, jsonSchema, stepCountIs, tool } from "ai";
3
3
  import { spawn } from "node:child_process";
4
4
  import { mkdir, readFile, readdir, rm, stat } from "node:fs/promises";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-worker",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "SDK and CLI for creating and testing agent workers with Vercel AI SDK",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",