@clawos-dev/clawd 0.2.767 → 0.2.769

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.cjs CHANGED
@@ -50900,6 +50900,12 @@ var SessionManager = class {
50900
50900
  broadcast: [{ frame: { type: "session:info", ...updated }, target: "all" }]
50901
50901
  };
50902
50902
  }
50903
+ /** A mounted cloud worker has no thread id until its turn ends; once the ledger reports it, history becomes readable. No-op if already attached. */
50904
+ attachCloudWorkerThread(sessionId, toolSessionId) {
50905
+ const file = this.findOwnedSession(sessionId);
50906
+ if (!file || !file.cloudConversationId || file.toolSessionId) return null;
50907
+ return this.applyUpdate({ sessionId, patch: { toolSessionId } });
50908
+ }
50903
50909
  bindCloudWorkspace(sessionId, binding, conversationId) {
50904
50910
  const file = this.getFile(sessionId);
50905
50911
  if (!isCloudTool(file.tool) || file.cloudPendingTurns?.length)
@@ -57808,13 +57814,26 @@ function createA2aHost(deps) {
57808
57814
  if (v3.initiator.host === "cloud") return deps.listSessions().find((s2) => s2.cloudConversationId === ref) ?? null;
57809
57815
  return null;
57810
57816
  }
57817
+ function mountCloudChildren(conversationRef) {
57818
+ for (const child of [...cache2.values()]) {
57819
+ if (child.initiator.host === "cloud" && child.initiator.sessionRef === conversationRef) onInitiatorTask(child, 0);
57820
+ }
57821
+ }
57811
57822
  function onInitiatorTask(v3, changeSeq) {
57812
57823
  remember(v3);
57813
57824
  const session = initiatorSession(v3);
57814
57825
  if (!session) return;
57815
- if (v3.targetDeviceId === null && v3.executorSessionRef && v3.executorThreadId && !v3.workerSessionId && deps.mountCloudWorker) {
57816
- const mounted = deps.mountCloudWorker(v3, session);
57817
- if (mounted) cache2.set(v3.taskId, { ...v3, workerSessionId: mounted });
57826
+ if (v3.targetDeviceId === null && v3.executorSessionRef && deps.mountCloudWorker) {
57827
+ let worker = v3.workerSessionId ?? deps.listSessions().find((s2) => s2.cloudConversationId === v3.executorSessionRef)?.sessionId;
57828
+ const ran = v3.state === "working" || v3.state === "input_required" || v3.executorThreadId !== null;
57829
+ if (!worker && ran) {
57830
+ worker = deps.mountCloudWorker(v3, session) ?? void 0;
57831
+ if (worker) {
57832
+ cache2.set(v3.taskId, { ...v3, workerSessionId: worker });
57833
+ mountCloudChildren(v3.executorSessionRef);
57834
+ }
57835
+ }
57836
+ if (worker && v3.executorThreadId) deps.attachCloudWorkerThread?.(worker, v3.executorThreadId);
57818
57837
  }
57819
57838
  if (v3.initiator.host === "cloud") return;
57820
57839
  if (!isDeliverable(v3) || v3.deliveredAt) return;
@@ -57865,6 +57884,7 @@ function createA2aHost(deps) {
57865
57884
  if (ref.kind === "device") return { kind: "local", deviceId: ref.deviceId, personaId: ref.personaId };
57866
57885
  const p3 = deps.persona(ref.personaId);
57867
57886
  if (!p3) throw new ClawdError(ERROR_CODES.INVALID_PARAM, `\u672C\u673A\u6CA1\u6709 persona ${ref.personaId}\uFF1B\u8054\u7CFB\u4EBA\u8BBE\u5907\u4E0A\u7684\u5199\u6210 <personaId>@<deviceId>\uFF0C\u4E91\u4E0A\u7684\u5199\u6210 cloud:<personaId>`);
57887
+ if (p3.cloud?.environment === "integration") throw new ClawdError(ERROR_CODES.INVALID_PARAM, `${ref.personaId} \u662F\u6D4B\u8BD5\u53D1\u5E03\u955C\u50CF\uFF0CA2A \u4E0D\u652F\u6301\uFF1B\u8BF7\u6D3E\u7ED9\u6B63\u5F0F\u73AF\u5883\u7684 persona`);
57868
57888
  return p3.cloud ? { kind: "cloud", personaId: p3.cloud.personaId } : { kind: "local", deviceId: deps.deviceId(), personaId: ref.personaId };
57869
57889
  }
57870
57890
  function checkTopicGate(call) {
@@ -57878,7 +57898,8 @@ function createA2aHost(deps) {
57878
57898
  if (ref.kind === "device") return m3.personaId === ref.personaId && m3.deviceId === ref.deviceId;
57879
57899
  if (m3.deviceId && m3.deviceId !== me2) return false;
57880
57900
  if (m3.personaId === ref.personaId) return true;
57881
- return ref.kind === "cloud" && deps.persona(m3.personaId)?.cloud?.personaId === ref.personaId;
57901
+ const mirror = deps.persona(m3.personaId)?.cloud;
57902
+ return ref.kind === "cloud" && mirror?.environment !== "integration" && mirror?.personaId === ref.personaId;
57882
57903
  });
57883
57904
  if (!ok2) throw new ClawdError(ERROR_CODES.INVALID_PARAM, `${call.target} is not a member of the channel behind topic ${topicId} \u2014\u2014 \u5148\u628A\u5B83\u52A0\u8FDB\u9891\u9053\u518D\u6D3E\u6D3B`);
57884
57905
  }
@@ -58075,6 +58096,12 @@ function createA2aHost(deps) {
58075
58096
  };
58076
58097
  }
58077
58098
 
58099
+ // src/a2a/cloud-mirror.ts
58100
+ function pickCloudMirror(personas, cloudPersonaId) {
58101
+ const mirrors = personas.filter((p3) => p3.cloud?.personaId === cloudPersonaId);
58102
+ return mirrors.find((p3) => p3.cloud?.environment !== "integration") ?? mirrors[0];
58103
+ }
58104
+
58078
58105
  // src/a2a/handlers.ts
58079
58106
  init_protocol();
58080
58107
  var argsOf = (frame) => {
@@ -76677,7 +76704,7 @@ function computeMethodAccess(args) {
76677
76704
  }
76678
76705
 
76679
76706
  // src/version.ts
76680
- var version = "0.2.767".length > 0 ? "0.2.767" : "dev";
76707
+ var version = "0.2.769".length > 0 ? "0.2.769" : "dev";
76681
76708
 
76682
76709
  // src/cli-probe/probe.ts
76683
76710
  var fs87 = __toESM(require("fs"), 1);
@@ -80535,14 +80562,14 @@ async function startDaemon(config) {
80535
80562
  injectResult: (sid, text) => manager.injectIntoSession(sid, text, "a2a-result"),
80536
80563
  // 云 worker 会话挂到发起会话下面:本机要有这个云 persona 的镜像(会话 cwd / 引擎从它来),没有就只留在台账里
80537
80564
  mountCloudWorker: (view, initiator) => {
80538
- const mirror = personaRegistry.list().find((p3) => p3.cloud?.personaId === view.targetPersonaId);
80539
- if (!mirror || !view.executorSessionRef || !view.executorThreadId) return null;
80565
+ const mirror = pickCloudMirror(personaRegistry.list(), view.targetPersonaId);
80566
+ if (!mirror || !view.executorSessionRef) return null;
80540
80567
  try {
80541
80568
  const { response, broadcast } = manager.create(
80542
80569
  {
80543
80570
  ownerPersonaId: mirror.personaId,
80544
80571
  label: (view.sessionLabel ?? view.taskText.split("\n")[0]).slice(0, 40),
80545
- cloudFork: { sessionId: newSessionId(), toolSessionId: view.executorThreadId, cloudConversationId: view.executorSessionRef },
80572
+ cloudFork: { sessionId: newSessionId(), ...view.executorThreadId ? { toolSessionId: view.executorThreadId } : {}, cloudConversationId: view.executorSessionRef },
80546
80573
  a2aWorker: { contextId: view.contextId, sourceSessionId: initiator.sessionId }
80547
80574
  },
80548
80575
  ownerPrincipalId,
@@ -80557,6 +80584,14 @@ async function startDaemon(config) {
80557
80584
  return null;
80558
80585
  }
80559
80586
  },
80587
+ attachCloudWorkerThread: (sessionId, threadId) => {
80588
+ try {
80589
+ const attached = manager.attachCloudWorkerThread(sessionId, threadId);
80590
+ for (const b3 of attached?.broadcast ?? []) broadcastManagerFrame(b3.frame, b3.target);
80591
+ } catch (err) {
80592
+ logger.warn("a2a.attach-cloud-worker-thread-failed", { sessionId, error: err instanceof Error ? err.message : String(err) });
80593
+ }
80594
+ },
80560
80595
  every: (ms, fn) => {
80561
80596
  const timer = setInterval(fn, ms);
80562
80597
  timer.unref();