@sema-agent/client-core 0.101.0 → 0.103.0
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/CHANGELOG.md +153 -0
- package/README.md +19 -11
- package/dist/adapt/toolCards.d.ts +4 -2
- package/dist/adapt/toolCards.js +22 -6
- package/dist/adapt.d.ts +1 -1
- package/dist/adapt.js +1 -1
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +5 -1
- package/dist/adapter/downstream/eventToSdkMessage.js +26 -70
- package/dist/adapter/downstream/terminalToSdkResult.js +0 -1
- package/dist/adapter/downstream/wiringManifestView.d.ts +1 -0
- package/dist/adapter/downstream/wiringManifestView.js +141 -0
- package/dist/cloudConfigWireCaps.js +6 -3
- package/dist/compensations.js +1 -1
- package/dist/credentialPlaneCapability.d.ts +22 -0
- package/dist/credentialPlaneCapability.js +75 -0
- package/dist/deviceExecutorManagementCapability.d.ts +1 -0
- package/dist/deviceExecutorManagementCapability.js +3 -1
- package/dist/displayUntrusted.d.ts +8 -4
- package/dist/displayUntrusted.js +769 -96
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +3 -1
- package/dist/engineNoticeCodes.d.ts +26 -0
- package/dist/engineNoticeCodes.js +121 -12
- package/dist/engineRowRef.js +2 -0
- package/dist/errorSupplementRoles.js +1 -3
- package/dist/eventLeg.js +2 -1
- package/dist/fleet/fleetProjection.js +16 -10
- package/dist/gateOutcome.d.ts +20 -0
- package/dist/gateOutcome.js +89 -0
- package/dist/generated/engineAskFaceTables.js +2 -2
- package/dist/generated/engineFactTables.d.ts +6 -2
- package/dist/generated/engineFactTables.js +41 -1
- package/dist/generated/engineNoticeTables.js +18 -0
- package/dist/generated/settingsSchemaDefaultModel.d.ts +1 -1
- package/dist/generated/settingsSchemaDefaultModel.js +2 -2
- package/dist/generated/settingsSchemaFns.d.ts +15 -0
- package/dist/generated/settingsSchemaFns.js +25 -2
- package/dist/generated/settingsSchemaHooksClassifier.js +109 -29
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +213 -93
- package/dist/generated/settingsSchemaMcpServerName.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpServerName.js +8 -0
- package/dist/generated/settingsSchemaOwnKeyRead.d.ts +1 -0
- package/dist/generated/settingsSchemaOwnKeyRead.js +172 -0
- package/dist/generated/settingsSchemaPlainJsonObject.d.ts +1 -0
- package/dist/generated/settingsSchemaPlainJsonObject.js +28 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.js +10 -7
- package/dist/generated/settingsSchemaTierWords.d.ts +1 -0
- package/dist/generated/settingsSchemaTierWords.js +7 -0
- package/dist/generated/settingsSchemaTypes.d.ts +3 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/decisionConflict.js +11 -11
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +4 -2
- package/dist/hitl/editedRuleTextPrecheck.d.ts +1 -0
- package/dist/hitl/editedRuleTextPrecheck.js +26 -1
- package/dist/hitl/persistedRulesWire.js +1 -0
- package/dist/hitl/planReviewWire.d.ts +2 -1
- package/dist/hitl/planReviewWire.js +8 -12
- package/dist/hitl/sessionPolicyDeliverable.d.ts +0 -1
- package/dist/hitl/sessionPolicyDeliverable.js +0 -5
- package/dist/hitl/sessionPolicyWire.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +18 -6
- package/dist/hitl/toolApprovalWire.js +9 -4
- package/dist/i18n/messages.en.d.ts +43 -0
- package/dist/i18n/messages.en.js +44 -1
- package/dist/i18n/messages.zh.js +46 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.js +7 -1
- package/dist/inheritEnvWire.d.ts +1 -0
- package/dist/inheritEnvWire.js +8 -5
- package/dist/interactiveHalt.d.ts +3 -1
- package/dist/interactiveHalt.js +2 -0
- package/dist/interactiveInterrupt.d.ts +2 -0
- package/dist/interactiveInterrupt.js +15 -0
- package/dist/mcpEngineLeg.d.ts +3 -0
- package/dist/mcpEngineLeg.js +4 -1
- package/dist/mcpLiveness.d.ts +18 -0
- package/dist/mcpLiveness.js +48 -1
- package/dist/mcpReconnect.d.ts +3 -0
- package/dist/mcpReconnect.js +6 -0
- package/dist/mcpStatusSupersetKeys.js +24 -1
- package/dist/mcpWireCaps.d.ts +2 -3
- package/dist/mcpWireCaps.js +9 -8
- package/dist/memoryEntriesWire.d.ts +35 -1
- package/dist/memoryEntriesWire.js +110 -14
- package/dist/modsFace.d.ts +8 -0
- package/dist/modsFace.js +63 -0
- package/dist/ownKey.d.ts +1 -0
- package/dist/ownKey.js +15 -0
- package/dist/postureKnob.js +1 -1
- package/dist/prepareRefusal.d.ts +0 -1
- package/dist/prepareRefusal.js +0 -3
- package/dist/printToolResultFrame.js +1 -1
- package/dist/promptProfileWireCaps.d.ts +1 -3
- package/dist/promptProfileWireCaps.js +2 -2
- package/dist/request/printNotification.js +1 -1
- package/dist/request/taskRequest.d.ts +22 -1
- package/dist/request/taskRequest.js +126 -10
- package/dist/retryStatus.d.ts +13 -1
- package/dist/retryStatus.js +20 -5
- package/dist/seam.js +1 -1
- package/dist/seatContract.d.ts +22 -6
- package/dist/seatContract.js +45 -6
- package/dist/sessionBackground.d.ts +165 -0
- package/dist/sessionBackground.js +781 -0
- package/dist/sessionBackgroundHandoff.d.ts +54 -0
- package/dist/sessionBackgroundHandoff.js +321 -0
- package/dist/sessionMap.js +4 -1
- package/dist/sessionMemoryErase.js +24 -2
- package/dist/settingsCredentialKeyPaths.js +2 -17
- package/dist/thinkingLatch.d.ts +69 -0
- package/dist/thinkingLatch.js +255 -0
- package/dist/thinkingLatchWords.d.ts +7 -0
- package/dist/thinkingLatchWords.js +4 -0
- package/dist/toolResult.js +2 -24
- package/dist/turnFailurePresentation.js +8 -1
- package/dist/wireFailureShape.d.ts +12 -1
- package/dist/wireFailureShape.js +58 -24
- package/dist/wireRefusalCopy.d.ts +0 -3
- package/dist/wireRefusalCopy.js +0 -17
- package/docs/INTEGRATION-CLIENTS.md +458 -14
- package/package.json +5 -5
- package/dist/argvFlagValue.d.ts +0 -8
- package/dist/argvFlagValue.js +0 -37
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AgentEvent } from '@sema-agent/sdk';
|
|
2
|
+
import type { UiLanguage } from './env/uiLanguage.js';
|
|
3
|
+
import { type BackgroundHandoffVerdict, type InteractiveEngineWire } from './sessionBackground.js';
|
|
4
|
+
export declare const BACKGROUND_HANDOFF_ABORT_REASON = "background";
|
|
5
|
+
export interface BackgroundHandoffRequest {
|
|
6
|
+
readonly wire: InteractiveEngineWire | undefined;
|
|
7
|
+
readonly sessionKey: string;
|
|
8
|
+
readonly onHandedOff: (reason: typeof BACKGROUND_HANDOFF_ABORT_REASON) => void;
|
|
9
|
+
readonly lang?: UiLanguage;
|
|
10
|
+
}
|
|
11
|
+
export type BackgroundHandoffOutcome = {
|
|
12
|
+
readonly kind: 'kept';
|
|
13
|
+
readonly verdict: Exclude<BackgroundHandoffVerdict, {
|
|
14
|
+
verdict: 'eligible';
|
|
15
|
+
}>;
|
|
16
|
+
readonly sentence: string;
|
|
17
|
+
} | {
|
|
18
|
+
readonly kind: 'handed-off';
|
|
19
|
+
readonly run: BackgroundRun;
|
|
20
|
+
readonly hostNotified: boolean;
|
|
21
|
+
readonly sentence: string;
|
|
22
|
+
};
|
|
23
|
+
export interface BackgroundRun {
|
|
24
|
+
readonly taskId: string;
|
|
25
|
+
openFrames(signal?: AbortSignal): AsyncGenerator<AgentEvent>;
|
|
26
|
+
readonly settled: Promise<BackgroundRunSettlement>;
|
|
27
|
+
dispose(): void;
|
|
28
|
+
}
|
|
29
|
+
export type BackgroundRunSettlement = {
|
|
30
|
+
readonly runEnded: true;
|
|
31
|
+
readonly kind: 'completed' | 'failed' | 'cancelled' | 'parked';
|
|
32
|
+
readonly status: string;
|
|
33
|
+
readonly errorCode?: string;
|
|
34
|
+
readonly sentence: string;
|
|
35
|
+
} | {
|
|
36
|
+
readonly runEnded: false;
|
|
37
|
+
readonly kind: 'observation-stopped';
|
|
38
|
+
readonly cause: 'window-exhausted' | 'disposed' | 'engine-ended';
|
|
39
|
+
readonly sentence: string;
|
|
40
|
+
};
|
|
41
|
+
export interface HandedOffRunRow {
|
|
42
|
+
readonly taskId: string;
|
|
43
|
+
readonly sessionKey: string;
|
|
44
|
+
readonly state: 'running' | 'ended' | 'unconfirmed';
|
|
45
|
+
}
|
|
46
|
+
export type HandedOffRunsReading = {
|
|
47
|
+
readonly kind: 'read';
|
|
48
|
+
readonly runs: readonly HandedOffRunRow[];
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: 'unrecognized-wire';
|
|
51
|
+
};
|
|
52
|
+
export declare function handoffInteractiveRun(req: BackgroundHandoffRequest): BackgroundHandoffOutcome;
|
|
53
|
+
export declare function handedOffRunsOf(wire: InteractiveEngineWire): HandedOffRunsReading;
|
|
54
|
+
export declare function forgetHandedOffRun(wire: InteractiveEngineWire, taskId: string): boolean;
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
2
|
+
import { abortableSleep } from './abortableSleep.js';
|
|
3
|
+
import { REATTACH_WINDOW_MS, reattachBackoffMs } from './reattachWindow.js';
|
|
4
|
+
import { terminalEventFromRunRow } from './headlessReconnectWire.js';
|
|
5
|
+
import { RUN_CANCELLED_CODE } from './runCancelContext.js';
|
|
6
|
+
import { readRunTerminal } from './runTerminal.js';
|
|
7
|
+
import { readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
8
|
+
import { backgroundHandoffSentence, judgeHandoff, ownSlotOf, wireStateOf, } from './sessionBackground.js';
|
|
9
|
+
export const BACKGROUND_HANDOFF_ABORT_REASON = 'background';
|
|
10
|
+
const HANDED_OFF_ENDED_CAP = 256;
|
|
11
|
+
const isObj = (v) => (typeof v === 'object' && v !== null) || typeof v === 'function';
|
|
12
|
+
function slot(o, key) {
|
|
13
|
+
try {
|
|
14
|
+
return readOwnDataValue(o, key);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function slotString(o, key) {
|
|
21
|
+
try {
|
|
22
|
+
return readOwnDataNonEmptyString(o, key);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function executionSettlementOf(ev) {
|
|
29
|
+
try {
|
|
30
|
+
const type = slot(ev, 'type');
|
|
31
|
+
if (type === 'failed') {
|
|
32
|
+
const code = slotString(ev, 'errorCode');
|
|
33
|
+
if (code === RUN_CANCELLED_CODE)
|
|
34
|
+
return { runEnded: true, kind: 'cancelled', status: 'failed' };
|
|
35
|
+
return { runEnded: true, kind: 'failed', status: 'failed', ...(code !== undefined ? { errorCode: code } : {}) };
|
|
36
|
+
}
|
|
37
|
+
if (type !== 'done' || slot(ev, 'replay') === true)
|
|
38
|
+
return undefined;
|
|
39
|
+
const read = readRunTerminal(slot(ev, 'result'));
|
|
40
|
+
if (read === null)
|
|
41
|
+
return { runEnded: true, kind: 'completed', status: 'completed' };
|
|
42
|
+
switch (read.kind) {
|
|
43
|
+
case 'completed':
|
|
44
|
+
return { runEnded: true, kind: 'completed', status: 'completed' };
|
|
45
|
+
case 'paused':
|
|
46
|
+
return { runEnded: true, kind: 'parked', status: read.flatStatus ?? 'paused' };
|
|
47
|
+
case 'failed':
|
|
48
|
+
if (read.code === RUN_CANCELLED_CODE)
|
|
49
|
+
return { runEnded: true, kind: 'cancelled', status: 'failed' };
|
|
50
|
+
return { runEnded: true, kind: 'failed', status: 'failed', ...(read.code !== undefined ? { errorCode: read.code } : {}) };
|
|
51
|
+
case 'blocked':
|
|
52
|
+
return { runEnded: true, kind: 'failed', status: 'blocked', ...(read.code !== undefined ? { errorCode: read.code } : {}) };
|
|
53
|
+
case 'unknown':
|
|
54
|
+
return { runEnded: true, kind: 'failed', status: read.word ?? 'unknown', ...(read.code !== undefined ? { errorCode: read.code } : {}) };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function settlementSentence(s, lang) {
|
|
62
|
+
if (!s.runEnded)
|
|
63
|
+
return renderMessage(msg('session.background.settled.observationStopped'), lang);
|
|
64
|
+
switch (s.kind) {
|
|
65
|
+
case 'completed':
|
|
66
|
+
return renderMessage(msg('session.background.settled.completed'), lang);
|
|
67
|
+
case 'cancelled':
|
|
68
|
+
return renderMessage(msg('session.background.settled.cancelled'), lang);
|
|
69
|
+
case 'parked':
|
|
70
|
+
return renderMessage(msg('session.background.settled.parked'), lang);
|
|
71
|
+
case 'failed':
|
|
72
|
+
return renderMessage(msg('session.background.settled.failed', { code: s.errorCode ?? s.status }), lang);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function runRowOf(row) {
|
|
76
|
+
if (!isObj(row))
|
|
77
|
+
return null;
|
|
78
|
+
const status = slotString(row, 'status');
|
|
79
|
+
if (status === undefined)
|
|
80
|
+
return null;
|
|
81
|
+
const result = slot(row, 'result');
|
|
82
|
+
const errorCode = slotString(row, 'errorCode');
|
|
83
|
+
const error = slotString(row, 'error');
|
|
84
|
+
return {
|
|
85
|
+
status,
|
|
86
|
+
...(result !== undefined ? { result } : {}),
|
|
87
|
+
...(errorCode !== undefined ? { errorCode } : {}),
|
|
88
|
+
...(error !== undefined ? { error } : {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function readRunRow(state, taskId, sessionId, signal) {
|
|
92
|
+
try {
|
|
93
|
+
const row = await state.get(taskId, signal !== undefined ? { session: sessionId, signal } : { session: sessionId });
|
|
94
|
+
return runRowOf(row);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function* framesEndedWith(error) {
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
function trimHandedOff(state) {
|
|
104
|
+
let ended = 0;
|
|
105
|
+
for (const e of state.handedOff.values())
|
|
106
|
+
if (e.state === 'ended')
|
|
107
|
+
ended++;
|
|
108
|
+
if (ended <= HANDED_OFF_ENDED_CAP)
|
|
109
|
+
return;
|
|
110
|
+
for (const [taskId, e] of [...state.handedOff]) {
|
|
111
|
+
if (ended <= HANDED_OFF_ENDED_CAP)
|
|
112
|
+
break;
|
|
113
|
+
if (e.state !== 'ended')
|
|
114
|
+
continue;
|
|
115
|
+
state.handedOff.delete(taskId);
|
|
116
|
+
ended--;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function ledgerSeqOf(ev) {
|
|
120
|
+
const id = slotString(ev, 'id');
|
|
121
|
+
return id !== undefined && /^\d+$/.test(id) ? Number(id) : undefined;
|
|
122
|
+
}
|
|
123
|
+
async function pump(state, taskId, sessionId, signal, finish) {
|
|
124
|
+
let deadline = Date.now() + REATTACH_WINDOW_MS;
|
|
125
|
+
let attempt = 0;
|
|
126
|
+
let farthest = -1;
|
|
127
|
+
for (;;) {
|
|
128
|
+
if (signal.aborted)
|
|
129
|
+
return;
|
|
130
|
+
let progressed = false;
|
|
131
|
+
try {
|
|
132
|
+
const frames = state.events(taskId, { session: sessionId, signal });
|
|
133
|
+
for await (const ev of frames) {
|
|
134
|
+
if (signal.aborted)
|
|
135
|
+
return;
|
|
136
|
+
const seq = ledgerSeqOf(ev);
|
|
137
|
+
if (seq !== undefined && seq > farthest) {
|
|
138
|
+
farthest = seq;
|
|
139
|
+
progressed = true;
|
|
140
|
+
}
|
|
141
|
+
const s = executionSettlementOf(ev);
|
|
142
|
+
if (s !== undefined) {
|
|
143
|
+
finish(s);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
}
|
|
150
|
+
if (signal.aborted)
|
|
151
|
+
return;
|
|
152
|
+
const row = await readRunRow(state, taskId, sessionId, signal);
|
|
153
|
+
if (signal.aborted)
|
|
154
|
+
return;
|
|
155
|
+
const synthesized = terminalEventFromRunRow(row);
|
|
156
|
+
const s = synthesized === null ? undefined : executionSettlementOf(synthesized);
|
|
157
|
+
if (s !== undefined) {
|
|
158
|
+
finish(s);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (progressed) {
|
|
162
|
+
deadline = Date.now() + REATTACH_WINDOW_MS;
|
|
163
|
+
attempt = 0;
|
|
164
|
+
}
|
|
165
|
+
if (Date.now() >= deadline) {
|
|
166
|
+
finish({ runEnded: false, kind: 'observation-stopped', cause: 'window-exhausted' });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
attempt++;
|
|
170
|
+
await abortableSleep(reattachBackoffMs(attempt), signal);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function startBackground(state, taskId, sessionKey, sessionId, lang) {
|
|
174
|
+
const controller = new AbortController();
|
|
175
|
+
let resolveSettled = () => { };
|
|
176
|
+
const settled = new Promise((resolve) => {
|
|
177
|
+
resolveSettled = resolve;
|
|
178
|
+
});
|
|
179
|
+
let done = false;
|
|
180
|
+
let reconciling = false;
|
|
181
|
+
const finish = (s) => {
|
|
182
|
+
if (done)
|
|
183
|
+
return;
|
|
184
|
+
done = true;
|
|
185
|
+
entry.state = s.runEnded ? 'ended' : 'unconfirmed';
|
|
186
|
+
controller.abort();
|
|
187
|
+
resolveSettled(Object.freeze({ ...s, sentence: settlementSentence(s, lang) }));
|
|
188
|
+
if (s.runEnded)
|
|
189
|
+
trimHandedOff(state);
|
|
190
|
+
};
|
|
191
|
+
const entry = {
|
|
192
|
+
taskId,
|
|
193
|
+
sessionKey,
|
|
194
|
+
state: 'running',
|
|
195
|
+
stop: (cause) => finish({ runEnded: false, kind: 'observation-stopped', cause }),
|
|
196
|
+
reconcile: () => {
|
|
197
|
+
if (entry.state !== 'unconfirmed' || reconciling || state.retired)
|
|
198
|
+
return;
|
|
199
|
+
reconciling = true;
|
|
200
|
+
void readRunRow(state, taskId, sessionId, undefined)
|
|
201
|
+
.then((row) => {
|
|
202
|
+
const synthesized = terminalEventFromRunRow(row);
|
|
203
|
+
const s = synthesized === null ? undefined : executionSettlementOf(synthesized);
|
|
204
|
+
if (s !== undefined && s.runEnded && entry.state === 'unconfirmed') {
|
|
205
|
+
entry.state = 'ended';
|
|
206
|
+
trimHandedOff(state);
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
.finally(() => {
|
|
210
|
+
reconciling = false;
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
state.handedOff.set(taskId, entry);
|
|
215
|
+
void pump(state, taskId, sessionId, controller.signal, finish).catch(() => finish({ runEnded: false, kind: 'observation-stopped', cause: 'window-exhausted' }));
|
|
216
|
+
const run = Object.freeze({
|
|
217
|
+
taskId,
|
|
218
|
+
openFrames(signal) {
|
|
219
|
+
try {
|
|
220
|
+
return state.events(taskId, signal !== undefined ? { session: sessionId, signal } : { session: sessionId });
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
return framesEndedWith(e);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
settled,
|
|
227
|
+
dispose() {
|
|
228
|
+
finish({ runEnded: false, kind: 'observation-stopped', cause: 'disposed' });
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
return run;
|
|
232
|
+
}
|
|
233
|
+
function snapshotHandoffRequest(req) {
|
|
234
|
+
if (!isObj(req))
|
|
235
|
+
return { readable: false, wire: undefined, sessionKey: undefined, onHandedOff: undefined, lang: undefined };
|
|
236
|
+
const wireSlot = ownSlotOf(req, 'wire');
|
|
237
|
+
const sessionKey = slotString(req, 'sessionKey');
|
|
238
|
+
const onHandedOff = slot(req, 'onHandedOff');
|
|
239
|
+
const lang = slot(req, 'lang');
|
|
240
|
+
return {
|
|
241
|
+
readable: sessionKey !== undefined && typeof onHandedOff === 'function',
|
|
242
|
+
wire: wireSlot.state === 'unreadable' ? {} : wireSlot.state === 'data' ? wireSlot.value : undefined,
|
|
243
|
+
sessionKey,
|
|
244
|
+
onHandedOff: typeof onHandedOff === 'function' ? onHandedOff : undefined,
|
|
245
|
+
lang: typeof lang === 'string' ? lang : undefined,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function keptOf(verdict, lang) {
|
|
249
|
+
const v = verdict.verdict === 'eligible' ? Object.freeze({ verdict: 'unknown', reason: 'unreadable-input' }) : verdict;
|
|
250
|
+
const sentence = backgroundHandoffSentence(v, lang) ?? renderMessage(msg('session.background.unknown'), lang);
|
|
251
|
+
return Object.freeze({ kind: 'kept', verdict: v, sentence });
|
|
252
|
+
}
|
|
253
|
+
export function handoffInteractiveRun(req) {
|
|
254
|
+
let snap;
|
|
255
|
+
try {
|
|
256
|
+
snap = snapshotHandoffRequest(req);
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return keptOf(Object.freeze({ verdict: 'unknown', reason: 'unreadable-input' }), undefined);
|
|
260
|
+
}
|
|
261
|
+
const lang = snap.lang;
|
|
262
|
+
if (!snap.readable || snap.sessionKey === undefined || snap.onHandedOff === undefined) {
|
|
263
|
+
return keptOf(Object.freeze({ verdict: 'unknown', reason: 'unreadable-input' }), lang);
|
|
264
|
+
}
|
|
265
|
+
const judged = judgeHandoff({ wire: snap.wire, sessionKey: snap.sessionKey });
|
|
266
|
+
const { verdict, rec, state } = judged;
|
|
267
|
+
if (verdict.verdict !== 'eligible' || rec === undefined || state === undefined || rec.sessionId === undefined)
|
|
268
|
+
return keptOf(verdict, lang);
|
|
269
|
+
const taskId = verdict.taskId;
|
|
270
|
+
const sessionId = rec.sessionId;
|
|
271
|
+
rec.phase = 'handing-off';
|
|
272
|
+
try {
|
|
273
|
+
rec.tear(BACKGROUND_HANDOFF_ABORT_REASON);
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
}
|
|
277
|
+
rec.phase = 'handed-off';
|
|
278
|
+
const run = startBackground(state, taskId, snap.sessionKey, sessionId, lang);
|
|
279
|
+
let hostNotified = true;
|
|
280
|
+
try {
|
|
281
|
+
snap.onHandedOff(BACKGROUND_HANDOFF_ABORT_REASON);
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
hostNotified = false;
|
|
285
|
+
}
|
|
286
|
+
const sentence = renderMessage(msg(hostNotified ? 'session.background.handedOff' : 'session.background.hostNotNotified'), lang);
|
|
287
|
+
return Object.freeze({ kind: 'handed-off', run, hostNotified, sentence });
|
|
288
|
+
}
|
|
289
|
+
export function handedOffRunsOf(wire) {
|
|
290
|
+
try {
|
|
291
|
+
const state = wireStateOf(wire);
|
|
292
|
+
if (state === undefined)
|
|
293
|
+
return Object.freeze({ kind: 'unrecognized-wire' });
|
|
294
|
+
const runs = [];
|
|
295
|
+
for (const e of state.handedOff.values()) {
|
|
296
|
+
if (e.state === 'unconfirmed')
|
|
297
|
+
e.reconcile();
|
|
298
|
+
runs.push(Object.freeze({ taskId: e.taskId, sessionKey: e.sessionKey, state: e.state }));
|
|
299
|
+
}
|
|
300
|
+
return Object.freeze({ kind: 'read', runs: Object.freeze(runs) });
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
return Object.freeze({ kind: 'unrecognized-wire' });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
export function forgetHandedOffRun(wire, taskId) {
|
|
307
|
+
try {
|
|
308
|
+
const state = wireStateOf(wire);
|
|
309
|
+
if (state === undefined || typeof taskId !== 'string')
|
|
310
|
+
return false;
|
|
311
|
+
const entry = state.handedOff.get(taskId);
|
|
312
|
+
if (entry === undefined)
|
|
313
|
+
return false;
|
|
314
|
+
entry.stop('disposed');
|
|
315
|
+
state.handedOff.delete(taskId);
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
}
|
package/dist/sessionMap.js
CHANGED
|
@@ -2,7 +2,10 @@ export function engineNamespaceKeyFor(baseUrl) {
|
|
|
2
2
|
if (!baseUrl)
|
|
3
3
|
return 'local';
|
|
4
4
|
try {
|
|
5
|
-
|
|
5
|
+
const u = new URL(baseUrl);
|
|
6
|
+
if (!/^(?:https?|wss?|ftp):$/.test(u.protocol))
|
|
7
|
+
return baseUrl.toLowerCase();
|
|
8
|
+
return u.origin.toLowerCase() + u.pathname.replace(/\/+$/, '');
|
|
6
9
|
}
|
|
7
10
|
catch {
|
|
8
11
|
return baseUrl.toLowerCase();
|
|
@@ -245,7 +245,29 @@ const UNCONFIRMED_TEXT = {
|
|
|
245
245
|
unreadable: 'Not confirmed: the result of this erase could not be read.',
|
|
246
246
|
};
|
|
247
247
|
const ERASED_TEXT = 'Erased: every memory entry recorded as coming from this session was erased or was already gone.';
|
|
248
|
-
const
|
|
248
|
+
const PARTIAL_ENTRIES_TEXT = 'Partly erased: some memory entries from this session were not erased yet.';
|
|
249
|
+
const PARTIAL_UNKNOWN_TEXT = 'Partly erased: the engine reports this erase as not complete, and its receipt does not show whether memory entries or other stored records of them remain.';
|
|
250
|
+
function partialCarriersText(kinds) {
|
|
251
|
+
return kinds === 1
|
|
252
|
+
? 'Partly erased: every memory entry recorded as coming from this session was erased or was already gone, but 1 kind of stored record that refers to them was not confirmed removed, and trying again may not remove it.'
|
|
253
|
+
: `Partly erased: every memory entry recorded as coming from this session was erased or was already gone, but ${kinds} kinds of stored records that refer to them were not confirmed removed, and trying again may not remove them.`;
|
|
254
|
+
}
|
|
255
|
+
function partialTextOf(cause) {
|
|
256
|
+
if (cause === null)
|
|
257
|
+
return PARTIAL_UNKNOWN_TEXT;
|
|
258
|
+
switch (cause.kind) {
|
|
259
|
+
case 'entries_pending':
|
|
260
|
+
return PARTIAL_ENTRIES_TEXT;
|
|
261
|
+
case 'carriers_residual':
|
|
262
|
+
return partialCarriersText(cause.carriers.length);
|
|
263
|
+
case 'unknown':
|
|
264
|
+
return PARTIAL_UNKNOWN_TEXT;
|
|
265
|
+
default: {
|
|
266
|
+
const unreachable = cause;
|
|
267
|
+
return unreachable;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
249
271
|
const RETRY_TEXT = {
|
|
250
272
|
not_needed: 'Nothing more to do.',
|
|
251
273
|
same_request_id: 'It is safe to try again with the same request id.',
|
|
@@ -414,7 +436,7 @@ export function sessionMemoryEraseOutcome(answer) {
|
|
|
414
436
|
return { kind: 'erased', receipt: reading, text: ERASED_TEXT, retry: 'not_needed', retryText: RETRY_TEXT.not_needed };
|
|
415
437
|
}
|
|
416
438
|
const retry = memoryEraseReplayPosture(reading) === 'idempotent' ? 'same_request_id' : 'human_decision';
|
|
417
|
-
return { kind: 'partial', receipt: reading, text:
|
|
439
|
+
return { kind: 'partial', receipt: reading, text: partialTextOf(reading.partialCause), retry, retryText: RETRY_TEXT[retry] };
|
|
418
440
|
}
|
|
419
441
|
if (status < 400)
|
|
420
442
|
return unconfirmedBy('unclassified', signed, { status });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { looksLikeKnownSecret, percentBoundaryReadingOf
|
|
1
|
+
import { configuredValueCarriesCredential, looksLikeKnownSecret, percentBoundaryReadingOf } from './displayUntrusted.js';
|
|
2
2
|
const CREDENTIAL_WORDS = new Set([
|
|
3
3
|
'key', 'keys', 'apikey', 'token', 'tokens', 'secret', 'secrets', 'password', 'passwd', 'pass', 'pwd', 'pin', 'otp',
|
|
4
4
|
'auth', 'authorization', 'credential', 'credentials', 'cookie', 'cookies', 'session', 'private', 'cert', 'signature', 'salt',
|
|
@@ -74,27 +74,12 @@ function formEncodedCarriesCredential(value) {
|
|
|
74
74
|
layer = next;
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
function urlCarriesCredential(value) {
|
|
78
|
-
const text = value.trim();
|
|
79
|
-
if (!text.includes('://'))
|
|
80
|
-
return false;
|
|
81
|
-
let url;
|
|
82
|
-
try {
|
|
83
|
-
url = new URL(text);
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
if (url.username !== '' || url.password !== '')
|
|
89
|
-
return true;
|
|
90
|
-
return url.search.length > 1 && queryCarriesCredential(url.search.slice(1));
|
|
91
|
-
}
|
|
92
77
|
function stringCarriesCredential(value) {
|
|
93
78
|
if (looksLikeKnownSecret(value) || formEncodedCarriesCredential(value))
|
|
94
79
|
return true;
|
|
95
80
|
let layer = value;
|
|
96
81
|
for (let depth = 0;; depth++) {
|
|
97
|
-
if (
|
|
82
|
+
if (configuredValueCarriesCredential(layer))
|
|
98
83
|
return true;
|
|
99
84
|
if (depth === FORM_READING_MAX_LAYERS)
|
|
100
85
|
return false;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { UiLanguage } from './env/uiLanguage.js';
|
|
2
|
+
import type { EffortLevelsReading } from './liveModelCatalog.js';
|
|
3
|
+
import type { ThinkingTurnProjection } from './request/taskRequest.js';
|
|
4
|
+
import { type LocalSessionRecord, type OkAck, type SeatCapabilityReading } from './seatContract.js';
|
|
5
|
+
import { type ThinkingLatchEvent, type ThinkingLatchRowWord, type ThinkingLatchState } from './thinkingLatchWords.js';
|
|
6
|
+
export type { ThinkingLatchEvent, ThinkingLatchRowWord, ThinkingLatchState } from './thinkingLatchWords.js';
|
|
7
|
+
export interface ThinkingLatchStorePort {
|
|
8
|
+
read(): boolean | undefined;
|
|
9
|
+
write(stored: boolean | undefined): void;
|
|
10
|
+
}
|
|
11
|
+
export interface ThinkingLatchReading {
|
|
12
|
+
readonly state: ThinkingLatchState;
|
|
13
|
+
readonly why?: 'no_port' | 'never_set' | 'unreadable' | 'malformed';
|
|
14
|
+
}
|
|
15
|
+
export type ThinkingLatchWriteOutcome = {
|
|
16
|
+
readonly kind: 'saved';
|
|
17
|
+
readonly previous: ThinkingLatchReading;
|
|
18
|
+
readonly state: ThinkingLatchState;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: 'unchanged';
|
|
21
|
+
readonly state: ThinkingLatchState;
|
|
22
|
+
} | {
|
|
23
|
+
readonly kind: 'not_saved';
|
|
24
|
+
readonly why: 'no_port' | 'bad_event';
|
|
25
|
+
readonly previous: ThinkingLatchReading;
|
|
26
|
+
} | {
|
|
27
|
+
readonly kind: 'not_saved';
|
|
28
|
+
readonly why: 'write_failed';
|
|
29
|
+
readonly attempted: ThinkingLatchState;
|
|
30
|
+
readonly now: ThinkingLatchReading;
|
|
31
|
+
};
|
|
32
|
+
export interface ThinkingLatchView {
|
|
33
|
+
readonly state: ThinkingLatchState;
|
|
34
|
+
readonly why?: ThinkingLatchReading['why'];
|
|
35
|
+
readonly conflict?: 'seat_cannot_carry' | 'model_cannot_think';
|
|
36
|
+
}
|
|
37
|
+
export type ThinkingLatchCarrier = {
|
|
38
|
+
readonly kind: 'engine';
|
|
39
|
+
} | {
|
|
40
|
+
readonly kind: 'seat';
|
|
41
|
+
readonly capability: SeatCapabilityReading;
|
|
42
|
+
};
|
|
43
|
+
export type ThinkingLatchSentenceSubject = {
|
|
44
|
+
readonly kind: 'state';
|
|
45
|
+
readonly state: ThinkingLatchState;
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: 'turn';
|
|
48
|
+
readonly projection: ThinkingTurnProjection;
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: 'view';
|
|
51
|
+
readonly view: ThinkingLatchView;
|
|
52
|
+
readonly carrier?: ThinkingLatchCarrier;
|
|
53
|
+
readonly model?: string;
|
|
54
|
+
} | {
|
|
55
|
+
readonly kind: 'write';
|
|
56
|
+
readonly outcome: ThinkingLatchWriteOutcome;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: 'seat_ack';
|
|
59
|
+
readonly ack: OkAck;
|
|
60
|
+
};
|
|
61
|
+
export declare function readThinkingLatch(port: ThinkingLatchStorePort | undefined): ThinkingLatchReading;
|
|
62
|
+
export declare function writeThinkingLatch(port: ThinkingLatchStorePort | undefined, event: ThinkingLatchEvent): ThinkingLatchWriteOutcome;
|
|
63
|
+
export declare function thinkingLatchView(reading: ThinkingLatchReading, ctx?: {
|
|
64
|
+
readonly carrier?: ThinkingLatchCarrier;
|
|
65
|
+
readonly model?: EffortLevelsReading;
|
|
66
|
+
}): ThinkingLatchView;
|
|
67
|
+
export declare function thinkingLatchSentence(subject: ThinkingLatchSentenceSubject, lang?: UiLanguage): string | undefined;
|
|
68
|
+
export declare function thinkingLatchRowWordOf(reading: ThinkingLatchReading): ThinkingLatchRowWord | undefined;
|
|
69
|
+
export declare function readSeatThinkingLatch(record: LocalSessionRecord | undefined, capability: SeatCapabilityReading): ThinkingLatchReading;
|