opencara 0.100.2 → 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.
- package/dist/bin.js +153 -16
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -12,9 +12,7 @@ import {
|
|
|
12
12
|
totalmem,
|
|
13
13
|
uptime
|
|
14
14
|
} from "node:os";
|
|
15
|
-
import {
|
|
16
|
-
import { dirname, join as join2 } from "node:path";
|
|
17
|
-
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { statfsSync } from "node:fs";
|
|
18
16
|
|
|
19
17
|
// src/config/store.ts
|
|
20
18
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from "node:fs";
|
|
@@ -179,16 +177,47 @@ var HelloAckSchema = z4.object({
|
|
|
179
177
|
});
|
|
180
178
|
var PingSchema = z4.object({ type: z4.literal("ping") });
|
|
181
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
|
+
]);
|
|
182
210
|
var ServerToDeviceMessageSchema = z4.discriminatedUnion("type", [
|
|
183
211
|
JobAssignmentSchema,
|
|
184
212
|
HelloAckSchema,
|
|
185
213
|
PingSchema
|
|
186
214
|
]);
|
|
187
|
-
var DeviceToServerMessageSchema = z4.
|
|
215
|
+
var DeviceToServerMessageSchema = z4.union([
|
|
188
216
|
HelloMessageSchema,
|
|
189
217
|
LogFrameSchema,
|
|
190
218
|
RunDoneSchema,
|
|
191
|
-
PongSchema
|
|
219
|
+
PongSchema,
|
|
220
|
+
AgentCallSchema
|
|
192
221
|
]);
|
|
193
222
|
var HostRegisterRequestSchema = z4.object({
|
|
194
223
|
hostId: z4.string(),
|
|
@@ -201,6 +230,36 @@ var HostRegisterResponseSchema = z4.object({
|
|
|
201
230
|
pollIntervalMs: z4.number().int().positive()
|
|
202
231
|
});
|
|
203
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
|
+
|
|
204
263
|
// src/commands/register.ts
|
|
205
264
|
var POLL_INTERVAL_MS = 2e3;
|
|
206
265
|
async function register(opts = {}) {
|
|
@@ -368,9 +427,72 @@ function runJob(spec, stdinJson, handlers) {
|
|
|
368
427
|
});
|
|
369
428
|
}
|
|
370
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
|
+
|
|
371
494
|
// src/commands/run.ts
|
|
372
|
-
var
|
|
373
|
-
var PKG_VERSION = readPkgVersion();
|
|
495
|
+
var PKG_VERSION = "0.101.0";
|
|
374
496
|
var LOG_FLUSH_MS = 800;
|
|
375
497
|
var MAX_CHUNK_SIZE = 4 * 1024;
|
|
376
498
|
async function run(opts = {}) {
|
|
@@ -390,7 +512,12 @@ async function run(opts = {}) {
|
|
|
390
512
|
type: "hello",
|
|
391
513
|
platform: platform(),
|
|
392
514
|
version: PKG_VERSION,
|
|
393
|
-
|
|
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"],
|
|
394
521
|
systemInfo: collectSystemInfo()
|
|
395
522
|
});
|
|
396
523
|
},
|
|
@@ -436,11 +563,29 @@ async function executeJob(job, client) {
|
|
|
436
563
|
if (flushTimer) return;
|
|
437
564
|
flushTimer = setTimeout(flush, LOG_FLUSH_MS);
|
|
438
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
|
+
});
|
|
439
583
|
try {
|
|
440
584
|
const result = await runJob(job.spec, job.stdinJson, {
|
|
441
585
|
onLog: (stream, chunk) => {
|
|
442
586
|
pending[stream] += chunk;
|
|
443
587
|
scheduleFlush();
|
|
588
|
+
if (stream === "stdout") callParser.feed(chunk);
|
|
444
589
|
}
|
|
445
590
|
});
|
|
446
591
|
flush();
|
|
@@ -458,14 +603,6 @@ async function executeJob(job, client) {
|
|
|
458
603
|
console.error(`[opencara] job ${runId.slice(-8)} failed`, message);
|
|
459
604
|
}
|
|
460
605
|
}
|
|
461
|
-
function readPkgVersion() {
|
|
462
|
-
try {
|
|
463
|
-
const raw = readFileSync2(join2(__dirname, "..", "..", "package.json"), "utf8");
|
|
464
|
-
return JSON.parse(raw).version ?? "0.0.0";
|
|
465
|
-
} catch {
|
|
466
|
-
return "0.0.0";
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
606
|
function collectSystemInfo() {
|
|
470
607
|
try {
|
|
471
608
|
const cpuList = cpus();
|