agent-ticketing 0.1.0 → 0.1.1

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
@@ -1,6 +1,6 @@
1
1
  # agent-ticketing
2
2
 
3
- Agent SDK for **Agent Mailbox** — claim tickets, heartbeat, ask the requester, complete. Zero dependencies, Node 18+.
3
+ Agent SDK for **Agent Ticketing** — claim tickets, heartbeat, ask the requester, complete. Zero dependencies, Node 18+.
4
4
 
5
5
  ```bash
6
6
  npm install agent-ticketing # (or use it from this repo via workspaces)
@@ -12,7 +12,7 @@ npm install agent-ticketing # (or use it from this repo via workspaces)
12
12
  import { MailboxAgent } from "agent-ticketing";
13
13
 
14
14
  const mailbox = new MailboxAgent({
15
- baseUrl: "https://agent-mailbox.<you>.workers.dev",
15
+ baseUrl: "https://agent-ticketing.<you>.workers.dev",
16
16
  apiKey: process.env.MAILBOX_API_KEY, // mbx_live_… from Settings → Agents
17
17
  });
18
18
 
@@ -59,9 +59,14 @@ NOT keep the Durable Object hot, so pick the mode by latency preference, not cos
59
59
  the thinking, the ticket is completed with its output.
60
60
 
61
61
  ```bash
62
- MAILBOX_URL=https://… MAILBOX_API_KEY=mbx_live_… node examples/runner-claude.mjs --interval 5m
62
+ MAILBOX_URL=https://… MAILBOX_API_KEY=mbx_live_… \
63
+ npx -y -p agent-ticketing mailbox-claude-runner # add --interval 5m for lazy polling
63
64
  ```
64
65
 
66
+ Runners are agent-specific — `mailbox-claude-runner` launches headless **Claude Code**
67
+ sessions. Runners for Codex and daemon-style agents (Hermes, OpenClaw) are planned;
68
+ for a custom harness, embed the SDK instead (below).
69
+
65
70
  ## Low-level client
66
71
 
67
72
  Every REST endpoint is also exposed directly if you don't want the loop:
package/dist/runner.js CHANGED
@@ -7,11 +7,9 @@
7
7
  * MAILBOX_URL=https://…workers.dev MAILBOX_API_KEY=mbx_live_… \
8
8
  * npx @mailbox/agent # or: mailbox-claude-runner [--interval 5m] [--once]
9
9
  */
10
- import { execFile } from "node:child_process";
10
+ import { spawn } from "node:child_process";
11
11
  import { appendFileSync } from "node:fs";
12
- import { promisify } from "node:util";
13
12
  import { MailboxAgent } from "./index.js";
14
- const exec = promisify(execFile);
15
13
  const baseUrl = process.env.MAILBOX_URL;
16
14
  const apiKey = process.env.MAILBOX_API_KEY;
17
15
  if (!baseUrl || !apiKey) {
@@ -50,14 +48,50 @@ function promptFor(ticket, messages) {
50
48
  thread,
51
49
  ].join("\n");
52
50
  }
51
+ /**
52
+ * Run `claude -p` with the prompt on STDIN (immune to ARG_MAX for long threads,
53
+ * keeps ticket text out of `ps`). On failure, the error carries the exit code
54
+ * AND the stderr tail — so the release reason / ndjson log show the real cause.
55
+ */
56
+ function runClaude(prompt, signal) {
57
+ return new Promise((resolve, reject) => {
58
+ // The runner is often launched from INSIDE a Claude session (setup prompt);
59
+ // strip nested-session markers so the child behaves like a fresh CLI run.
60
+ const env = { ...process.env };
61
+ delete env.CLAUDECODE;
62
+ delete env.CLAUDE_CODE_ENTRYPOINT;
63
+ const child = spawn(claudeCmd, ["-p", "--output-format", "text"], {
64
+ env,
65
+ signal,
66
+ timeout: 10 * 60 * 1000,
67
+ stdio: ["pipe", "pipe", "pipe"],
68
+ });
69
+ let stdout = "";
70
+ let stderr = "";
71
+ child.stdout.on("data", (d) => {
72
+ if (stdout.length < 10 * 1024 * 1024)
73
+ stdout += d.toString();
74
+ });
75
+ child.stderr.on("data", (d) => {
76
+ if (stderr.length < 1024 * 1024)
77
+ stderr += d.toString();
78
+ });
79
+ child.on("error", (e) => reject(new Error(`could not run "${claudeCmd}": ${e.message}`)));
80
+ child.on("close", (code, sig) => {
81
+ if (code === 0)
82
+ return resolve(stdout);
83
+ const tail = stderr.trim().slice(-600) || stdout.trim().slice(-600) || "(no output)";
84
+ reject(new Error(`${claudeCmd} exited with ${sig ? `signal ${sig}` : `code ${code}`}: ${tail}`));
85
+ });
86
+ child.stdin.on("error", () => undefined); // child died before reading stdin; close() reports it
87
+ child.stdin.write(prompt);
88
+ child.stdin.end();
89
+ });
90
+ }
53
91
  const controller = new AbortController();
54
92
  await mailbox.poll(async (ticket, ctx) => {
55
93
  await ctx.progress("launching headless Claude Code session");
56
- const { stdout } = await exec(claudeCmd, ["-p", promptFor(ticket, ctx.messages), "--output-format", "text"], {
57
- timeout: 10 * 60 * 1000,
58
- maxBuffer: 10 * 1024 * 1024,
59
- signal: ctx.signal,
60
- });
94
+ const stdout = await runClaude(promptFor(ticket, ctx.messages), ctx.signal);
61
95
  const result = stdout.trim();
62
96
  if (!result)
63
97
  throw new Error("claude produced no output");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-ticketing",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Agent SDK for Agent Mailbox — poll tickets, heartbeat, ask the requester, complete. Zero dependencies.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "repository": {
33
33
  "type": "git",
34
- "url": "https://github.com/terryds/agent-mailbox"
34
+ "url": "https://github.com/terryds/agent-ticketing"
35
35
  },
36
36
  "license": "MIT",
37
37
  "keywords": [