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.
- package/dist/publish-build-manifest.json +78 -63
- package/dist/src/agents/adapter.d.ts +5 -1
- package/dist/src/agents/claude.d.ts +3 -2
- package/dist/src/agents/claude.js +6 -6
- package/dist/src/agents/workbuddy.d.ts +3 -2
- package/dist/src/agents/workbuddy.js +2 -2
- package/dist/src/index.js +3 -3
- package/dist/src/manager/runtime.js +8 -8
- package/dist/src/native-fusion/codex-files.d.ts +2 -0
- package/dist/src/native-fusion/codex-files.js +1 -0
- package/dist/src/native-fusion/codex-parser.d.ts +1 -2
- package/dist/src/native-fusion/codex-parser.js +3 -5
- package/dist/src/native-fusion/codex-user-input.d.ts +11 -0
- package/dist/src/native-fusion/codex-user-input.js +5 -0
- package/dist/src/native-fusion/file-watcher.d.ts +13 -5
- package/dist/src/native-fusion/file-watcher.js +1 -1
- package/dist/src/native-fusion/local-repository.d.ts +2 -0
- package/dist/src/native-fusion/local-repository.js +2 -2
- package/dist/src/native-fusion/parser-common.d.ts +1 -0
- package/dist/src/native-fusion/parser-common.js +4 -4
- package/dist/src/native-fusion/parsers.d.ts +1 -0
- package/dist/src/native-fusion/parsers.js +2 -2
- package/dist/src/native-fusion/service.d.ts +3 -0
- package/dist/src/native-fusion/service.js +2 -2
- package/dist/src/native-fusion/state.js +2 -2
- package/dist/src/native-fusion/types.d.ts +4 -0
- package/dist/src/personal-sync/epoch.d.ts +17 -0
- package/dist/src/personal-sync/epoch.js +2 -0
- package/dist/src/personal-sync/identity.js +2 -2
- package/dist/src/personal-sync/machine-authority.d.ts +11 -0
- package/dist/src/personal-sync/machine-authority.js +1 -0
- package/dist/src/personal-sync/metrics.d.ts +7 -1
- package/dist/src/personal-sync/metrics.js +1 -1
- package/dist/src/personal-sync/paths.d.ts +2 -5
- package/dist/src/personal-sync/paths.js +1 -1
- package/dist/src/relay/client.d.ts +8 -2
- package/dist/src/relay/client.js +1 -1
- package/dist/src/session/attachment-transfer-store.d.ts +10 -3
- package/dist/src/session/canonical-store.d.ts +2 -0
- package/dist/src/session/canonical-store.js +5 -5
- package/dist/src/session/deletion-sync-state.d.ts +18 -0
- package/dist/src/session/deletion-sync-state.js +2 -2
- package/dist/src/session/handlers/chat.js +2 -2
- package/dist/src/session/handlers/fs.js +1 -1
- package/dist/src/session/handlers/message-status.js +1 -1
- package/dist/src/session/handlers/title.js +1 -1
- package/dist/src/session/handlers/tool-detail.js +1 -1
- package/dist/src/session/handlers/voice-window.js +1 -1
- package/dist/src/session/history-subscriptions.js +1 -1
- package/dist/src/session/index-publisher.d.ts +2 -2
- package/dist/src/session/index-publisher.js +1 -1
- package/dist/src/session/manager.d.ts +1 -0
- package/dist/src/session/manager.js +1 -1
- package/dist/src/session/native-session-lifecycle.js +4 -4
- package/dist/src/session/queue.d.ts +1 -0
- package/dist/src/session/queue.js +4 -4
- package/dist/src/session/store.d.ts +16 -0
- package/dist/src/session/store.js +2 -2
- package/node_modules/@shennian/wire/dist/frames.d.ts +3 -0
- package/node_modules/@shennian/wire/dist/fs.d.ts +16 -6
- package/node_modules/@shennian/wire/dist/machine.d.ts +2 -0
- package/node_modules/@shennian/wire/dist/message-payload.js +2 -0
- package/node_modules/@shennian/wire/dist/session-sync.d.ts +76 -33
- package/node_modules/@shennian/wire/dist/session-sync.js +50 -2
- package/node_modules/@shennian/wire/dist/session.d.ts +20 -10
- package/node_modules/@shennian/wire/dist/tool-detail.d.ts +3 -2
- package/node_modules/@shennian/wire/package.json +1 -1
- package/package.json +1 -1
- package/dist/src/personal-sync/account-namespace.d.ts +0 -6
- 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:
|
|
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.
|
|
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
|
-
|
|
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 =
|
|
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.
|
|
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 +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};
|