shennian 0.3.63 → 0.3.65

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 (70) hide show
  1. package/dist/publish-build-manifest.json +78 -63
  2. package/dist/src/agents/adapter.d.ts +5 -1
  3. package/dist/src/agents/claude.d.ts +3 -2
  4. package/dist/src/agents/claude.js +6 -6
  5. package/dist/src/agents/workbuddy.d.ts +3 -2
  6. package/dist/src/agents/workbuddy.js +2 -2
  7. package/dist/src/index.js +3 -3
  8. package/dist/src/manager/runtime.js +8 -8
  9. package/dist/src/native-fusion/codex-files.d.ts +2 -0
  10. package/dist/src/native-fusion/codex-files.js +1 -0
  11. package/dist/src/native-fusion/codex-parser.d.ts +1 -2
  12. package/dist/src/native-fusion/codex-parser.js +3 -5
  13. package/dist/src/native-fusion/codex-user-input.d.ts +11 -0
  14. package/dist/src/native-fusion/codex-user-input.js +5 -0
  15. package/dist/src/native-fusion/file-watcher.d.ts +13 -5
  16. package/dist/src/native-fusion/file-watcher.js +1 -1
  17. package/dist/src/native-fusion/local-repository.d.ts +2 -0
  18. package/dist/src/native-fusion/local-repository.js +2 -2
  19. package/dist/src/native-fusion/parser-common.d.ts +1 -0
  20. package/dist/src/native-fusion/parser-common.js +4 -4
  21. package/dist/src/native-fusion/parsers.d.ts +1 -0
  22. package/dist/src/native-fusion/parsers.js +2 -2
  23. package/dist/src/native-fusion/service.d.ts +3 -0
  24. package/dist/src/native-fusion/service.js +2 -2
  25. package/dist/src/native-fusion/state.js +2 -2
  26. package/dist/src/native-fusion/types.d.ts +4 -0
  27. package/dist/src/personal-sync/epoch.d.ts +17 -0
  28. package/dist/src/personal-sync/epoch.js +2 -0
  29. package/dist/src/personal-sync/identity.js +2 -2
  30. package/dist/src/personal-sync/machine-authority.d.ts +11 -0
  31. package/dist/src/personal-sync/machine-authority.js +1 -0
  32. package/dist/src/personal-sync/metrics.d.ts +7 -1
  33. package/dist/src/personal-sync/metrics.js +1 -1
  34. package/dist/src/personal-sync/paths.d.ts +2 -5
  35. package/dist/src/personal-sync/paths.js +1 -1
  36. package/dist/src/relay/client.d.ts +8 -2
  37. package/dist/src/relay/client.js +1 -1
  38. package/dist/src/session/attachment-transfer-store.d.ts +10 -3
  39. package/dist/src/session/canonical-store.d.ts +2 -0
  40. package/dist/src/session/canonical-store.js +5 -5
  41. package/dist/src/session/deletion-sync-state.d.ts +18 -0
  42. package/dist/src/session/deletion-sync-state.js +2 -2
  43. package/dist/src/session/handlers/chat.js +2 -2
  44. package/dist/src/session/handlers/fs.js +1 -1
  45. package/dist/src/session/handlers/message-status.js +1 -1
  46. package/dist/src/session/handlers/title.js +1 -1
  47. package/dist/src/session/handlers/tool-detail.js +1 -1
  48. package/dist/src/session/handlers/voice-window.js +1 -1
  49. package/dist/src/session/history-subscriptions.js +1 -1
  50. package/dist/src/session/index-publisher.d.ts +2 -2
  51. package/dist/src/session/index-publisher.js +1 -1
  52. package/dist/src/session/manager.d.ts +1 -0
  53. package/dist/src/session/manager.js +1 -1
  54. package/dist/src/session/native-session-lifecycle.js +4 -4
  55. package/dist/src/session/queue.d.ts +1 -0
  56. package/dist/src/session/queue.js +4 -4
  57. package/dist/src/session/store.d.ts +16 -0
  58. package/dist/src/session/store.js +2 -2
  59. package/node_modules/@shennian/wire/dist/frames.d.ts +3 -0
  60. package/node_modules/@shennian/wire/dist/fs.d.ts +16 -6
  61. package/node_modules/@shennian/wire/dist/machine.d.ts +2 -0
  62. package/node_modules/@shennian/wire/dist/message-payload.js +2 -0
  63. package/node_modules/@shennian/wire/dist/session-sync.d.ts +76 -33
  64. package/node_modules/@shennian/wire/dist/session-sync.js +50 -2
  65. package/node_modules/@shennian/wire/dist/session.d.ts +20 -10
  66. package/node_modules/@shennian/wire/dist/tool-detail.d.ts +3 -2
  67. package/node_modules/@shennian/wire/package.json +1 -1
  68. package/package.json +1 -1
  69. package/dist/src/personal-sync/account-namespace.d.ts +0 -6
  70. package/dist/src/personal-sync/account-namespace.js +0 -1
@@ -1,15 +1,21 @@
1
1
  import type { Envelope } from './envelope.ts';
2
2
  import type { AgentType, ManagerConfig, SessionMode } from './session.ts';
3
- export declare const SESSION_SYNC_PROTOCOL_VERSION: 1;
3
+ export declare const SESSION_SYNC_PROTOCOL_VERSION: 2;
4
4
  export type SessionSyncProtocolVersion = typeof SESSION_SYNC_PROTOCOL_VERSION;
5
+ /**
6
+ * Monotonic authority generation for personal Session data. This is shared by
7
+ * daemon, Server and App; implementations must not carry a private cache epoch.
8
+ */
9
+ export declare const SESSION_SYNC_DATA_EPOCH: 2;
10
+ export type SessionSyncDataEpoch = typeof SESSION_SYNC_DATA_EPOCH;
5
11
  export declare const SESSION_SYNC_RELEASE_GATE: {
6
- readonly minCliVersion: "0.3.52";
12
+ readonly minCliVersion: "0.3.65";
7
13
  readonly minAppBuild: {
8
14
  readonly ios: 51;
9
15
  readonly android: 12;
10
16
  };
11
17
  };
12
- export declare const SESSION_SYNC_REQUIRED_CAPABILITIES: readonly ["session_index_v1", "session_body_revision_v1", "session_history_subscription_v1", "local_canonical_v1", "session_title_authority_v1", "session_title_seed_v1", "session_tool_detail_v1", "voice_session_body_relay_v1", "native_source_tombstone_v1", "session_durable_send_v1", "daemon_installation_identity_v1", "session_user_boundary_v1", "session_terminal_outbox_v1", "session_list_preview_v1", "session_attention_v1"];
18
+ export declare const SESSION_SYNC_REQUIRED_CAPABILITIES: readonly ["session_index_v1", "session_body_revision_v1", "session_history_subscription_v1", "local_canonical_v1", "session_title_authority_v1", "session_title_seed_v1", "session_tool_detail_v1", "voice_session_body_relay_v1", "native_source_tombstone_v1", "session_durable_send_v1", "daemon_installation_identity_v1", "session_user_boundary_v1", "session_terminal_outbox_v1", "session_list_preview_v1", "session_attention_v1", "session_data_epoch_v2", "session_structured_rejection_v2", "machine_personal_authority_v2"];
13
19
  export declare const SESSION_SYNC_EVENT_NAMES: readonly ["session.index.updated", "session.body.delta"];
14
20
  export declare const SESSION_HISTORY_LIMITS: {
15
21
  readonly defaultSnapshotMessages: 100;
@@ -25,10 +31,15 @@ export type SessionSyncCapability = (typeof SESSION_SYNC_REQUIRED_CAPABILITIES)[
25
31
  export type SessionSyncEventName = (typeof SESSION_SYNC_EVENT_NAMES)[number];
26
32
  export type SessionBodyStorageMode = 'machine_local';
27
33
  export type NativeCleanupPolicy = 'none' | 'auto';
34
+ export type PersonalSyncIdentity = {
35
+ protocolVersion: SessionSyncProtocolVersion;
36
+ dataEpoch: SessionSyncDataEpoch;
37
+ daemonInstallationId: string;
38
+ };
28
39
  export type SessionTitleSource = 'shennian_manual' | 'agent_native' | 'shennian_generated' | 'first_user_fallback';
29
40
  export declare const SESSION_TITLE_SOURCE_PRIORITY: Readonly<Record<SessionTitleSource, number>>;
30
41
  export declare function isSessionTitleSource(value: unknown): value is SessionTitleSource;
31
- export type SessionTitleSetParams = {
42
+ export type SessionTitleSetParams = PersonalSyncIdentity & {
32
43
  sessionId: string;
33
44
  agentType: AgentType;
34
45
  agentSessionId: string | null;
@@ -43,7 +54,7 @@ export type SessionTitleGenerationEligibility = 'agent_native_unavailable' | 'te
43
54
  * Ephemeral daemon -> Server request. titleSeed must never be persisted or
44
55
  * placed in an at-least-once event buffer by either side.
45
56
  */
46
- export type SessionTitleGenerateParams = {
57
+ export type SessionTitleGenerateParams = PersonalSyncIdentity & {
47
58
  sessionId: string;
48
59
  requestId: string;
49
60
  titleSeed: string;
@@ -60,7 +71,43 @@ export type SessionTitleGenerateResponse = {
60
71
  generated: false;
61
72
  reason: 'not_eligible' | 'superseded' | 'generator_unavailable' | 'generation_failed';
62
73
  };
63
- export type SessionSyncErrorCode = 'upgrade_required' | 'revision_gap' | 'snapshot_compacted' | 'machine_offline' | 'history_unavailable' | 'subscription_not_found' | 'subscription_limit_exceeded' | 'response_too_large';
74
+ export type SessionSyncErrorCode = 'upgrade_required' | 'epoch_mismatch' | 'session_deleted' | 'ownership_transferred' | 'token_revoked' | 'room_authority_conflict' | 'invalid_payload' | 'invalid_identity' | 'revision_gap' | 'snapshot_compacted' | 'machine_offline' | 'history_unavailable' | 'subscription_not_found' | 'subscription_limit_exceeded' | 'response_too_large' | 'temporary_unavailable';
75
+ export declare const SESSION_SYNC_REQUIRED_ACTIONS: readonly ["retry", "reset_epoch", "purge_session", "quarantine_record", "refresh_machine_ownership", "upgrade_client", "stop"];
76
+ export type SessionSyncRequiredAction = (typeof SESSION_SYNC_REQUIRED_ACTIONS)[number];
77
+ export type SessionSyncRejection = {
78
+ code: SessionSyncErrorCode;
79
+ retryable: boolean;
80
+ requiredAction: SessionSyncRequiredAction;
81
+ authoritativeEpoch?: SessionSyncDataEpoch;
82
+ authoritativeRevision?: number;
83
+ message?: string;
84
+ };
85
+ /** Privacy-safe regression cases shared by the cross-client hard-cut tests. */
86
+ export declare const PERSONAL_SYNC_FAILURE_FIXTURES: readonly [{
87
+ readonly id: "legacy_index_replay_after_server_reset";
88
+ readonly ingress: "session.index.updated";
89
+ readonly condition: "stale_data_epoch";
90
+ readonly expectedCode: "epoch_mismatch";
91
+ readonly expectedAction: "reset_epoch";
92
+ }, {
93
+ readonly id: "personal_index_targets_room_session";
94
+ readonly ingress: "session.index.updated";
95
+ readonly condition: "room_binding_exists";
96
+ readonly expectedCode: "room_authority_conflict";
97
+ readonly expectedAction: "quarantine_record";
98
+ }, {
99
+ readonly id: "history_response_not_durably_applied";
100
+ readonly ingress: "session.history.open";
101
+ readonly condition: "network_success_cache_revision_zero";
102
+ readonly expectedCode: "revision_gap";
103
+ readonly expectedAction: "stop";
104
+ }, {
105
+ readonly id: "native_path_move_replays_attention";
106
+ readonly ingress: "session.index.updated";
107
+ readonly condition: "same_source_event_identity";
108
+ readonly expectedCode: "invalid_payload";
109
+ readonly expectedAction: "quarantine_record";
110
+ }];
64
111
  export type SessionSyncError = {
65
112
  code: SessionSyncErrorCode;
66
113
  message?: string;
@@ -69,6 +116,9 @@ export type SessionSyncError = {
69
116
  expectedRevision?: number;
70
117
  actualRevision?: number;
71
118
  retryable: boolean;
119
+ requiredAction: SessionSyncRequiredAction;
120
+ authoritativeEpoch?: SessionSyncDataEpoch;
121
+ authoritativeRevision?: number;
72
122
  };
73
123
  export type PersonalAttachmentReference = {
74
124
  path: string;
@@ -79,7 +129,7 @@ export type PersonalAttachmentReference = {
79
129
  sha256: string;
80
130
  };
81
131
  export type SessionDeliveryState = 'queued' | 'committed' | 'executing' | 'completed' | 'failed' | 'cancelled';
82
- export type SessionDurableSendAck<TState extends SessionDeliveryState = SessionDeliveryState> = {
132
+ export type SessionDurableSendAck<TState extends SessionDeliveryState = SessionDeliveryState> = PersonalSyncIdentity & {
83
133
  sessionId: string;
84
134
  clientMessageId: string;
85
135
  messageId: string;
@@ -87,22 +137,22 @@ export type SessionDurableSendAck<TState extends SessionDeliveryState = SessionD
87
137
  bodyRevision: number;
88
138
  committedAt: string;
89
139
  };
90
- export type SessionMessageStatusParams = {
140
+ export type SessionMessageStatusParams = PersonalSyncIdentity & {
91
141
  sessionId: string;
92
142
  clientMessageId: string;
93
143
  };
94
- export type SessionMessageStatusResponse = {
144
+ export type SessionMessageStatusResponse = (PersonalSyncIdentity & {
95
145
  state: 'not_found';
96
146
  sessionId: string;
97
147
  clientMessageId: string;
98
- } | {
148
+ }) | {
99
149
  [TState in SessionDeliveryState]: {
100
150
  state: TState;
101
151
  } & SessionDurableSendAck<TState>;
102
152
  }[SessionDeliveryState];
103
153
  export declare function getMissingSessionSyncCapabilities(capabilities: readonly string[] | null | undefined): SessionSyncCapability[];
104
154
  export declare function hasRequiredSessionSyncCapabilities(capabilities: readonly string[] | null | undefined): capabilities is readonly SessionSyncCapability[];
105
- export type SessionHistoryOpenParams = {
155
+ export type SessionHistoryOpenParams = PersonalSyncIdentity & {
106
156
  sessionId: string;
107
157
  subscriptionId: string;
108
158
  cachedBodyRevision?: number;
@@ -115,7 +165,7 @@ export type SessionHistoryMessage = {
115
165
  message: Envelope;
116
166
  deliveryState?: SessionDeliveryState;
117
167
  };
118
- export type SessionHistorySnapshot = {
168
+ export type SessionHistorySnapshot = PersonalSyncIdentity & {
119
169
  sessionId: string;
120
170
  subscriptionId: string;
121
171
  storageMode: SessionBodyStorageMode;
@@ -125,13 +175,13 @@ export type SessionHistorySnapshot = {
125
175
  hasOlder: boolean;
126
176
  messages: SessionHistoryMessage[];
127
177
  };
128
- export type SessionHistoryPageParams = {
178
+ export type SessionHistoryPageParams = PersonalSyncIdentity & {
129
179
  sessionId: string;
130
180
  subscriptionId: string;
131
181
  beforeSequence: number;
132
182
  limit?: number;
133
183
  };
134
- export type SessionHistoryPage = {
184
+ export type SessionHistoryPage = PersonalSyncIdentity & {
135
185
  sessionId: string;
136
186
  subscriptionId: string;
137
187
  snapshotRevision: number;
@@ -139,30 +189,30 @@ export type SessionHistoryPage = {
139
189
  hasOlder: boolean;
140
190
  messages: SessionHistoryMessage[];
141
191
  };
142
- export type VoiceSessionBodyWindowParams = {
192
+ export type VoiceSessionBodyWindowParams = PersonalSyncIdentity & {
143
193
  sessionId: string;
144
194
  callId: string;
145
195
  bodyRevision?: number;
146
196
  limit?: number;
147
197
  maxBytes?: number;
148
198
  };
149
- export type VoiceSessionBodyWindow = {
199
+ export type VoiceSessionBodyWindow = PersonalSyncIdentity & {
150
200
  sessionId: string;
151
201
  callId: string;
152
202
  bodyRevision: number;
153
203
  messages: Envelope[];
154
204
  truncated: boolean;
155
205
  };
156
- export type SessionHistoryCloseParams = {
206
+ export type SessionHistoryCloseParams = PersonalSyncIdentity & {
157
207
  sessionId: string;
158
208
  subscriptionId: string;
159
209
  };
160
- export type SessionHistoryCloseResponse = {
210
+ export type SessionHistoryCloseResponse = PersonalSyncIdentity & {
161
211
  sessionId: string;
162
212
  subscriptionId: string;
163
213
  closed: true;
164
214
  };
165
- export type SessionBodyMutation = {
215
+ export type SessionBodyMutation = PersonalSyncIdentity & {
166
216
  sessionId: string;
167
217
  subscriptionId: string;
168
218
  revision: number;
@@ -172,7 +222,7 @@ export type SessionBodyMutation = {
172
222
  message?: Envelope;
173
223
  deliveryState?: SessionDeliveryState;
174
224
  };
175
- export type SessionBodyDeltaEvent = {
225
+ export type SessionBodyDeltaEvent = PersonalSyncIdentity & {
176
226
  sessionId: string;
177
227
  subscriptionId: string;
178
228
  fromRevision: number;
@@ -230,9 +280,7 @@ export type DaemonSessionIndexProjection = {
230
280
  updatedAt: string;
231
281
  deletedAt: string | null;
232
282
  };
233
- export type SessionIndexUpdate = {
234
- protocolVersion: SessionSyncProtocolVersion;
235
- daemonInstallationId: string;
283
+ export type SessionIndexUpdate = PersonalSyncIdentity & {
236
284
  session: DaemonSessionIndexProjection;
237
285
  };
238
286
  export type NativeSourceDeletionRef = {
@@ -249,27 +297,22 @@ export type SessionDeletionCommand = {
249
297
  deletedAt: string;
250
298
  /** Origin working directory; required by project-scoped lifecycle tools such as Gemini. */
251
299
  workDir?: string;
252
- /** Missing means `none` for compatibility with older Server/App versions. */
253
- nativeCleanupPolicy?: NativeCleanupPolicy;
300
+ nativeCleanupPolicy: NativeCleanupPolicy;
254
301
  sources: NativeSourceDeletionRef[];
255
302
  };
256
- export type SessionDeletionsSyncParams = {
257
- protocolVersion: SessionSyncProtocolVersion;
258
- daemonInstallationId: string;
303
+ export type SessionDeletionsSyncParams = PersonalSyncIdentity & {
259
304
  afterRevision: number;
260
305
  };
261
- export type SessionDeletionsSyncResponse = {
306
+ export type SessionDeletionsSyncResponse = PersonalSyncIdentity & {
262
307
  /** Highest pruned revision the daemon may durably baseline before applying returned commands. */
263
308
  baselineRevision: number;
264
309
  latestRevision: number;
265
310
  deletions: SessionDeletionCommand[];
266
311
  };
267
- export type SessionDeletionsAckParams = {
268
- protocolVersion: SessionSyncProtocolVersion;
269
- daemonInstallationId: string;
312
+ export type SessionDeletionsAckParams = PersonalSyncIdentity & {
270
313
  deletionRevision: number;
271
314
  };
272
- export type SessionDeletionsAckResponse = {
315
+ export type SessionDeletionsAckResponse = PersonalSyncIdentity & {
273
316
  deletionRevision: number;
274
317
  acknowledged: true;
275
318
  };
@@ -1,8 +1,13 @@
1
1
  // @arch docs/architecture/data-sync.md#目标架构-v3
2
2
  // @test src/__tests__/session-sync.test.ts
3
- export const SESSION_SYNC_PROTOCOL_VERSION = 1;
3
+ export const SESSION_SYNC_PROTOCOL_VERSION = 2;
4
+ /**
5
+ * Monotonic authority generation for personal Session data. This is shared by
6
+ * daemon, Server and App; implementations must not carry a private cache epoch.
7
+ */
8
+ export const SESSION_SYNC_DATA_EPOCH = 2;
4
9
  export const SESSION_SYNC_RELEASE_GATE = {
5
- minCliVersion: '0.3.52',
10
+ minCliVersion: '0.3.65',
6
11
  minAppBuild: { ios: 51, android: 12 },
7
12
  };
8
13
  export const SESSION_SYNC_REQUIRED_CAPABILITIES = [
@@ -21,6 +26,9 @@ export const SESSION_SYNC_REQUIRED_CAPABILITIES = [
21
26
  'session_terminal_outbox_v1',
22
27
  'session_list_preview_v1',
23
28
  'session_attention_v1',
29
+ 'session_data_epoch_v2',
30
+ 'session_structured_rejection_v2',
31
+ 'machine_personal_authority_v2',
24
32
  ];
25
33
  export const SESSION_SYNC_EVENT_NAMES = [
26
34
  'session.index.updated',
@@ -45,6 +53,46 @@ export const SESSION_TITLE_SOURCE_PRIORITY = {
45
53
  export function isSessionTitleSource(value) {
46
54
  return typeof value === 'string' && value in SESSION_TITLE_SOURCE_PRIORITY;
47
55
  }
56
+ export const SESSION_SYNC_REQUIRED_ACTIONS = [
57
+ 'retry',
58
+ 'reset_epoch',
59
+ 'purge_session',
60
+ 'quarantine_record',
61
+ 'refresh_machine_ownership',
62
+ 'upgrade_client',
63
+ 'stop',
64
+ ];
65
+ /** Privacy-safe regression cases shared by the cross-client hard-cut tests. */
66
+ export const PERSONAL_SYNC_FAILURE_FIXTURES = [
67
+ {
68
+ id: 'legacy_index_replay_after_server_reset',
69
+ ingress: 'session.index.updated',
70
+ condition: 'stale_data_epoch',
71
+ expectedCode: 'epoch_mismatch',
72
+ expectedAction: 'reset_epoch',
73
+ },
74
+ {
75
+ id: 'personal_index_targets_room_session',
76
+ ingress: 'session.index.updated',
77
+ condition: 'room_binding_exists',
78
+ expectedCode: 'room_authority_conflict',
79
+ expectedAction: 'quarantine_record',
80
+ },
81
+ {
82
+ id: 'history_response_not_durably_applied',
83
+ ingress: 'session.history.open',
84
+ condition: 'network_success_cache_revision_zero',
85
+ expectedCode: 'revision_gap',
86
+ expectedAction: 'stop',
87
+ },
88
+ {
89
+ id: 'native_path_move_replays_attention',
90
+ ingress: 'session.index.updated',
91
+ condition: 'same_source_event_identity',
92
+ expectedCode: 'invalid_payload',
93
+ expectedAction: 'quarantine_record',
94
+ },
95
+ ];
48
96
  export function getMissingSessionSyncCapabilities(capabilities) {
49
97
  const available = new Set(capabilities ?? []);
50
98
  return SESSION_SYNC_REQUIRED_CAPABILITIES.filter((capability) => !available.has(capability));
@@ -1,5 +1,5 @@
1
1
  import type { NativeSessionSourceMode } from './native-session.js';
2
- import type { PersonalAttachmentReference, SessionBodyStorageMode, SessionTitleSource } from './session-sync.js';
2
+ import type { PersonalAttachmentReference, PersonalSyncIdentity, SessionBodyStorageMode, SessionTitleSource } from './session-sync.js';
3
3
  export type BuiltinAgentType = 'claude' | 'codex' | 'workbuddy' | 'gemini' | 'cursor' | 'openclaw' | 'opencode' | 'pi' | 'manager';
4
4
  export type CustomAgentType = `custom:${string}`;
5
5
  export type AgentType = BuiltinAgentType | CustomAgentType;
@@ -80,6 +80,14 @@ export type SessionUserState = {
80
80
  manualUnread?: boolean;
81
81
  updatedAt: string;
82
82
  };
83
+ /** Exact lightweight index state the user actually saw before marking a Session read. */
84
+ export type SessionReadWatermark = {
85
+ bodyRevision: number;
86
+ visibleMessageCount: number;
87
+ lastVisibleMessageId: string | null;
88
+ attentionCount: number;
89
+ lastAttentionId: string | null;
90
+ };
83
91
  export type SessionRunPhase = 'thinking' | 'tool_running' | 'streaming_text' | 'waiting_approval' | 'waiting_user_input';
84
92
  export type SessionActivitySnapshot = {
85
93
  sessionId: string;
@@ -209,6 +217,8 @@ export type NianSession = {
209
217
  localReady?: boolean;
210
218
  bodyRevision?: number;
211
219
  indexRevision?: number;
220
+ /** Personal data authority generation; absent only for Room/legacy projections. */
221
+ dataEpoch?: import('./session-sync.ts').SessionSyncDataEpoch;
212
222
  firstAvailableSeq?: number | null;
213
223
  visibleMessageCount?: number;
214
224
  lastVisibleMessageId?: string | null;
@@ -231,8 +241,8 @@ export type NianSession = {
231
241
  activity?: SessionActivitySnapshot | null;
232
242
  externalChannel?: ExternalChannelSessionStatus | null;
233
243
  };
234
- export type SessionListProjection = Pick<NianSession, 'id' | 'machineId' | 'userId' | 'agentType' | 'sessionMode' | 'managerConfig' | 'agentSessionId' | 'modelId' | 'managerDefaultWorkerAgentType' | 'managerDefaultWorkerModelId' | 'title' | 'titleSource' | 'titleRevision' | 'titleLockedByUser' | 'titleOriginEventId' | 'status' | 'workDir' | 'lastMessagePreview' | 'lastMessagePreviewMessageId' | 'lastMessagePreviewAt' | 'bodyStorageMode' | 'bodyRevision' | 'indexRevision' | 'firstAvailableSeq' | 'visibleMessageCount' | 'lastVisibleMessageId' | 'attentionCount' | 'lastAttentionId' | 'lastBodyCommittedAt' | 'deletionRevision' | 'lastActivityAt' | 'createdAt' | 'updatedAt' | 'deletedAt' | 'machineName' | 'ownerName' | 'ownerPhone' | 'ownerEmail' | 'canManage' | 'sharedMachineSession' | 'activity' | 'externalChannel'>;
235
- export type ChatSendParams = {
244
+ export type SessionListProjection = Pick<NianSession, 'id' | 'machineId' | 'userId' | 'agentType' | 'sessionMode' | 'managerConfig' | 'agentSessionId' | 'modelId' | 'managerDefaultWorkerAgentType' | 'managerDefaultWorkerModelId' | 'title' | 'titleSource' | 'titleRevision' | 'titleLockedByUser' | 'titleOriginEventId' | 'status' | 'workDir' | 'lastMessagePreview' | 'lastMessagePreviewMessageId' | 'lastMessagePreviewAt' | 'bodyStorageMode' | 'bodyRevision' | 'indexRevision' | 'dataEpoch' | 'firstAvailableSeq' | 'visibleMessageCount' | 'lastVisibleMessageId' | 'attentionCount' | 'lastAttentionId' | 'lastBodyCommittedAt' | 'deletionRevision' | 'lastActivityAt' | 'createdAt' | 'updatedAt' | 'deletedAt' | 'machineName' | 'ownerName' | 'ownerPhone' | 'ownerEmail' | 'canManage' | 'sharedMachineSession' | 'activity' | 'externalChannel'>;
245
+ export type ChatSendParams = PersonalSyncIdentity & {
236
246
  sessionId: string;
237
247
  text: string;
238
248
  agentType: string;
@@ -254,7 +264,7 @@ export type ChatSendParams = {
254
264
  externalChannel?: ExternalChannelSessionStatus | null;
255
265
  replyTarget?: string | null;
256
266
  };
257
- export type QueuedChatMessage = {
267
+ export type QueuedChatMessage = PersonalSyncIdentity & {
258
268
  id: string;
259
269
  sessionId: string;
260
270
  text: string;
@@ -278,7 +288,7 @@ export type QueuedChatMessage = {
278
288
  createdAt: string;
279
289
  updatedAt: string;
280
290
  };
281
- export type ChatQueueSnapshot = {
291
+ export type ChatQueueSnapshot = PersonalSyncIdentity & {
282
292
  sessionId: string;
283
293
  busy: boolean;
284
294
  pending: QueuedChatMessage[];
@@ -287,10 +297,10 @@ export type ChatEnqueueParams = ChatSendParams & {
287
297
  queueMessageId?: string;
288
298
  origin?: 'app' | 'external';
289
299
  };
290
- export type ChatQueueGetParams = {
300
+ export type ChatQueueGetParams = PersonalSyncIdentity & {
291
301
  sessionId: string;
292
302
  };
293
- export type ChatQueueEditParams = {
303
+ export type ChatQueueEditParams = PersonalSyncIdentity & {
294
304
  sessionId: string;
295
305
  queueMessageId: string;
296
306
  text: string;
@@ -299,15 +309,15 @@ export type ChatQueueEditParams = {
299
309
  previewData?: string;
300
310
  }>;
301
311
  };
302
- export type ChatQueueDeleteParams = {
312
+ export type ChatQueueDeleteParams = PersonalSyncIdentity & {
303
313
  sessionId: string;
304
314
  queueMessageId: string;
305
315
  };
306
- export type SessionResumeParams = {
316
+ export type SessionResumeParams = PersonalSyncIdentity & {
307
317
  sessionId: string;
308
318
  agentSessionId: string | null;
309
319
  };
310
- export type SessionHistoryParams = {
320
+ export type SessionHistoryParams = PersonalSyncIdentity & {
311
321
  sessionId: string;
312
322
  limit?: number;
313
323
  before?: number;
@@ -1,3 +1,4 @@
1
+ import type { PersonalSyncIdentity } from './session-sync.ts';
1
2
  export declare const SESSION_TOOL_DETAIL_LIMITS: {
2
3
  readonly defaultMaxBytes: number;
3
4
  readonly minMaxBytes: number;
@@ -13,13 +14,13 @@ export type ToolDetailRef = {
13
14
  sourceSeq?: number;
14
15
  toolIndex?: number;
15
16
  };
16
- export type SessionToolDetailRequest = {
17
+ export type SessionToolDetailRequest = PersonalSyncIdentity & {
17
18
  sessionId: string;
18
19
  toolCallId: string;
19
20
  detailRevision: number;
20
21
  maxBytes?: number;
21
22
  };
22
- export type SessionToolDetailResponse = {
23
+ export type SessionToolDetailResponse = PersonalSyncIdentity & {
23
24
  sessionId: string;
24
25
  toolCallId: string;
25
26
  detailRevision: number;
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "scripts": {
20
20
  "build": "tsc",
21
- "build:publish": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc --sourceMap false --declarationMap false",
21
+ "build:publish": "node -e \"const fs=require('node:fs'); fs.rmSync('dist', { recursive: true, force: true }); fs.rmSync('tsconfig.tsbuildinfo', { force: true })\" && tsc --sourceMap false --declarationMap false",
22
22
  "dev": "tsc --watch",
23
23
  "prepublishOnly": "pnpm build"
24
24
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shennian",
3
- "version": "0.3.63",
3
+ "version": "0.3.65",
4
4
  "description": "Shennian — AI Agent Control Plane CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +0,0 @@
1
- export declare function synchronizeActiveAccountNamespace(input: {
2
- serverUrl: string;
3
- machineToken: string;
4
- machineId?: string | null;
5
- fetchImpl?: typeof fetch;
6
- }): Promise<string>;
@@ -1 +0,0 @@
1
- import{loadConfig as o,saveConfig as t}from"../config/index.js";const i=/^[a-f0-9]{64}$/;async function r(e){const c=await(e.fetchImpl??fetch)(`${e.serverUrl.replace(/\/+$/,"")}/api/machines/identity`,{headers:{Authorization:`Bearer ${e.machineToken}`},signal:AbortSignal.timeout(1e4)});if(!c.ok)throw new Error(`account_namespace_unavailable:${c.status}`);const a=await c.json();if(typeof a.machineId!="string"||!a.machineId||typeof a.accountNamespaceId!="string"||!i.test(a.accountNamespaceId))throw new Error("account_namespace_invalid_response");if(e.machineId&&a.machineId!==e.machineId)throw new Error("account_namespace_machine_mismatch");const n=o();return(n.accountNamespaceId!==a.accountNamespaceId||n.machineId!==a.machineId)&&t({...n,machineId:a.machineId,accountNamespaceId:a.accountNamespaceId}),a.accountNamespaceId}export{r as synchronizeActiveAccountNamespace};