@clawos-dev/clawd 0.2.28-beta.38.7eb315d → 0.2.28

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 +115 -9
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -4408,10 +4408,17 @@ var init_methods = __esm({
4408
4408
  });
4409
4409
 
4410
4410
  // ../protocol/src/events.ts
4411
- var HISTORY_USER_META_VALUES, ASK_USER_QUESTION_TOOL_NAME;
4411
+ var SESSION_STATUS_VALUES, HISTORY_USER_META_VALUES, ASK_USER_QUESTION_TOOL_NAME;
4412
4412
  var init_events = __esm({
4413
4413
  "../protocol/src/events.ts"() {
4414
4414
  "use strict";
4415
+ SESSION_STATUS_VALUES = [
4416
+ "idle",
4417
+ "running",
4418
+ "stopped",
4419
+ "error",
4420
+ "observing"
4421
+ ];
4415
4422
  HISTORY_USER_META_VALUES = [
4416
4423
  "task-notification",
4417
4424
  "slash-command",
@@ -8698,13 +8705,14 @@ var init_persona_schemas = __esm({
8698
8705
  });
8699
8706
 
8700
8707
  // ../protocol/src/schemas.ts
8701
- var UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SessionSubscribeArgs, SessionPinArgs, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, GitWorktreePrefixArgs, GitWorktreePrefixResponseSchema, GitWorktreeCreateArgs, GitWorktreeCreateResponseSchema, GitWorktreeRemoveArgs, GitWorktreeRemoveResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelExitedEventSchema;
8708
+ var SessionStatusSchema, UsageSchema, ContextUsageSchema, sessionMetaShape, SessionMetaSchema, ModelInfoSchema, ModeInfoSchema, ConfigFieldSchemaSchema, CapabilitiesGetArgs, CapabilitiesResponseSchema, AllowRuleSchema, SessionFileSchema, ParsedEventBase, HistoryUserMetaSchema, SubagentToolStatsSchema, StructuredPatchHunkSchema, ToolResultExtraSchema, MemoryEntrySchema, AskQuestionOptionSchema, AskQuestionItemSchema, ParsedEventSchema, SessionCreateArgs, SessionIdArgs, SessionUpdateArgs, SessionSendArgs, SessionRewindArgs, SessionRewindResponseSchema, SessionRewindDiffArgs, RewindDiffHunkSchema, RewindDiffFileSchema, SessionRewindDiffResponseSchema, SessionRewindableMessageIdsArgs, SessionRewindableMessageIdsResponseSchema, SessionResumeArgs, SessionForkArgs, SessionForkResponseSchema, SessionObserveArgs, SessionEventsArgs, PermissionRespondArgs, HistoryListArgs, HistoryReadArgs, HistorySubagentsArgs, HistorySubagentReadArgs, WorkspaceListArgs, WorkspaceReadArgs, SkillsListArgs, SessionSubscribeArgs, SessionPinArgs, SessionReorderPinsArgs, GitRootArgs, GitRootResponseSchema, GitBranchArgs, GitBranchResponseSchema, GitBranchesArgs, GitBranchesResponseSchema, GitWorktreePrefixArgs, GitWorktreePrefixResponseSchema, GitWorktreeCreateArgs, GitWorktreeCreateResponseSchema, GitWorktreeRemoveArgs, GitWorktreeRemoveResponseSchema, HistoryRecentDirsArgs, RecentDirEntrySchema, HistoryRecentDirsResponseSchema, SessionQuestionFrameSchema, SessionQuestionClearedFrameSchema, AnswerQuestionArgs, AnswerQuestionResponseSchema, AuthRequestFrameSchema, AuthOkFrameSchema, TunnelExitedEventSchema, InfoRunningSessionSchema, InfoResponseSchema;
8702
8709
  var init_schemas = __esm({
8703
8710
  "../protocol/src/schemas.ts"() {
8704
8711
  "use strict";
8705
8712
  init_zod();
8706
8713
  init_events();
8707
8714
  init_persona_schemas();
8715
+ SessionStatusSchema = external_exports.enum(SESSION_STATUS_VALUES);
8708
8716
  UsageSchema = external_exports.object({
8709
8717
  input_tokens: external_exports.number().int().nonnegative().optional(),
8710
8718
  cache_read_input_tokens: external_exports.number().int().nonnegative().optional(),
@@ -9177,6 +9185,13 @@ var init_schemas = __esm({
9177
9185
  // UI 单卡承载多 question;空数组语义无效,schema 必拒
9178
9186
  questions: external_exports.array(AskQuestionItemSchema).min(1)
9179
9187
  });
9188
+ SessionQuestionClearedFrameSchema = external_exports.object({
9189
+ type: external_exports.literal("session:question:cleared"),
9190
+ sessionId: external_exports.string().min(1),
9191
+ toolUseId: external_exports.string().min(1),
9192
+ // record<string,string>:与 AnswerQuestionArgs.answers 同形状(question text → label)
9193
+ answers: external_exports.record(external_exports.string(), external_exports.string()).optional()
9194
+ });
9180
9195
  AnswerQuestionArgs = external_exports.object({
9181
9196
  sessionId: external_exports.string().min(1),
9182
9197
  toolUseId: external_exports.string().min(1),
@@ -9199,6 +9214,22 @@ var init_schemas = __esm({
9199
9214
  subdomain: external_exports.string().nullable(),
9200
9215
  url: external_exports.string().nullable()
9201
9216
  });
9217
+ InfoRunningSessionSchema = external_exports.object({
9218
+ sessionId: external_exports.string().min(1),
9219
+ status: SessionStatusSchema,
9220
+ freshSpawn: external_exports.boolean(),
9221
+ pendingPermissionsCount: external_exports.number().int().nonnegative(),
9222
+ pendingQuestionsCount: external_exports.number().int().nonnegative()
9223
+ });
9224
+ InfoResponseSchema = external_exports.object({
9225
+ type: external_exports.literal("info"),
9226
+ version: external_exports.string(),
9227
+ protocolVersion: external_exports.number(),
9228
+ hostname: external_exports.string(),
9229
+ os: external_exports.string(),
9230
+ tools: external_exports.array(external_exports.object({ id: external_exports.string(), available: external_exports.boolean() })),
9231
+ runningSessions: external_exports.array(InfoRunningSessionSchema)
9232
+ });
9202
9233
  }
9203
9234
  });
9204
9235
 
@@ -15860,6 +15891,16 @@ function applyCommand(state, command, deps) {
15860
15891
  return { state: nextState, effects };
15861
15892
  }
15862
15893
  case "stop": {
15894
+ for (const toolUseId of Object.keys(state.pendingQuestions ?? {})) {
15895
+ effects.push({
15896
+ kind: "emit-frame",
15897
+ frame: {
15898
+ type: "session:question:cleared",
15899
+ sessionId,
15900
+ toolUseId
15901
+ }
15902
+ });
15903
+ }
15863
15904
  next.pendingPermissions = {};
15864
15905
  next.pendingQuestions = {};
15865
15906
  if (next.procAlive) {
@@ -15887,6 +15928,16 @@ function applyCommand(state, command, deps) {
15887
15928
  return { state: next, effects };
15888
15929
  }
15889
15930
  case "delete": {
15931
+ for (const toolUseId of Object.keys(state.pendingQuestions ?? {})) {
15932
+ effects.push({
15933
+ kind: "emit-frame",
15934
+ frame: {
15935
+ type: "session:question:cleared",
15936
+ sessionId,
15937
+ toolUseId
15938
+ }
15939
+ });
15940
+ }
15890
15941
  next.pendingPermissions = {};
15891
15942
  next.pendingQuestions = {};
15892
15943
  if (next.procAlive) {
@@ -15998,6 +16049,17 @@ function reduceSession(state, input, deps) {
15998
16049
  const next = cloneState(state);
15999
16050
  next.procAlive = false;
16000
16051
  next.status = "stopped";
16052
+ const sessionId = next.file.sessionId;
16053
+ const clearedEffects = Object.keys(state.pendingQuestions ?? {}).map(
16054
+ (toolUseId) => ({
16055
+ kind: "emit-frame",
16056
+ frame: {
16057
+ type: "session:question:cleared",
16058
+ sessionId,
16059
+ toolUseId
16060
+ }
16061
+ })
16062
+ );
16001
16063
  next.pendingQuestions = {};
16002
16064
  return {
16003
16065
  state: next,
@@ -16006,11 +16068,12 @@ function reduceSession(state, input, deps) {
16006
16068
  kind: "emit-frame",
16007
16069
  frame: {
16008
16070
  type: "session:status",
16009
- sessionId: next.file.sessionId,
16071
+ sessionId,
16010
16072
  status: next.status,
16011
16073
  exitCode: input.code
16012
16074
  }
16013
- }
16075
+ },
16076
+ ...clearedEffects
16014
16077
  ]
16015
16078
  };
16016
16079
  }
@@ -16084,6 +16147,7 @@ function reduceSession(state, input, deps) {
16084
16147
  ...baseInput,
16085
16148
  answers: input.answers
16086
16149
  };
16150
+ const sessionId = next.file.sessionId;
16087
16151
  return {
16088
16152
  state: next,
16089
16153
  effects: [
@@ -16091,6 +16155,17 @@ function reduceSession(state, input, deps) {
16091
16155
  kind: "send-control-response-allow-with-input",
16092
16156
  requestId: pending.requestId,
16093
16157
  updatedInput
16158
+ },
16159
+ // cleared(with answers) broadcast:UI dispatch session:question:submitted,
16160
+ // pendingQuestions[toolUseId] 转 submitted 只读态。target 缺省=broadcast。
16161
+ {
16162
+ kind: "emit-frame",
16163
+ frame: {
16164
+ type: "session:question:cleared",
16165
+ sessionId,
16166
+ toolUseId: input.toolUseId,
16167
+ answers: input.answers
16168
+ }
16094
16169
  }
16095
16170
  ]
16096
16171
  };
@@ -17138,7 +17213,10 @@ var SessionManager = class {
17138
17213
  running.push({
17139
17214
  sessionId: sid,
17140
17215
  status: compressStatus(st.status),
17141
- freshSpawn: st.freshSpawn
17216
+ freshSpawn: st.freshSpawn,
17217
+ // sidebar awaiting-user baseline:UI 端据此填 anonymous slot 直到 push 帧带真实 toolUseId
17218
+ pendingPermissionsCount: Object.keys(st.pendingPermissions).length,
17219
+ pendingQuestionsCount: Object.keys(st.pendingQuestions).length
17142
17220
  });
17143
17221
  }
17144
17222
  return { runningSessions: running };
@@ -18317,9 +18395,15 @@ var LocalWsServer = class {
18317
18395
  return;
18318
18396
  }
18319
18397
  if (frame.type === "session:subscribe" && typeof frame.sessionId === "string") {
18320
- addSubscription(client, frame.sessionId);
18398
+ const sessionId = frame.sessionId;
18399
+ addSubscription(client, sessionId);
18321
18400
  if (typeof frame.requestId === "string") {
18322
- this.safeSend(this.clients.get(client.id).ws, { type: "subscribed", requestId: frame.requestId, sessionId: frame.sessionId });
18401
+ this.safeSend(this.clients.get(client.id).ws, { type: "subscribed", requestId: frame.requestId, sessionId });
18402
+ }
18403
+ try {
18404
+ this.opts.onSubscribe?.(client, sessionId);
18405
+ } catch (err) {
18406
+ this.logger?.warn("onSubscribe hook threw", { err: err.message });
18323
18407
  }
18324
18408
  return;
18325
18409
  }
@@ -20076,7 +20160,28 @@ async function startDaemon(config) {
20076
20160
  readyFrameBuilder: () => buildReadyFrame({ manager, getAdapter, getTunnelUrl: () => currentTunnelUrl }),
20077
20161
  protocolVersion: PROTOCOL_VERSION,
20078
20162
  authGate: authGate ?? void 0,
20079
- personaBoundHandler
20163
+ personaBoundHandler,
20164
+ // 订阅成功后给该 client 重放 in-flight pendingQuestions(plan: clawd-question-server-truth)。
20165
+ // daemon 是 pendingQuestions 的唯一 source of truth;新 client 接入 / 刷新页面时
20166
+ // 把当前所有未决 question 以 session:question 帧定向回放,让 UI 不再误显示 Ended。
20167
+ // 形状与 reducer permission_request 分支构造的 session:question 帧一致;UI 不区分
20168
+ // 首播 vs 重放(last-write-wins,详见 protocol/events.ts JSDoc)。
20169
+ onSubscribe: (client, sessionId) => {
20170
+ const runner = manager.getActive(sessionId);
20171
+ if (!runner) return;
20172
+ const pendingQuestions = runner.getState().pendingQuestions ?? {};
20173
+ for (const [toolUseId, entry] of Object.entries(pendingQuestions)) {
20174
+ const rawInput = entry.input;
20175
+ const questions = rawInput && typeof rawInput === "object" && "questions" in rawInput ? rawInput.questions : void 0;
20176
+ client.send({
20177
+ type: "session:question",
20178
+ sessionId,
20179
+ toolUseId,
20180
+ requestId: entry.requestId,
20181
+ questions: Array.isArray(questions) ? questions : []
20182
+ });
20183
+ }
20184
+ }
20080
20185
  });
20081
20186
  transport = wsServer;
20082
20187
  const wss = wsServer;
@@ -20196,7 +20301,8 @@ ${bar}
20196
20301
  stop: shutdown,
20197
20302
  url,
20198
20303
  tunnelUrl: stateSnapshot.tunnelUrl ?? null,
20199
- authToken: resolvedAuthToken
20304
+ authToken: resolvedAuthToken,
20305
+ manager
20200
20306
  };
20201
20307
  }
20202
20308
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.28-beta.38.7eb315d",
3
+ "version": "0.2.28",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",