@cleocode/cleo 2026.4.114 → 2026.4.116
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/cli/index.js +275 -25
- package/dist/cli/index.js.map +4 -4
- package/package.json +9 -9
package/dist/cli/index.js
CHANGED
|
@@ -705,6 +705,13 @@ var init_variable_substitution = __esm({
|
|
|
705
705
|
}
|
|
706
706
|
});
|
|
707
707
|
|
|
708
|
+
// packages/contracts/src/operations/worktree.ts
|
|
709
|
+
var init_worktree = __esm({
|
|
710
|
+
"packages/contracts/src/operations/worktree.ts"() {
|
|
711
|
+
"use strict";
|
|
712
|
+
}
|
|
713
|
+
});
|
|
714
|
+
|
|
708
715
|
// packages/contracts/src/operations/index.ts
|
|
709
716
|
var init_operations = __esm({
|
|
710
717
|
"packages/contracts/src/operations/index.ts"() {
|
|
@@ -725,6 +732,7 @@ var init_operations = __esm({
|
|
|
725
732
|
init_tasks();
|
|
726
733
|
init_validate();
|
|
727
734
|
init_variable_substitution();
|
|
735
|
+
init_worktree();
|
|
728
736
|
}
|
|
729
737
|
});
|
|
730
738
|
|
|
@@ -735,6 +743,13 @@ var init_orchestration_hierarchy = __esm({
|
|
|
735
743
|
}
|
|
736
744
|
});
|
|
737
745
|
|
|
746
|
+
// packages/contracts/src/peer.ts
|
|
747
|
+
var init_peer = __esm({
|
|
748
|
+
"packages/contracts/src/peer.ts"() {
|
|
749
|
+
"use strict";
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
|
|
738
753
|
// packages/contracts/src/session.ts
|
|
739
754
|
var init_session2 = __esm({
|
|
740
755
|
"packages/contracts/src/session.ts"() {
|
|
@@ -845,6 +860,7 @@ var init_src = __esm({
|
|
|
845
860
|
init_operations();
|
|
846
861
|
init_params();
|
|
847
862
|
init_orchestration_hierarchy();
|
|
863
|
+
init_peer();
|
|
848
864
|
init_session2();
|
|
849
865
|
init_status_registry();
|
|
850
866
|
init_task_evidence();
|
|
@@ -9617,13 +9633,15 @@ async function composeSpawnForTask(taskId, root, options = {}) {
|
|
|
9617
9633
|
sessionId: options.sessionId ?? null,
|
|
9618
9634
|
role: inferredRole,
|
|
9619
9635
|
protocol: options.protocol,
|
|
9620
|
-
skipAtomicityCheck: options.skipAtomicityCheck ?? false
|
|
9636
|
+
skipAtomicityCheck: options.skipAtomicityCheck ?? false,
|
|
9637
|
+
worktreePath: options.worktreePath,
|
|
9638
|
+
worktreeBranch: options.worktreeBranch
|
|
9621
9639
|
});
|
|
9622
9640
|
} finally {
|
|
9623
9641
|
db.close();
|
|
9624
9642
|
}
|
|
9625
9643
|
}
|
|
9626
|
-
async function orchestrateSpawn(taskId, protocolType, projectRoot, tier) {
|
|
9644
|
+
async function orchestrateSpawn(taskId, protocolType, projectRoot, tier, noWorktree) {
|
|
9627
9645
|
if (!taskId) {
|
|
9628
9646
|
return engineError("E_INVALID_INPUT", "taskId is required");
|
|
9629
9647
|
}
|
|
@@ -9650,10 +9668,43 @@ async function orchestrateSpawn(taskId, protocolType, projectRoot, tier) {
|
|
|
9650
9668
|
} catch {
|
|
9651
9669
|
activeSessionId = null;
|
|
9652
9670
|
}
|
|
9671
|
+
let sdkWorktreeResult = null;
|
|
9672
|
+
let worktreePath;
|
|
9673
|
+
let worktreeBranch;
|
|
9674
|
+
if (noWorktree) {
|
|
9675
|
+
getLogger2("engine:orchestrate").info(
|
|
9676
|
+
{ taskId },
|
|
9677
|
+
"T1140 --no-worktree: worktree provisioning skipped (audit logged)"
|
|
9678
|
+
);
|
|
9679
|
+
try {
|
|
9680
|
+
const accessor2 = await getAccessor2(root);
|
|
9681
|
+
await accessor2.appendLog({
|
|
9682
|
+
action: "orchestrate.spawn.no-worktree",
|
|
9683
|
+
taskId,
|
|
9684
|
+
actor: "orchestrate-engine",
|
|
9685
|
+
details: { reason: "--no-worktree flag set by caller", taskId }
|
|
9686
|
+
});
|
|
9687
|
+
} catch {
|
|
9688
|
+
}
|
|
9689
|
+
} else {
|
|
9690
|
+
try {
|
|
9691
|
+
const { spawnWorktree } = await import("@cleocode/core/internal");
|
|
9692
|
+
sdkWorktreeResult = await spawnWorktree(root, { taskId });
|
|
9693
|
+
worktreePath = sdkWorktreeResult.path;
|
|
9694
|
+
worktreeBranch = sdkWorktreeResult.branch;
|
|
9695
|
+
} catch (wtErr) {
|
|
9696
|
+
getLogger2("engine:orchestrate").warn(
|
|
9697
|
+
{ taskId, err: wtErr },
|
|
9698
|
+
`T1140 worktree creation failed for ${taskId} \u2014 spawning without isolation: ${wtErr instanceof Error ? wtErr.message : String(wtErr)}`
|
|
9699
|
+
);
|
|
9700
|
+
}
|
|
9701
|
+
}
|
|
9653
9702
|
const payload = await composeSpawnForTask(taskId, root, {
|
|
9654
9703
|
tier,
|
|
9655
9704
|
sessionId: activeSessionId,
|
|
9656
|
-
protocol: protocolType
|
|
9705
|
+
protocol: protocolType,
|
|
9706
|
+
worktreePath,
|
|
9707
|
+
worktreeBranch
|
|
9657
9708
|
});
|
|
9658
9709
|
if (!payload.atomicity.allowed) {
|
|
9659
9710
|
return engineError(
|
|
@@ -9669,20 +9720,21 @@ async function orchestrateSpawn(taskId, protocolType, projectRoot, tier) {
|
|
|
9669
9720
|
}
|
|
9670
9721
|
);
|
|
9671
9722
|
}
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9723
|
+
const finalPrompt = payload.prompt;
|
|
9724
|
+
const worktreeAdapterResult = sdkWorktreeResult ? {
|
|
9725
|
+
worktree: {
|
|
9726
|
+
path: sdkWorktreeResult.path,
|
|
9727
|
+
branch: sdkWorktreeResult.branch,
|
|
9728
|
+
taskId: sdkWorktreeResult.taskId,
|
|
9729
|
+
baseRef: sdkWorktreeResult.baseRef,
|
|
9730
|
+
projectHash: sdkWorktreeResult.projectHash,
|
|
9731
|
+
createdAt: sdkWorktreeResult.createdAt,
|
|
9732
|
+
locked: sdkWorktreeResult.locked
|
|
9733
|
+
},
|
|
9734
|
+
envVars: sdkWorktreeResult.envVars,
|
|
9735
|
+
cwd: sdkWorktreeResult.path,
|
|
9736
|
+
preamble: sdkWorktreeResult.preamble
|
|
9737
|
+
} : null;
|
|
9686
9738
|
return {
|
|
9687
9739
|
success: true,
|
|
9688
9740
|
data: {
|
|
@@ -9694,10 +9746,10 @@ ${payload.prompt}` : payload.prompt;
|
|
|
9694
9746
|
harnessHint: payload.harnessHint,
|
|
9695
9747
|
atomicity: payload.atomicity,
|
|
9696
9748
|
meta: payload.meta,
|
|
9697
|
-
// T1118 L1+L2 — worktree binding for harness adapters.
|
|
9698
|
-
worktree:
|
|
9699
|
-
worktreeEnv:
|
|
9700
|
-
worktreeCwd:
|
|
9749
|
+
// T1118 L1+L2 / T1140 — worktree binding for harness adapters.
|
|
9750
|
+
worktree: worktreeAdapterResult?.worktree ?? null,
|
|
9751
|
+
worktreeEnv: worktreeAdapterResult?.envVars ?? null,
|
|
9752
|
+
worktreeCwd: worktreeAdapterResult?.cwd ?? null,
|
|
9701
9753
|
spawnContext: {
|
|
9702
9754
|
taskId: payload.taskId,
|
|
9703
9755
|
protocol: payload.meta.protocol,
|
|
@@ -16407,6 +16459,15 @@ var init_conduit2 = __esm({
|
|
|
16407
16459
|
);
|
|
16408
16460
|
return wrapResult(result, "query", "conduit", operation, startTime);
|
|
16409
16461
|
}
|
|
16462
|
+
case "listen": {
|
|
16463
|
+
const result = await this.listenTopic(
|
|
16464
|
+
params?.topicName,
|
|
16465
|
+
params?.agentId,
|
|
16466
|
+
params?.limit,
|
|
16467
|
+
params?.since
|
|
16468
|
+
);
|
|
16469
|
+
return wrapResult(result, "query", "conduit", operation, startTime);
|
|
16470
|
+
}
|
|
16410
16471
|
default:
|
|
16411
16472
|
return unsupportedOp("query", "conduit", operation, startTime);
|
|
16412
16473
|
}
|
|
@@ -16446,6 +16507,24 @@ var init_conduit2 = __esm({
|
|
|
16446
16507
|
);
|
|
16447
16508
|
return wrapResult(result, "mutate", "conduit", operation, startTime);
|
|
16448
16509
|
}
|
|
16510
|
+
case "subscribe": {
|
|
16511
|
+
const result = await this.subscribeTopic(
|
|
16512
|
+
params?.topicName,
|
|
16513
|
+
params?.agentId,
|
|
16514
|
+
params?.filter
|
|
16515
|
+
);
|
|
16516
|
+
return wrapResult(result, "mutate", "conduit", operation, startTime);
|
|
16517
|
+
}
|
|
16518
|
+
case "publish": {
|
|
16519
|
+
const result = await this.publishToTopic(
|
|
16520
|
+
params?.topicName,
|
|
16521
|
+
params?.content,
|
|
16522
|
+
params?.kind,
|
|
16523
|
+
params?.payload,
|
|
16524
|
+
params?.agentId
|
|
16525
|
+
);
|
|
16526
|
+
return wrapResult(result, "mutate", "conduit", operation, startTime);
|
|
16527
|
+
}
|
|
16449
16528
|
default:
|
|
16450
16529
|
return unsupportedOp("mutate", "conduit", operation, startTime);
|
|
16451
16530
|
}
|
|
@@ -16462,8 +16541,8 @@ var init_conduit2 = __esm({
|
|
|
16462
16541
|
}
|
|
16463
16542
|
getSupportedOperations() {
|
|
16464
16543
|
return {
|
|
16465
|
-
query: ["status", "peek"],
|
|
16466
|
-
mutate: ["start", "stop", "send"]
|
|
16544
|
+
query: ["status", "peek", "listen"],
|
|
16545
|
+
mutate: ["start", "stop", "send", "subscribe", "publish"]
|
|
16467
16546
|
};
|
|
16468
16547
|
}
|
|
16469
16548
|
// ---------------------------------------------------------------------------
|
|
@@ -16670,6 +16749,165 @@ var init_conduit2 = __esm({
|
|
|
16670
16749
|
}
|
|
16671
16750
|
};
|
|
16672
16751
|
}
|
|
16752
|
+
// ── A2A Topic Operations (T1252) ────────────────────────────────────────
|
|
16753
|
+
/**
|
|
16754
|
+
* Subscribe agent to a named topic.
|
|
16755
|
+
*
|
|
16756
|
+
* Uses `LocalTransport` exclusively — topic operations require conduit.db.
|
|
16757
|
+
*
|
|
16758
|
+
* @param topicName - Topic name, e.g. `"epic-T1149.wave-2"`.
|
|
16759
|
+
* @param agentId - Agent id (defaults to active agent).
|
|
16760
|
+
* @param _filter - Reserved for future filter support.
|
|
16761
|
+
* @task T1252
|
|
16762
|
+
*/
|
|
16763
|
+
async subscribeTopic(topicName, agentId, _filter) {
|
|
16764
|
+
if (!topicName) {
|
|
16765
|
+
return {
|
|
16766
|
+
success: false,
|
|
16767
|
+
error: { code: "E_ARGS", message: 'Must specify "topicName"' }
|
|
16768
|
+
};
|
|
16769
|
+
}
|
|
16770
|
+
const credential = await this.resolveCredential(agentId);
|
|
16771
|
+
const { LocalTransport } = await import("@cleocode/core/conduit");
|
|
16772
|
+
if (!LocalTransport.isAvailable(process.cwd())) {
|
|
16773
|
+
return {
|
|
16774
|
+
success: false,
|
|
16775
|
+
error: { code: "E_CONDUIT", message: "conduit.db not found \u2014 run: cleo init" }
|
|
16776
|
+
};
|
|
16777
|
+
}
|
|
16778
|
+
const transport = new LocalTransport();
|
|
16779
|
+
await transport.connect({
|
|
16780
|
+
agentId: credential.agentId,
|
|
16781
|
+
apiKey: credential.apiKey,
|
|
16782
|
+
apiBaseUrl: credential.apiBaseUrl
|
|
16783
|
+
});
|
|
16784
|
+
try {
|
|
16785
|
+
await transport.subscribeTopic(topicName);
|
|
16786
|
+
return {
|
|
16787
|
+
success: true,
|
|
16788
|
+
data: {
|
|
16789
|
+
agentId: credential.agentId,
|
|
16790
|
+
topicName,
|
|
16791
|
+
message: `Subscribed to topic: ${topicName}`
|
|
16792
|
+
}
|
|
16793
|
+
};
|
|
16794
|
+
} finally {
|
|
16795
|
+
await transport.disconnect();
|
|
16796
|
+
}
|
|
16797
|
+
}
|
|
16798
|
+
/**
|
|
16799
|
+
* Publish a message to a named topic.
|
|
16800
|
+
*
|
|
16801
|
+
* Uses `LocalTransport` exclusively — topic operations require conduit.db.
|
|
16802
|
+
*
|
|
16803
|
+
* @param topicName - Target topic name.
|
|
16804
|
+
* @param content - Message content (required).
|
|
16805
|
+
* @param kind - Message kind (default `"message"`).
|
|
16806
|
+
* @param payload - Optional structured payload.
|
|
16807
|
+
* @param agentId - Publisher agent id (defaults to active agent).
|
|
16808
|
+
* @task T1252
|
|
16809
|
+
*/
|
|
16810
|
+
async publishToTopic(topicName, content, kind, payload, agentId) {
|
|
16811
|
+
if (!topicName) {
|
|
16812
|
+
return {
|
|
16813
|
+
success: false,
|
|
16814
|
+
error: { code: "E_ARGS", message: 'Must specify "topicName"' }
|
|
16815
|
+
};
|
|
16816
|
+
}
|
|
16817
|
+
if (!content) {
|
|
16818
|
+
return {
|
|
16819
|
+
success: false,
|
|
16820
|
+
error: { code: "E_ARGS", message: 'Must specify "content"' }
|
|
16821
|
+
};
|
|
16822
|
+
}
|
|
16823
|
+
const credential = await this.resolveCredential(agentId);
|
|
16824
|
+
const { LocalTransport } = await import("@cleocode/core/conduit");
|
|
16825
|
+
if (!LocalTransport.isAvailable(process.cwd())) {
|
|
16826
|
+
return {
|
|
16827
|
+
success: false,
|
|
16828
|
+
error: { code: "E_CONDUIT", message: "conduit.db not found \u2014 run: cleo init" }
|
|
16829
|
+
};
|
|
16830
|
+
}
|
|
16831
|
+
const transport = new LocalTransport();
|
|
16832
|
+
await transport.connect({
|
|
16833
|
+
agentId: credential.agentId,
|
|
16834
|
+
apiKey: credential.apiKey,
|
|
16835
|
+
apiBaseUrl: credential.apiBaseUrl
|
|
16836
|
+
});
|
|
16837
|
+
try {
|
|
16838
|
+
const result = await transport.publishToTopic(topicName, content, { kind, payload });
|
|
16839
|
+
return {
|
|
16840
|
+
success: true,
|
|
16841
|
+
data: {
|
|
16842
|
+
messageId: result.messageId,
|
|
16843
|
+
from: credential.agentId,
|
|
16844
|
+
topicName,
|
|
16845
|
+
transport: "local",
|
|
16846
|
+
publishedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
16847
|
+
}
|
|
16848
|
+
};
|
|
16849
|
+
} finally {
|
|
16850
|
+
await transport.disconnect();
|
|
16851
|
+
}
|
|
16852
|
+
}
|
|
16853
|
+
/**
|
|
16854
|
+
* One-shot poll for topic messages.
|
|
16855
|
+
*
|
|
16856
|
+
* Returns messages published to the topic (ordered oldest-first).
|
|
16857
|
+
* Uses `LocalTransport` exclusively — topic operations require conduit.db.
|
|
16858
|
+
*
|
|
16859
|
+
* @param topicName - Topic name to poll.
|
|
16860
|
+
* @param agentId - Agent id (defaults to active agent).
|
|
16861
|
+
* @param limit - Maximum messages to return (default 50).
|
|
16862
|
+
* @param since - Return only messages after this ISO 8601 timestamp.
|
|
16863
|
+
* @task T1252
|
|
16864
|
+
*/
|
|
16865
|
+
async listenTopic(topicName, agentId, limit, since) {
|
|
16866
|
+
if (!topicName) {
|
|
16867
|
+
return {
|
|
16868
|
+
success: false,
|
|
16869
|
+
error: { code: "E_ARGS", message: 'Must specify "topicName"' }
|
|
16870
|
+
};
|
|
16871
|
+
}
|
|
16872
|
+
const startMs = Date.now();
|
|
16873
|
+
const credential = await this.resolveCredential(agentId);
|
|
16874
|
+
const { LocalTransport } = await import("@cleocode/core/conduit");
|
|
16875
|
+
if (!LocalTransport.isAvailable(process.cwd())) {
|
|
16876
|
+
return {
|
|
16877
|
+
success: false,
|
|
16878
|
+
error: { code: "E_CONDUIT", message: "conduit.db not found \u2014 run: cleo init" }
|
|
16879
|
+
};
|
|
16880
|
+
}
|
|
16881
|
+
const transport = new LocalTransport();
|
|
16882
|
+
await transport.connect({
|
|
16883
|
+
agentId: credential.agentId,
|
|
16884
|
+
apiKey: credential.apiKey,
|
|
16885
|
+
apiBaseUrl: credential.apiBaseUrl
|
|
16886
|
+
});
|
|
16887
|
+
try {
|
|
16888
|
+
const sinceUnix = since ? Math.floor(new Date(since).getTime() / 1e3) : 0;
|
|
16889
|
+
const messages = await transport.pollTopic(topicName, {
|
|
16890
|
+
limit: limit ?? 50,
|
|
16891
|
+
since: sinceUnix
|
|
16892
|
+
});
|
|
16893
|
+
return {
|
|
16894
|
+
success: true,
|
|
16895
|
+
data: {
|
|
16896
|
+
topicName,
|
|
16897
|
+
messages: messages.map((m) => ({
|
|
16898
|
+
id: m.id,
|
|
16899
|
+
from: m.from,
|
|
16900
|
+
content: m.content,
|
|
16901
|
+
conversationId: m.threadId,
|
|
16902
|
+
timestamp: m.timestamp
|
|
16903
|
+
})),
|
|
16904
|
+
listenedForMs: Date.now() - startMs
|
|
16905
|
+
}
|
|
16906
|
+
};
|
|
16907
|
+
} finally {
|
|
16908
|
+
await transport.disconnect();
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16673
16911
|
/** Send a message to an agent or conversation. Uses LocalTransport when conduit.db is available. */
|
|
16674
16912
|
async sendMessage(content, to, conversationId, agentId) {
|
|
16675
16913
|
if (!to && !conversationId) {
|
|
@@ -26285,7 +26523,14 @@ var init_orchestrate2 = __esm({
|
|
|
26285
26523
|
}
|
|
26286
26524
|
const protocolType = params?.protocolType;
|
|
26287
26525
|
const tier = params?.tier;
|
|
26288
|
-
const
|
|
26526
|
+
const noWorktree = params?.noWorktree;
|
|
26527
|
+
const result = await orchestrateSpawn(
|
|
26528
|
+
taskId,
|
|
26529
|
+
protocolType,
|
|
26530
|
+
projectRoot,
|
|
26531
|
+
tier,
|
|
26532
|
+
noWorktree
|
|
26533
|
+
);
|
|
26289
26534
|
return wrapResult(result, "mutate", "orchestrate", operation, startTime);
|
|
26290
26535
|
}
|
|
26291
26536
|
case "handoff": {
|
|
@@ -50383,6 +50628,10 @@ var spawnCommand2 = defineCommand({
|
|
|
50383
50628
|
tier: {
|
|
50384
50629
|
type: "string",
|
|
50385
50630
|
description: "Protocol tier: 0 (minimal), 1 (standard), 2 (full), or auto (default \u2014 inferred from role+size+labels via T892 heuristics)"
|
|
50631
|
+
},
|
|
50632
|
+
"no-worktree": {
|
|
50633
|
+
type: "boolean",
|
|
50634
|
+
description: "Skip worktree provisioning for this spawn. The opt-out is logged to the audit log (T1140)."
|
|
50386
50635
|
}
|
|
50387
50636
|
},
|
|
50388
50637
|
async run({ args }) {
|
|
@@ -50400,7 +50649,8 @@ var spawnCommand2 = defineCommand({
|
|
|
50400
50649
|
{
|
|
50401
50650
|
taskId: args.taskId,
|
|
50402
50651
|
protocolType: args.protocol,
|
|
50403
|
-
tier
|
|
50652
|
+
tier,
|
|
50653
|
+
noWorktree: args["no-worktree"] === true
|
|
50404
50654
|
},
|
|
50405
50655
|
{ command: "orchestrate" }
|
|
50406
50656
|
);
|