@clawos-dev/clawd 0.2.218-beta.429.c31b635 → 0.2.219-beta.430.6b524a2

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/cli.cjs +60 -101
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -41651,6 +41651,47 @@ function escapeAttr(v2) {
41651
41651
  return v2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
41652
41652
  }
41653
41653
 
41654
+ // src/shift/end-frame-handler.ts
41655
+ function makeEndFrameHandler(sessionId, onEnd) {
41656
+ return (frame) => {
41657
+ if (!frame || typeof frame !== "object") return;
41658
+ const f = frame;
41659
+ if (f.type !== "session:status") return;
41660
+ if (f.sessionId !== sessionId) return;
41661
+ if (f.status === "running-idle") {
41662
+ onEnd({ kind: "idle" });
41663
+ return;
41664
+ }
41665
+ if (f.status === "stopped") {
41666
+ onEnd({ kind: "stopped" });
41667
+ return;
41668
+ }
41669
+ if (f.status === "error") {
41670
+ onEnd({ kind: "error", message: f.message ?? "cc proc error" });
41671
+ return;
41672
+ }
41673
+ };
41674
+ }
41675
+
41676
+ // src/shift/end-dispatcher.ts
41677
+ function dispatchShiftEnd(info, settle, killImpl) {
41678
+ if (info.kind === "idle") {
41679
+ settle({ ok: true });
41680
+ killImpl();
41681
+ return;
41682
+ }
41683
+ if (info.kind === "stopped") {
41684
+ settle({ error: "cc exited before turn completed" });
41685
+ return;
41686
+ }
41687
+ if (info.kind === "error") {
41688
+ settle({ error: info.message });
41689
+ return;
41690
+ }
41691
+ const _exhaustive = info;
41692
+ throw new Error(`dispatchShiftEnd: unhandled kind ${JSON.stringify(_exhaustive)}`);
41693
+ }
41694
+
41654
41695
  // src/session/runner.ts
41655
41696
  var import_node_os4 = __toESM(require("os"), 1);
41656
41697
  var import_node_path7 = __toESM(require("path"), 1);
@@ -44469,8 +44510,9 @@ var SessionManager = class {
44469
44510
  * 跟 createDispatchedSession 的差异:
44470
44511
  * - 不带 dispatchId / source / task pack;prompt 直接当第一条 user message
44471
44512
  * - 不调 personaDispatchManager.registerBSession
44472
- * - 多返一个 ended Promise,监听 session:status (stopped/error) 帧通过现有
44473
- * subscribe() 入口(白名单已含 session:status)
44513
+ * - 多返一个 ended Promise,监听 session:status 帧翻译成 shift 业务终态 union
44514
+ * (ShiftSessionEnded:{ok:true} | {error:string}),不经 exit code 中转
44515
+ * - turn-idle 到达即视为业务完成 → settle {ok:true} + fire-and-forget kill cc
44474
44516
  * - kill 通过 runner.input({command:{kind:'stop'}}) 触发 SIGKILL → proc-exit
44475
44517
  */
44476
44518
  createShiftSession(args) {
@@ -44514,16 +44556,18 @@ var SessionManager = class {
44514
44556
  unsubscribe();
44515
44557
  resolveEnded(info);
44516
44558
  };
44517
- unsubscribe = this.subscribe(sessionId, scope, (frame) => {
44518
- if (frame.type !== "session:status") return;
44519
- const f = frame;
44520
- if (f.sessionId !== sessionId) return;
44521
- if (f.status === "stopped") {
44522
- settle({ exitCode: f.exitCode ?? null });
44523
- } else if (f.status === "error") {
44524
- settle({ exitCode: null, error: f.message ?? "cc proc error" });
44525
- }
44526
- });
44559
+ const killImpl = () => {
44560
+ const r = this.runners.get(sessionId);
44561
+ if (!r) return;
44562
+ r.input({ kind: "command", command: { kind: "stop" } });
44563
+ };
44564
+ unsubscribe = this.subscribe(
44565
+ sessionId,
44566
+ scope,
44567
+ makeEndFrameHandler(sessionId, (info) => {
44568
+ dispatchShiftEnd(info, settle, killImpl);
44569
+ })
44570
+ );
44527
44571
  const runner = this.ensureRunnerForScope(file, scope);
44528
44572
  this.deps.logger?.info("shift.createShiftSession.runner-ready", { sessionId });
44529
44573
  runner.input({
@@ -44536,12 +44580,7 @@ var SessionManager = class {
44536
44580
  })
44537
44581
  }
44538
44582
  });
44539
- const kill = () => {
44540
- const r = this.runners.get(sessionId);
44541
- if (!r) return;
44542
- r.input({ kind: "command", command: { kind: "stop" } });
44543
- };
44544
- return { sessionId, ended, kill };
44583
+ return { sessionId, ended, kill: killImpl };
44545
44584
  }
44546
44585
  /**
44547
44586
  * 老板插话:把 'inject-owner-text' input 喂给对应 runner,
@@ -48446,15 +48485,11 @@ function createShiftSpawnFn(deps) {
48446
48485
  void created.ended.then((info) => {
48447
48486
  clearTimeout(timer);
48448
48487
  if (settled) return;
48449
- if (info.error) {
48450
- settle({ kind: "error", error: info.error });
48451
- return;
48452
- }
48453
- if (info.exitCode === 0) {
48488
+ if ("ok" in info) {
48454
48489
  settle({ kind: "ok" });
48455
48490
  return;
48456
48491
  }
48457
- settle({ kind: "error", error: `cc exited with code ${info.exitCode}` });
48492
+ settle({ kind: "error", error: info.error });
48458
48493
  });
48459
48494
  return { sessionId: created.sessionId, ended };
48460
48495
  };
@@ -54191,22 +54226,6 @@ var LoginFlow = class {
54191
54226
  } catch (err) {
54192
54227
  return { ok: false, reason: `user_info failed: ${err.message}` };
54193
54228
  }
54194
- if (!identity.unionId) {
54195
- return { ok: false, reason: "union_id missing from TTC user_info" };
54196
- }
54197
- try {
54198
- await this.deps.upsertBinding({
54199
- deviceId: this.deps.getDeviceId(),
54200
- unionId: identity.unionId,
54201
- displayName: identity.displayName,
54202
- avatarUrl: identity.avatarUrl ?? null
54203
- });
54204
- } catch (err) {
54205
- return {
54206
- ok: false,
54207
- reason: `device_binding upsert failed: ${err.message}`
54208
- };
54209
- }
54210
54229
  const expiresAtNum = params.expiresAt ? Number.parseInt(params.expiresAt, 10) : NaN;
54211
54230
  this.deps.store.write({
54212
54231
  identity,
@@ -54375,57 +54394,6 @@ async function centralListDevices(opts) {
54375
54394
  return out;
54376
54395
  }
54377
54396
 
54378
- // src/feishu-auth/device-binding-client.ts
54379
- var DeviceBindingClientError = class extends Error {
54380
- constructor(code, message, cause) {
54381
- super(message);
54382
- this.code = code;
54383
- this.cause = cause;
54384
- this.name = "DeviceBindingClientError";
54385
- }
54386
- code;
54387
- cause;
54388
- };
54389
- var DEFAULT_TIMEOUT_MS4 = 8e3;
54390
- async function upsertDeviceBinding(opts) {
54391
- const doFetch = opts.fetchImpl ?? fetch;
54392
- const ac = new AbortController();
54393
- const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4);
54394
- const body = { unionId: opts.unionId };
54395
- if (opts.avatarUrl != null) body.avatarUrl = opts.avatarUrl;
54396
- let res;
54397
- try {
54398
- res = await doFetch(`${opts.apiUrl}/api/device-bindings/self`, {
54399
- method: "PUT",
54400
- signal: ac.signal,
54401
- headers: {
54402
- authorization: `Bearer ${opts.apiKey}`,
54403
- "x-did": encodeURIComponent(opts.deviceId),
54404
- "x-name": encodeURIComponent(opts.displayName),
54405
- "content-type": "application/json"
54406
- },
54407
- body: JSON.stringify(body)
54408
- });
54409
- } catch (err) {
54410
- clearTimeout(timer);
54411
- throw new DeviceBindingClientError(
54412
- "NETWORK",
54413
- `network error: ${err.message}`,
54414
- err
54415
- );
54416
- } finally {
54417
- clearTimeout(timer);
54418
- }
54419
- if (!res.ok) {
54420
- let detail = "";
54421
- try {
54422
- detail = JSON.stringify(await res.json());
54423
- } catch {
54424
- }
54425
- throw new DeviceBindingClientError("API_ERROR", `HTTP ${res.status}: ${detail}`);
54426
- }
54427
- }
54428
-
54429
54397
  // src/feishu-auth/verify-token.ts
54430
54398
  var crypto14 = __toESM(require("crypto"), 1);
54431
54399
  var CONNECT_TOKEN_PREFIX = "clawdtk1";
@@ -59595,16 +59563,7 @@ async function startDaemon(config) {
59595
59563
  store: ownerIdentityStore,
59596
59564
  fetchUserInfo: (ttcToken) => fetchTtcUserInfo({ apiBase: TTC_HOSTS.api, token: ttcToken }),
59597
59565
  ttcAuthBase: TTC_HOSTS.auth,
59598
- getCallbackUrl: () => `http://127.0.0.1:${config.port}/auth/callback`,
59599
- // device_bindings upsert(did ↔ 飞书 unionId 映射):
59600
- // deviceId 从 auth.json 稳定读;apiUrl 走同一份 clawosApi;apiKey 复用 CLAWD_TICKETS_API_KEY。
59601
- // 失败即登录失败(fail-hard,login-flow.spec §upsert 失败)。
59602
- getDeviceId: () => authFile.deviceId,
59603
- upsertBinding: (opts) => upsertDeviceBinding({
59604
- apiUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
59605
- apiKey: resolveClawdTicketsApiKey(),
59606
- ...opts
59607
- })
59566
+ getCallbackUrl: () => `http://127.0.0.1:${config.port}/auth/callback`
59608
59567
  });
59609
59568
  const visitorStore = createVisitorStore({ dir: config.dataDir });
59610
59569
  const exchangeVisitorToken = buildVisitorLogin({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.218-beta.429.c31b635",
3
+ "version": "0.2.219-beta.430.6b524a2",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",