ccgateway 0.1.7 → 0.1.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.
- package/dist/async-watcher.d.ts +48 -0
- package/dist/async-watcher.d.ts.map +1 -0
- package/dist/async-watcher.js +183 -0
- package/dist/async-watcher.js.map +1 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +35 -2
- package/dist/daemon.js.map +1 -1
- package/dist/messaging.d.ts.map +1 -1
- package/dist/messaging.js +11 -2
- package/dist/messaging.js.map +1 -1
- package/dist/plugins/slack-gateway.d.ts.map +1 -1
- package/dist/plugins/slack-gateway.js +27 -1
- package/dist/plugins/slack-gateway.js.map +1 -1
- package/dist/router.d.ts +11 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +210 -9
- package/dist/router.js.map +1 -1
- package/dist/spawner.d.ts +44 -5
- package/dist/spawner.d.ts.map +1 -1
- package/dist/spawner.js +278 -19
- package/dist/spawner.js.map +1 -1
- package/package.json +1 -1
package/dist/router.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { getCcgHome } from "./config.js";
|
|
2
|
+
import { writeFile, mkdir, rm } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
1
5
|
// ── MessageRouter ─────────────────────────────────────────────────────────
|
|
2
6
|
export class MessageRouter {
|
|
3
7
|
agents;
|
|
@@ -5,12 +9,14 @@ export class MessageRouter {
|
|
|
5
9
|
context;
|
|
6
10
|
spawner;
|
|
7
11
|
bindings;
|
|
8
|
-
|
|
12
|
+
watcher;
|
|
13
|
+
constructor(agents, sessions, context, spawner, bindings, watcher) {
|
|
9
14
|
this.agents = agents;
|
|
10
15
|
this.sessions = sessions;
|
|
11
16
|
this.context = context;
|
|
12
17
|
this.spawner = spawner;
|
|
13
18
|
this.bindings = bindings;
|
|
19
|
+
this.watcher = watcher;
|
|
14
20
|
}
|
|
15
21
|
/**
|
|
16
22
|
* Resolve which agent handles a message based on bindings.
|
|
@@ -58,23 +64,107 @@ export class MessageRouter {
|
|
|
58
64
|
sourceUser: message.from.user,
|
|
59
65
|
sourceMessageId: message.from.messageId,
|
|
60
66
|
});
|
|
61
|
-
// 4.
|
|
67
|
+
// 4. Download attachments (if any)
|
|
68
|
+
// Images → base64 in-memory, passed as content blocks (no Read-tool round-trip)
|
|
69
|
+
// Other → saved to temp dir so Claude can read them via the Read tool
|
|
70
|
+
let attachmentDir;
|
|
71
|
+
let messageContent = message.content;
|
|
72
|
+
const images = [];
|
|
73
|
+
if (message.attachments.length > 0) {
|
|
74
|
+
const result = await this.downloadAttachments(message.attachments);
|
|
75
|
+
attachmentDir = result.dir;
|
|
76
|
+
images.push(...result.images);
|
|
77
|
+
if (result.filePaths.length > 0) {
|
|
78
|
+
const fileList = result.filePaths
|
|
79
|
+
.map((p) => ` - ${p}`)
|
|
80
|
+
.join("\n");
|
|
81
|
+
messageContent += `\n\n[Attached files — use the Read tool to view them]\n${fileList}`;
|
|
82
|
+
}
|
|
83
|
+
if (result.rejected.length > 0) {
|
|
84
|
+
const rejectedList = result.rejected.join(", ");
|
|
85
|
+
messageContent += `\n\n[Rejected attachments (blocked file type): ${rejectedList}]`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// 5. Build context
|
|
62
89
|
const systemPrompt = await this.context.build(agentId, sessionKey);
|
|
63
|
-
// 5.
|
|
90
|
+
// 5.5 Triage: should this run async?
|
|
91
|
+
// Images always go async — they're slow on Opus and the user gets
|
|
92
|
+
// instant feedback instead of waiting 10+ minutes.
|
|
93
|
+
const mode = this.watcher
|
|
94
|
+
? images.length > 0
|
|
95
|
+
? "async"
|
|
96
|
+
: await this.spawner.triage(messageContent, agent.model)
|
|
97
|
+
: "sync";
|
|
98
|
+
if (mode === "async") {
|
|
99
|
+
// For async tasks with images: save images to temp files in the
|
|
100
|
+
// workspace so Claude Code can read them via the Read tool.
|
|
101
|
+
let asyncMessage = messageContent;
|
|
102
|
+
let asyncAttachDir;
|
|
103
|
+
if (images.length > 0) {
|
|
104
|
+
const dir = join(agent.workspace, `.ccg-attachments-${Date.now()}`);
|
|
105
|
+
await mkdir(dir, { recursive: true });
|
|
106
|
+
asyncAttachDir = dir;
|
|
107
|
+
const paths = [];
|
|
108
|
+
for (let i = 0; i < images.length; i++) {
|
|
109
|
+
const ext = images[i].mediaType.split("/")[1] || "png";
|
|
110
|
+
const filePath = join(dir, `image-${i}.${ext}`);
|
|
111
|
+
await writeFile(filePath, Buffer.from(images[i].base64, "base64"));
|
|
112
|
+
paths.push(filePath);
|
|
113
|
+
}
|
|
114
|
+
const fileList = paths.map((p) => ` - ${p}`).join("\n");
|
|
115
|
+
asyncMessage += `\n\n[Attached images — use the Read tool to view them]\n${fileList}`;
|
|
116
|
+
}
|
|
117
|
+
const { sessionName, taskDir } = await this.spawner.spawnAsync({
|
|
118
|
+
workspace: agent.workspace,
|
|
119
|
+
message: asyncMessage,
|
|
120
|
+
systemPrompt,
|
|
121
|
+
model: agent.model,
|
|
122
|
+
ccgHome: getCcgHome(),
|
|
123
|
+
agentId,
|
|
124
|
+
});
|
|
125
|
+
// Register with watcher
|
|
126
|
+
const binding = this.bindings.find((b) => b.agent === agentId);
|
|
127
|
+
this.watcher.register({
|
|
128
|
+
sessionName,
|
|
129
|
+
taskDir,
|
|
130
|
+
agentId,
|
|
131
|
+
gateway: message.from.gateway,
|
|
132
|
+
channel: message.from.channel,
|
|
133
|
+
botId: binding?.bot ?? agentId,
|
|
134
|
+
sessionKey,
|
|
135
|
+
workspace: agent.workspace,
|
|
136
|
+
startedAt: Date.now(),
|
|
137
|
+
});
|
|
138
|
+
const placeholder = `On it — working on this in the background. I'll get back to you when it's done. (tmux: \`${sessionName}\`)`;
|
|
139
|
+
await this.sessions.appendMessage(agentId, sessionKey, {
|
|
140
|
+
role: "assistant",
|
|
141
|
+
content: placeholder,
|
|
142
|
+
ts: Date.now(),
|
|
143
|
+
tokens: { in: 0, out: 0 },
|
|
144
|
+
});
|
|
145
|
+
return placeholder;
|
|
146
|
+
}
|
|
147
|
+
// 6. Spawn claude --print (sync path — unchanged)
|
|
64
148
|
const result = await this.spawner.spawn({
|
|
65
149
|
workspace: agent.workspace,
|
|
66
|
-
message:
|
|
150
|
+
message: messageContent,
|
|
67
151
|
systemPrompt,
|
|
68
152
|
model: agent.model,
|
|
69
153
|
allowedTools: agent.allowedTools,
|
|
70
154
|
...(agent.timeoutMs ? { timeoutMs: agent.timeoutMs } : {}),
|
|
155
|
+
...(images.length > 0 ? { images } : {}),
|
|
71
156
|
});
|
|
72
|
-
//
|
|
157
|
+
// 7. Clean up attachment temp dir
|
|
158
|
+
if (attachmentDir) {
|
|
159
|
+
rm(attachmentDir, { recursive: true, force: true }).catch(() => { });
|
|
160
|
+
}
|
|
161
|
+
// 8. Handle failure: append error to session and throw
|
|
73
162
|
if (result.exitCode !== 0) {
|
|
74
163
|
const isTimeout = result.exitCode === 124;
|
|
164
|
+
const stderrHint = result.stderr ? `\n\nDetails: ${result.stderr.slice(0, 500)}` : "";
|
|
75
165
|
const errorContent = isTimeout
|
|
76
166
|
? "The task timed out — it took longer than the allowed time. Try breaking it into smaller steps, or increase the agent's `timeoutMs` setting."
|
|
77
|
-
: result.response || `Spawner failed with exit code ${result.exitCode}
|
|
167
|
+
: (result.response || `Spawner failed with exit code ${result.exitCode}`) + stderrHint;
|
|
78
168
|
await this.sessions.appendMessage(agentId, sessionKey, {
|
|
79
169
|
role: "assistant",
|
|
80
170
|
content: `[error] ${errorContent}`,
|
|
@@ -83,15 +173,15 @@ export class MessageRouter {
|
|
|
83
173
|
});
|
|
84
174
|
throw new Error(errorContent);
|
|
85
175
|
}
|
|
86
|
-
//
|
|
176
|
+
// 9. Append assistant response to session
|
|
87
177
|
await this.sessions.appendMessage(agentId, sessionKey, {
|
|
88
178
|
role: "assistant",
|
|
89
179
|
content: result.response,
|
|
90
180
|
ts: Date.now(),
|
|
91
181
|
tokens: result.tokensEstimate,
|
|
92
182
|
});
|
|
93
|
-
//
|
|
94
|
-
return result.response;
|
|
183
|
+
// 10. Return response text (guard against empty responses)
|
|
184
|
+
return result.response.trim() || "(no response)";
|
|
95
185
|
}
|
|
96
186
|
/**
|
|
97
187
|
* Add a binding at runtime.
|
|
@@ -111,5 +201,116 @@ export class MessageRouter {
|
|
|
111
201
|
getPrimaryBinding(agentId) {
|
|
112
202
|
return this.bindings.find((b) => b.agent === agentId);
|
|
113
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* Download attachments, separating images (kept as base64 in-memory)
|
|
206
|
+
* from other files (saved to a temp directory for Read-tool access).
|
|
207
|
+
* Rejects blocked file types (executables, archives, etc.).
|
|
208
|
+
*/
|
|
209
|
+
async downloadAttachments(attachments) {
|
|
210
|
+
const dir = join(tmpdir(), `ccg-attach-${Date.now()}`);
|
|
211
|
+
const filePaths = [];
|
|
212
|
+
const images = [];
|
|
213
|
+
const rejected = [];
|
|
214
|
+
let dirCreated = false;
|
|
215
|
+
for (const att of attachments) {
|
|
216
|
+
if (!att.url && !att.data)
|
|
217
|
+
continue;
|
|
218
|
+
const filename = att.filename || "attachment";
|
|
219
|
+
if (isBlockedAttachment(att.type, filename)) {
|
|
220
|
+
rejected.push(filename);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
// Use pre-downloaded data if available, otherwise fetch from URL
|
|
225
|
+
let buffer;
|
|
226
|
+
if (att.data) {
|
|
227
|
+
buffer = att.data;
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
const resp = await fetch(att.url);
|
|
231
|
+
if (!resp.ok)
|
|
232
|
+
continue;
|
|
233
|
+
buffer = Buffer.from(await resp.arrayBuffer());
|
|
234
|
+
}
|
|
235
|
+
if (att.type.startsWith("image/")) {
|
|
236
|
+
images.push({
|
|
237
|
+
base64: buffer.toString("base64"),
|
|
238
|
+
mediaType: att.type,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
if (!dirCreated) {
|
|
243
|
+
await mkdir(dir, { recursive: true });
|
|
244
|
+
dirCreated = true;
|
|
245
|
+
}
|
|
246
|
+
const filePath = join(dir, filename);
|
|
247
|
+
await writeFile(filePath, buffer);
|
|
248
|
+
filePaths.push(filePath);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
// Skip failed downloads
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return { dir, filePaths, images, rejected };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// ── Attachment filtering ──────────────────────────────────────────────────
|
|
259
|
+
/** MIME types that are never allowed through. */
|
|
260
|
+
const BLOCKED_MIME_PREFIXES = [
|
|
261
|
+
"application/x-executable",
|
|
262
|
+
"application/x-msdos-program",
|
|
263
|
+
"application/x-msdownload",
|
|
264
|
+
"application/x-sharedlib",
|
|
265
|
+
"application/x-dosexec",
|
|
266
|
+
"application/vnd.microsoft.portable-executable",
|
|
267
|
+
];
|
|
268
|
+
const BLOCKED_MIME_EXACT = new Set([
|
|
269
|
+
"application/x-sh",
|
|
270
|
+
"application/x-csh",
|
|
271
|
+
"application/x-bat",
|
|
272
|
+
"application/x-msi",
|
|
273
|
+
"application/java-archive",
|
|
274
|
+
"application/x-rar-compressed",
|
|
275
|
+
"application/x-7z-compressed",
|
|
276
|
+
"application/x-tar",
|
|
277
|
+
"application/gzip",
|
|
278
|
+
"application/zip",
|
|
279
|
+
"application/x-bzip2",
|
|
280
|
+
"application/x-xz",
|
|
281
|
+
"application/x-iso9660-image",
|
|
282
|
+
"application/x-apple-diskimage",
|
|
283
|
+
"application/vnd.debian.binary-package",
|
|
284
|
+
"application/x-rpm",
|
|
285
|
+
]);
|
|
286
|
+
/** File extensions that are never allowed through (lowercase, with dot). */
|
|
287
|
+
const BLOCKED_EXTENSIONS = new Set([
|
|
288
|
+
// Executables & scripts
|
|
289
|
+
".exe", ".bat", ".cmd", ".com", ".msi", ".scr", ".pif",
|
|
290
|
+
".sh", ".bash", ".csh", ".ksh", ".zsh",
|
|
291
|
+
".ps1", ".psm1", ".psd1", ".vbs", ".vbe", ".wsf", ".wsh",
|
|
292
|
+
// Compiled / bytecode
|
|
293
|
+
".dll", ".so", ".dylib", ".sys", ".drv", ".o", ".obj",
|
|
294
|
+
".class", ".jar", ".war", ".ear",
|
|
295
|
+
// Archives
|
|
296
|
+
".zip", ".tar", ".gz", ".tgz", ".bz2", ".xz", ".7z",
|
|
297
|
+
".rar", ".iso", ".dmg", ".img",
|
|
298
|
+
// Packages
|
|
299
|
+
".deb", ".rpm", ".apk", ".snap", ".flatpak",
|
|
300
|
+
".whl", ".gem", ".nupkg",
|
|
301
|
+
]);
|
|
302
|
+
/** Returns true if the attachment should be rejected. */
|
|
303
|
+
export function isBlockedAttachment(mimeType, filename) {
|
|
304
|
+
const mime = mimeType.toLowerCase();
|
|
305
|
+
if (BLOCKED_MIME_EXACT.has(mime))
|
|
306
|
+
return true;
|
|
307
|
+
if (BLOCKED_MIME_PREFIXES.some((p) => mime.startsWith(p)))
|
|
308
|
+
return true;
|
|
309
|
+
const ext = filename.lastIndexOf(".") >= 0
|
|
310
|
+
? filename.slice(filename.lastIndexOf(".")).toLowerCase()
|
|
311
|
+
: "";
|
|
312
|
+
if (ext && BLOCKED_EXTENSIONS.has(ext))
|
|
313
|
+
return true;
|
|
314
|
+
return false;
|
|
114
315
|
}
|
|
115
316
|
//# sourceMappingURL=router.js.map
|
package/dist/router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAMA,6EAA6E;AAE7E,MAAM,OAAO,aAAa;IAEd;IACA;IACA;IACA;IACA;
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,6EAA6E;AAE7E,MAAM,OAAO,aAAa;IAEd;IACA;IACA;IACA;IACA;IACA;IANV,YACU,MAAqB,EACrB,QAAwB,EACxB,OAAuB,EACvB,OAAkB,EAClB,QAAyB,EACzB,OAA0B;QAL1B,WAAM,GAAN,MAAM,CAAe;QACrB,aAAQ,GAAR,QAAQ,CAAgB;QACxB,YAAO,GAAP,OAAO,CAAgB;QACvB,YAAO,GAAP,OAAO,CAAW;QAClB,aAAQ,GAAR,QAAQ,CAAiB;QACzB,YAAO,GAAP,OAAO,CAAmB;IACjC,CAAC;IAEJ;;;OAGG;IACH,YAAY,CAAC,OAAe,EAAE,SAAiB;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,CACxD,CAAC;QACF,OAAO,OAAO,EAAE,KAAK,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,iBAAiB,CAAC,OAAe,EAAE,KAAa;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAChC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,KAAK,CAChD,CAAC;QACF,OAAO,OAAO,EAAE,KAAK,CAAC;IACxB,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,MAAM,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC;QAEjC,sBAAsB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,UAAU,OAAO,yBAAyB,CAAC,CAAC;QAC9D,CAAC;QAED,wBAAwB;QACxB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CACjD,OAAO,EACP,OAAO,CAAC,IAAI,CAAC,OAAO,EACpB,OAAO,CAAC,IAAI,CAAC,OAAO,CACrB,CAAC;QAEF,oCAAoC;QACpC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE;YACrD,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO;YAC5B,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;YAC7B,eAAe,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS;SACxC,CAAC,CAAC;QAEH,mCAAmC;QACnC,oFAAoF;QACpF,2EAA2E;QAC3E,IAAI,aAAiC,CAAC;QACtC,IAAI,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;QACrC,MAAM,MAAM,GAAiB,EAAE,CAAC;QAEhC,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YACnE,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAE9B,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS;qBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;qBACtB,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,cAAc,IAAI,0DAA0D,QAAQ,EAAE,CAAC;YACzF,CAAC;YAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChD,cAAc,IAAI,kDAAkD,YAAY,GAAG,CAAC;YACtF,CAAC;QACH,CAAC;QAED,mBAAmB;QACnB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAEnE,qCAAqC;QACrC,sEAAsE;QACtE,uDAAuD;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO;YACvB,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAE,OAAiB;gBACpB,CAAC,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC;YAC1D,CAAC,CAAE,MAAgB,CAAC;QAEtB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,gEAAgE;YAChE,4DAA4D;YAC5D,IAAI,YAAY,GAAG,cAAc,CAAC;YAClC,IAAI,cAAkC,CAAC;YAEvC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,oBAAoB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACpE,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtC,cAAc,GAAG,GAAG,CAAC;gBAErB,MAAM,KAAK,GAAa,EAAE,CAAC;gBAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACvC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;oBACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;oBAChD,MAAM,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;oBACnE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;gBACD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACzD,YAAY,IAAI,2DAA2D,QAAQ,EAAE,CAAC;YACxF,CAAC;YAED,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;gBAC7D,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,OAAO,EAAE,YAAY;gBACrB,YAAY;gBACZ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,UAAU,EAAE;gBACrB,OAAO;aACR,CAAC,CAAC;YAEH,wBAAwB;YACxB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;YAC/D,IAAI,CAAC,OAAQ,CAAC,QAAQ,CAAC;gBACrB,WAAW;gBACX,OAAO;gBACP,OAAO;gBACP,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO;gBAC7B,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO;gBAC7B,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,OAAO;gBAC9B,UAAU;gBACV,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,4FAA4F,WAAW,KAAK,CAAC;YACjI,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE;gBACrD,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW;gBACpB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;aAC1B,CAAC,CAAC;YAEH,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,kDAAkD;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACtC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,cAAc;YACvB,YAAY;YACZ,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzC,CAAC,CAAC;QAEH,kCAAkC;QAClC,IAAI,aAAa,EAAE,CAAC;YAClB,EAAE,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtE,CAAC;QAED,uDAAuD;QACvD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,KAAK,GAAG,CAAC;YAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,MAAM,YAAY,GAAG,SAAS;gBAC5B,CAAC,CAAC,6IAA6I;gBAC/I,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,IAAI,iCAAiC,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,UAAU,CAAC;YACzF,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE;gBACrD,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW,YAAY,EAAE;gBAClC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,MAAM,EAAE,MAAM,CAAC,cAAc;aAC9B,CAAC,CAAC;YACH,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;QAChC,CAAC;QAED,0CAA0C;QAC1C,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE;YACrD,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,MAAM,CAAC,QAAQ;YACxB,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,MAAM,EAAE,MAAM,CAAC,cAAc;SAC9B,CAAC,CAAC;QAEH,2DAA2D;QAC3D,OAAO,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,eAAe,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,OAAsB;QAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,OAAe;QACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,OAAe;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,mBAAmB,CAC/B,WAAyB;QAEzB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvD,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,UAAU,GAAG,KAAK,CAAC;QAEvB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI;gBAAE,SAAS;YAEpC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,YAAY,CAAC;YAE9C,IAAI,mBAAmB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACxB,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,iEAAiE;gBACjE,IAAI,MAAc,CAAC;gBACnB,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;gBACpB,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAI,CAAC,CAAC;oBACnC,IAAI,CAAC,IAAI,CAAC,EAAE;wBAAE,SAAS;oBACvB,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;gBACjD,CAAC;gBAED,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAClC,MAAM,CAAC,IAAI,CAAC;wBACV,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBACjC,SAAS,EAAE,GAAG,CAAC,IAAI;qBACpB,CAAC,CAAC;gBACL,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,UAAU,EAAE,CAAC;wBAChB,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;wBACtC,UAAU,GAAG,IAAI,CAAC;oBACpB,CAAC;oBACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;oBACrC,MAAM,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAClC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;QAED,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9C,CAAC;CACF;AAED,6EAA6E;AAE7E,iDAAiD;AACjD,MAAM,qBAAqB,GAAG;IAC5B,0BAA0B;IAC1B,6BAA6B;IAC7B,0BAA0B;IAC1B,yBAAyB;IACzB,uBAAuB;IACvB,+CAA+C;CAChD,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,kBAAkB;IAClB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;IACnB,0BAA0B;IAC1B,8BAA8B;IAC9B,6BAA6B;IAC7B,mBAAmB;IACnB,kBAAkB;IAClB,iBAAiB;IACjB,qBAAqB;IACrB,kBAAkB;IAClB,6BAA6B;IAC7B,+BAA+B;IAC/B,uCAAuC;IACvC,mBAAmB;CACpB,CAAC,CAAC;AAEH,4EAA4E;AAC5E,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,wBAAwB;IACxB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACtD,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACtC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACxD,sBAAsB;IACtB,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IACrD,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAChC,WAAW;IACX,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;IACnD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC9B,WAAW;IACX,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU;IAC3C,MAAM,EAAE,MAAM,EAAE,QAAQ;CACzB,CAAC,CAAC;AAEH,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,QAAgB;IACpE,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAEpC,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvE,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QACxC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;QACzD,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,GAAG,IAAI,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAEpD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/spawner.d.ts
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
export interface SpawnResult {
|
|
2
2
|
response: string;
|
|
3
|
+
stderr: string;
|
|
3
4
|
exitCode: number;
|
|
4
5
|
tokensEstimate: {
|
|
5
6
|
in: number;
|
|
6
7
|
out: number;
|
|
7
8
|
};
|
|
8
9
|
}
|
|
10
|
+
export interface ImageInput {
|
|
11
|
+
base64: string;
|
|
12
|
+
mediaType: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AsyncSpawnOptions {
|
|
15
|
+
workspace: string;
|
|
16
|
+
message: string;
|
|
17
|
+
systemPrompt: string;
|
|
18
|
+
model: string;
|
|
19
|
+
ccgHome: string;
|
|
20
|
+
agentId: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AsyncSpawnResult {
|
|
23
|
+
sessionName: string;
|
|
24
|
+
taskDir: string;
|
|
25
|
+
}
|
|
9
26
|
export interface SpawnOptions {
|
|
10
27
|
workspace: string;
|
|
11
28
|
message: string;
|
|
@@ -13,17 +30,39 @@ export interface SpawnOptions {
|
|
|
13
30
|
model: string;
|
|
14
31
|
allowedTools: string[];
|
|
15
32
|
timeoutMs?: number;
|
|
33
|
+
/** When provided, switches to --input-format stream-json so images are
|
|
34
|
+
* sent as content blocks directly (no Read-tool round-trip). */
|
|
35
|
+
images?: ImageInput[];
|
|
16
36
|
}
|
|
17
37
|
export declare class CCSpawner {
|
|
38
|
+
private static readonly TRIAGE_TIMEOUT_MS;
|
|
39
|
+
private static readonly TRIAGE_PROMPT;
|
|
18
40
|
/**
|
|
19
|
-
*
|
|
41
|
+
* Run a quick `claude --print` with Sonnet to classify a message as
|
|
42
|
+
* "sync" (quick task) or "async" (intensive, long-running).
|
|
20
43
|
*
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
|
|
44
|
+
* Defaults to "sync" on timeout, unexpected output, or errors.
|
|
45
|
+
*/
|
|
46
|
+
triage(message: string, _model: string): Promise<"sync" | "async">;
|
|
47
|
+
/**
|
|
48
|
+
* Spawn a `claude --print` invocation.
|
|
24
49
|
*
|
|
25
|
-
*
|
|
50
|
+
* When `images` are provided, uses `--input-format stream-json` to pass
|
|
51
|
+
* image content blocks directly via stdin (avoids the Read-tool
|
|
52
|
+
* round-trip). Otherwise falls back to the simpler `-p "<message>"` form
|
|
53
|
+
* with stdin closed.
|
|
26
54
|
*/
|
|
27
55
|
spawn(options: SpawnOptions): Promise<SpawnResult>;
|
|
56
|
+
private detectMultiplexer;
|
|
57
|
+
spawnAsync(options: AsyncSpawnOptions): Promise<AsyncSpawnResult>;
|
|
58
|
+
private spawnText;
|
|
59
|
+
private spawnStreamJson;
|
|
28
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Extract the assistant's text response from stream-json JSONL output.
|
|
63
|
+
*
|
|
64
|
+
* Looks for a `{"type":"result","result":"..."}` event first (final output),
|
|
65
|
+
* then falls back to collecting text from assistant message content blocks.
|
|
66
|
+
*/
|
|
67
|
+
export declare function parseStreamOutput(stdout: string): string;
|
|
29
68
|
//# sourceMappingURL=spawner.d.ts.map
|
package/dist/spawner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;qEACiE;IACjE,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAOD,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAU;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAIxB;IAEb;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC;IA8CxE;;;;;;;OAOG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAOxD,OAAO,CAAC,iBAAiB;IAoBnB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAiCvE,OAAO,CAAC,SAAS;IAkFjB,OAAO,CAAC,eAAe;CAmHxB;AAID;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAyCxD"}
|