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 +8 -3
- package/dist/runner.js +42 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# agent-ticketing
|
|
2
2
|
|
|
3
|
-
Agent SDK for **Agent
|
|
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-
|
|
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_…
|
|
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 {
|
|
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
|
|
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.
|
|
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-
|
|
34
|
+
"url": "https://github.com/terryds/agent-ticketing"
|
|
35
35
|
},
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"keywords": [
|