opencara 0.100.3 → 0.101.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.
Files changed (2) hide show
  1. package/dist/bin.js +152 -4
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -177,16 +177,47 @@ var HelloAckSchema = z4.object({
177
177
  });
178
178
  var PingSchema = z4.object({ type: z4.literal("ping") });
179
179
  var PongSchema = z4.object({ type: z4.literal("pong") });
180
+ var AgentCallEnvelope = {
181
+ type: z4.literal("agent-call"),
182
+ runId: z4.string(),
183
+ callId: z4.string()
184
+ };
185
+ var IssueBodySetCallSchema = z4.object({
186
+ ...AgentCallEnvelope,
187
+ kind: z4.literal("issue.body.set"),
188
+ issueNumber: z4.number().int(),
189
+ bodyMd: z4.string()
190
+ });
191
+ var FlowNodeConfigSetCallSchema = z4.object({
192
+ ...AgentCallEnvelope,
193
+ kind: z4.literal("flow.node.config.set"),
194
+ flowSlug: z4.string().min(1),
195
+ nodeId: z4.string().min(1),
196
+ config: z4.record(z4.string(), z4.unknown())
197
+ });
198
+ var TemplateNodeConfigSetCallSchema = z4.object({
199
+ ...AgentCallEnvelope,
200
+ kind: z4.literal("template.node.config.set"),
201
+ templateSlug: z4.string().min(1),
202
+ nodeId: z4.string().min(1),
203
+ config: z4.record(z4.string(), z4.unknown())
204
+ });
205
+ var AgentCallSchema = z4.discriminatedUnion("kind", [
206
+ IssueBodySetCallSchema,
207
+ FlowNodeConfigSetCallSchema,
208
+ TemplateNodeConfigSetCallSchema
209
+ ]);
180
210
  var ServerToDeviceMessageSchema = z4.discriminatedUnion("type", [
181
211
  JobAssignmentSchema,
182
212
  HelloAckSchema,
183
213
  PingSchema
184
214
  ]);
185
- var DeviceToServerMessageSchema = z4.discriminatedUnion("type", [
215
+ var DeviceToServerMessageSchema = z4.union([
186
216
  HelloMessageSchema,
187
217
  LogFrameSchema,
188
218
  RunDoneSchema,
189
- PongSchema
219
+ PongSchema,
220
+ AgentCallSchema
190
221
  ]);
191
222
  var HostRegisterRequestSchema = z4.object({
192
223
  hostId: z4.string(),
@@ -199,6 +230,36 @@ var HostRegisterResponseSchema = z4.object({
199
230
  pollIntervalMs: z4.number().int().positive()
200
231
  });
201
232
 
233
+ // ../shared/dist/issues.js
234
+ import { z as z5 } from "zod";
235
+ var IssueLabelSchema = z5.object({
236
+ name: z5.string(),
237
+ color: z5.string()
238
+ });
239
+ var IssueAssigneeSchema = z5.object({
240
+ login: z5.string(),
241
+ id: z5.number()
242
+ });
243
+ var IssueSummarySchema = z5.object({
244
+ id: z5.string(),
245
+ number: z5.number().int(),
246
+ title: z5.string(),
247
+ state: z5.string(),
248
+ stateReason: z5.string().nullable(),
249
+ labels: z5.array(IssueLabelSchema),
250
+ assignees: z5.array(IssueAssigneeSchema),
251
+ authorLogin: z5.string().nullable(),
252
+ htmlUrl: z5.string(),
253
+ createdAt: z5.string().datetime(),
254
+ updatedAt: z5.string().datetime(),
255
+ closedAt: z5.string().datetime().nullable()
256
+ });
257
+ var IssueDetailSchema = IssueSummarySchema.extend({
258
+ bodyMd: z5.string().nullable(),
259
+ draftBodyMd: z5.string().nullable(),
260
+ draftUpdatedAt: z5.string().datetime().nullable()
261
+ });
262
+
202
263
  // src/commands/register.ts
203
264
  var POLL_INTERVAL_MS = 2e3;
204
265
  async function register(opts = {}) {
@@ -366,8 +427,72 @@ function runJob(spec, stdinJson, handlers) {
366
427
  });
367
428
  }
368
429
 
430
+ // src/runner/agentCallParser.ts
431
+ import { z as z6 } from "zod";
432
+ var MAX_BUFFER_BYTES = 64 * 1024;
433
+ var FENCE_RE = /```opencara-call\r?\n([\s\S]*?)\r?\n```/;
434
+ var VARIANT_SCHEMAS = {
435
+ "issue.body.set": IssueBodySetCallSchema.omit({ type: true, runId: true }),
436
+ "flow.node.config.set": FlowNodeConfigSetCallSchema.omit({
437
+ type: true,
438
+ runId: true
439
+ }),
440
+ "template.node.config.set": TemplateNodeConfigSetCallSchema.omit({
441
+ type: true,
442
+ runId: true
443
+ })
444
+ };
445
+ var KindSchema = z6.enum([
446
+ "issue.body.set",
447
+ "flow.node.config.set",
448
+ "template.node.config.set"
449
+ ]);
450
+ var AgentCallParser = class {
451
+ constructor(emit) {
452
+ this.emit = emit;
453
+ }
454
+ emit;
455
+ buffer = "";
456
+ feed(chunk) {
457
+ this.buffer += chunk;
458
+ if (this.buffer.length > MAX_BUFFER_BYTES) {
459
+ const cutoff = Math.floor(MAX_BUFFER_BYTES / 2);
460
+ const nl = this.buffer.indexOf("\n", this.buffer.length - cutoff);
461
+ this.buffer = nl >= 0 ? this.buffer.slice(nl + 1) : this.buffer.slice(-cutoff);
462
+ }
463
+ while (true) {
464
+ const m = FENCE_RE.exec(this.buffer);
465
+ if (!m) break;
466
+ const inner = m[1] ?? "";
467
+ const consumedTo = m.index + m[0].length;
468
+ this.buffer = this.buffer.slice(consumedTo);
469
+ this.tryEmit(inner);
470
+ }
471
+ }
472
+ tryEmit(inner) {
473
+ let parsed;
474
+ try {
475
+ parsed = JSON.parse(inner);
476
+ } catch {
477
+ return;
478
+ }
479
+ if (!parsed || typeof parsed !== "object") return;
480
+ const raw = parsed;
481
+ const kindResult = KindSchema.safeParse(raw.kind);
482
+ if (!kindResult.success) return;
483
+ const withCallId = {
484
+ ...raw,
485
+ callId: typeof raw.callId === "string" && raw.callId.length > 0 ? raw.callId : `call_${Date.now().toString(36)}`
486
+ };
487
+ const schema = VARIANT_SCHEMAS[kindResult.data];
488
+ const result = schema.safeParse(withCallId);
489
+ if (!result.success) return;
490
+ this.emit(result.data);
491
+ }
492
+ };
493
+
369
494
  // src/commands/run.ts
370
- var PKG_VERSION = "0.100.3";
495
+ var PKG_VERSION = "0.101.0";
371
496
  var LOG_FLUSH_MS = 800;
372
497
  var MAX_CHUNK_SIZE = 4 * 1024;
373
498
  async function run(opts = {}) {
@@ -387,7 +512,12 @@ async function run(opts = {}) {
387
512
  type: "hello",
388
513
  platform: platform(),
389
514
  version: PKG_VERSION,
390
- capabilities: [],
515
+ // Advertise the new opencara-call stdout protocol so the
516
+ // server can later gate the skill prompt to capable CLIs.
517
+ // Older CLIs without this capability would still be sent the
518
+ // skill markdown today (it doesn't crash; the fenced block
519
+ // just shows up in stdout unparsed).
520
+ capabilities: ["agent-call"],
391
521
  systemInfo: collectSystemInfo()
392
522
  });
393
523
  },
@@ -433,11 +563,29 @@ async function executeJob(job, client) {
433
563
  if (flushTimer) return;
434
564
  flushTimer = setTimeout(flush, LOG_FLUSH_MS);
435
565
  };
566
+ const callParser = new AgentCallParser((call) => {
567
+ switch (call.kind) {
568
+ case "issue.body.set":
569
+ client.send({ type: "agent-call", runId, ...call });
570
+ return;
571
+ case "flow.node.config.set":
572
+ client.send({ type: "agent-call", runId, ...call });
573
+ return;
574
+ case "template.node.config.set":
575
+ client.send({ type: "agent-call", runId, ...call });
576
+ return;
577
+ default: {
578
+ const exhaustive = call;
579
+ void exhaustive;
580
+ }
581
+ }
582
+ });
436
583
  try {
437
584
  const result = await runJob(job.spec, job.stdinJson, {
438
585
  onLog: (stream, chunk) => {
439
586
  pending[stream] += chunk;
440
587
  scheduleFlush();
588
+ if (stream === "stdout") callParser.feed(chunk);
441
589
  }
442
590
  });
443
591
  flush();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencara",
3
- "version": "0.100.3",
3
+ "version": "0.101.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": {