opencara 0.104.1 → 0.105.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/dist/bin.js CHANGED
@@ -273,7 +273,6 @@ var DeviceToServerMessageSchema = z4.union([
273
273
  LogFrameSchema,
274
274
  RunDoneSchema,
275
275
  PongSchema,
276
- AgentCallSchema,
277
276
  AgentCallRequestSchema
278
277
  ]);
279
278
  var HostRegisterRequestSchema = z4.object({
@@ -455,9 +454,6 @@ var WsClient = class {
455
454
  }
456
455
  };
457
456
 
458
- // src/runner/spawn.ts
459
- import { spawn as spawn3 } from "node:child_process";
460
-
461
457
  // src/runner/acpRunner.ts
462
458
  import { existsSync as existsSync3 } from "node:fs";
463
459
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -1187,100 +1183,8 @@ function resolveLocalAcpAdapter(command, args) {
1187
1183
  return { command, args: [...args] };
1188
1184
  }
1189
1185
 
1190
- // src/runner/spawn.ts
1191
- function runJob(spec, stdinJson, handlers) {
1192
- return new Promise((resolve, reject) => {
1193
- const child = spawn3(spec.command, spec.args ?? [], {
1194
- env: { ...process.env, ...spec.env ?? {} },
1195
- cwd: spec.cwd,
1196
- stdio: ["pipe", "pipe", "pipe"]
1197
- });
1198
- child.stdout.setEncoding("utf8");
1199
- child.stderr.setEncoding("utf8");
1200
- child.stdout.on("data", (c) => handlers.onLog("stdout", c));
1201
- child.stderr.on("data", (c) => handlers.onLog("stderr", c));
1202
- child.on("error", reject);
1203
- child.on("close", (code) => resolve({ exitCode: code ?? -1 }));
1204
- if (stdinJson !== void 0) {
1205
- try {
1206
- child.stdin.end(JSON.stringify(stdinJson));
1207
- } catch (err) {
1208
- child.kill();
1209
- reject(err);
1210
- return;
1211
- }
1212
- } else {
1213
- child.stdin.end();
1214
- }
1215
- });
1216
- }
1217
-
1218
- // src/runner/agentCallParser.ts
1219
- import { z as z6 } from "zod";
1220
- var MAX_BUFFER_BYTES = 64 * 1024;
1221
- var FENCE_RE = /```opencara-call\r?\n([\s\S]*?)\r?\n```/;
1222
- var VARIANT_SCHEMAS = {
1223
- "issue.body.set": IssueBodySetCallSchema.omit({ type: true, runId: true }),
1224
- "flow.node.config.set": FlowNodeConfigSetCallSchema.omit({
1225
- type: true,
1226
- runId: true
1227
- }),
1228
- "template.node.config.set": TemplateNodeConfigSetCallSchema.omit({
1229
- type: true,
1230
- runId: true
1231
- })
1232
- };
1233
- var KindSchema = z6.enum([
1234
- "issue.body.set",
1235
- "flow.node.config.set",
1236
- "template.node.config.set"
1237
- ]);
1238
- var AgentCallParser = class {
1239
- constructor(emit) {
1240
- this.emit = emit;
1241
- }
1242
- emit;
1243
- buffer = "";
1244
- feed(chunk) {
1245
- this.buffer += chunk;
1246
- if (this.buffer.length > MAX_BUFFER_BYTES) {
1247
- const cutoff = Math.floor(MAX_BUFFER_BYTES / 2);
1248
- const nl = this.buffer.indexOf("\n", this.buffer.length - cutoff);
1249
- this.buffer = nl >= 0 ? this.buffer.slice(nl + 1) : this.buffer.slice(-cutoff);
1250
- }
1251
- while (true) {
1252
- const m = FENCE_RE.exec(this.buffer);
1253
- if (!m) break;
1254
- const inner = m[1] ?? "";
1255
- const consumedTo = m.index + m[0].length;
1256
- this.buffer = this.buffer.slice(consumedTo);
1257
- this.tryEmit(inner);
1258
- }
1259
- }
1260
- tryEmit(inner) {
1261
- let parsed;
1262
- try {
1263
- parsed = JSON.parse(inner);
1264
- } catch {
1265
- return;
1266
- }
1267
- if (!parsed || typeof parsed !== "object") return;
1268
- const raw = parsed;
1269
- const kindResult = KindSchema.safeParse(raw.kind);
1270
- if (!kindResult.success) return;
1271
- const withCallId = {
1272
- ...raw,
1273
- callId: typeof raw.callId === "string" && raw.callId.length > 0 ? raw.callId : `call_${Date.now().toString(36)}`
1274
- };
1275
- const schema = VARIANT_SCHEMAS[kindResult.data];
1276
- const result = schema.safeParse(withCallId);
1277
- if (!result.success) return;
1278
- this.emit(result.data);
1279
- }
1280
- };
1281
-
1282
1186
  // src/commands/run.ts
1283
- var PKG_VERSION = "0.104.1";
1187
+ var PKG_VERSION = "0.105.0";
1284
1188
  var LOG_FLUSH_MS = 800;
1285
1189
  var MAX_CHUNK_SIZE = 4 * 1024;
1286
1190
  async function run(opts = {}) {
@@ -1300,12 +1204,11 @@ async function run(opts = {}) {
1300
1204
  type: "hello",
1301
1205
  platform: platform(),
1302
1206
  version: PKG_VERSION,
1303
- // Advertise the new opencara-call stdout protocol so the
1304
- // server can later gate the skill prompt to capable CLIs.
1305
- // Older CLIs without this capability would still be sent the
1306
- // skill markdown today (it doesn't crash; the fenced block
1307
- // just shows up in stdout unparsed).
1308
- capabilities: ["agent-call"],
1207
+ // Advertise ACP transport support. Pre-v0.30 devices reported
1208
+ // "agent-call" (the fenced-stdout-block protocol); since the
1209
+ // legacy path was removed, this version reports "acp" so the
1210
+ // orchestrator knows the device can handle `spec.acp` jobs.
1211
+ capabilities: ["acp"],
1309
1212
  systemInfo: collectSystemInfo()
1310
1213
  });
1311
1214
  },
@@ -1357,66 +1260,27 @@ async function executeJob(job, client) {
1357
1260
  if (flushTimer) return;
1358
1261
  flushTimer = setTimeout(flush, LOG_FLUSH_MS);
1359
1262
  };
1360
- if (job.spec.acp) {
1361
- const handle = runAcpJob({
1362
- runId,
1363
- spec: job.spec,
1364
- handlers: {
1365
- onLog: (stream, chunk) => {
1366
- pending[stream] += chunk;
1367
- scheduleFlush();
1368
- },
1369
- sendAgentCall: (req) => client.send(req)
1370
- }
1371
- });
1372
- acpControllers.set(runId, handle.controller);
1373
- try {
1374
- const result = await handle.promise;
1375
- flush();
1376
- client.send({
1377
- type: "done",
1378
- runId,
1379
- status: result.exitCode === 0 ? "succeeded" : "failed",
1380
- exitCode: result.exitCode
1381
- });
1382
- console.log(
1383
- `[opencara] job ${runId.slice(-8)} (acp) \u2192 ${result.stopReason} exit=${result.exitCode}`
1384
- );
1385
- } catch (err) {
1386
- flush();
1387
- const message = err instanceof Error ? err.message : String(err);
1388
- client.send({ type: "done", runId, status: "failed", errorMessage: message });
1389
- console.error(`[opencara] job ${runId.slice(-8)} (acp) failed`, message);
1390
- } finally {
1391
- acpControllers.delete(runId);
1392
- }
1263
+ if (!job.spec.acp) {
1264
+ flush();
1265
+ const message = `legacy stdin-JSON dispatch removed in v0.30 \u2014 orchestrator must send spec.acp. Got command: ${job.spec.command}.`;
1266
+ client.send({ type: "done", runId, status: "failed", errorMessage: message });
1267
+ console.error(`[opencara] job ${runId.slice(-8)} rejected: ${message}`);
1393
1268
  return;
1394
1269
  }
1395
- const callParser = new AgentCallParser((call) => {
1396
- switch (call.kind) {
1397
- case "issue.body.set":
1398
- client.send({ type: "agent-call", runId, ...call });
1399
- return;
1400
- case "flow.node.config.set":
1401
- client.send({ type: "agent-call", runId, ...call });
1402
- return;
1403
- case "template.node.config.set":
1404
- client.send({ type: "agent-call", runId, ...call });
1405
- return;
1406
- default: {
1407
- const exhaustive = call;
1408
- void exhaustive;
1409
- }
1410
- }
1411
- });
1412
- try {
1413
- const result = await runJob(job.spec, job.stdinJson, {
1270
+ const handle = runAcpJob({
1271
+ runId,
1272
+ spec: job.spec,
1273
+ handlers: {
1414
1274
  onLog: (stream, chunk) => {
1415
1275
  pending[stream] += chunk;
1416
1276
  scheduleFlush();
1417
- if (stream === "stdout") callParser.feed(chunk);
1418
- }
1419
- });
1277
+ },
1278
+ sendAgentCall: (req) => client.send(req)
1279
+ }
1280
+ });
1281
+ acpControllers.set(runId, handle.controller);
1282
+ try {
1283
+ const result = await handle.promise;
1420
1284
  flush();
1421
1285
  client.send({
1422
1286
  type: "done",
@@ -1424,12 +1288,16 @@ async function executeJob(job, client) {
1424
1288
  status: result.exitCode === 0 ? "succeeded" : "failed",
1425
1289
  exitCode: result.exitCode
1426
1290
  });
1427
- console.log(`[opencara] job ${runId.slice(-8)} \u2192 exit ${result.exitCode}`);
1291
+ console.log(
1292
+ `[opencara] job ${runId.slice(-8)} (acp) \u2192 ${result.stopReason} exit=${result.exitCode}`
1293
+ );
1428
1294
  } catch (err) {
1429
1295
  flush();
1430
1296
  const message = err instanceof Error ? err.message : String(err);
1431
1297
  client.send({ type: "done", runId, status: "failed", errorMessage: message });
1432
- console.error(`[opencara] job ${runId.slice(-8)} failed`, message);
1298
+ console.error(`[opencara] job ${runId.slice(-8)} (acp) failed`, message);
1299
+ } finally {
1300
+ acpControllers.delete(runId);
1433
1301
  }
1434
1302
  }
1435
1303
  function collectSystemInfo() {
@@ -315,7 +315,6 @@ var DeviceToServerMessageSchema = z3.union([
315
315
  LogFrameSchema,
316
316
  RunDoneSchema,
317
317
  PongSchema,
318
- AgentCallSchema,
319
318
  AgentCallRequestSchema
320
319
  ]);
321
320
  var HostRegisterRequestSchema = z3.object({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.104.1",
3
+ "version": "0.105.0",
4
4
  "description": "OpenCara agent-host CLI: register a machine as an agent host and run dispatched agents.",
5
5
  "license": "MIT",
6
6
  "repository": {