@sema-agent/client-core 0.104.0 → 0.105.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 +99 -0
- package/README.md +13 -5
- package/dist/adapt/arms.js +14 -6
- package/dist/adapter/activeRunSelfHeal.d.ts +1 -0
- package/dist/adapter/activeRunSelfHeal.js +10 -5
- package/dist/adapter/downstream/eventToSdkMessage.js +4 -4
- package/dist/adapter/downstream/wiringManifestView.d.ts +6 -0
- package/dist/adapter/downstream/wiringManifestView.js +25 -0
- package/dist/adapter/runStream.js +5 -1
- package/dist/cloudConfigWireCaps.js +3 -0
- package/dist/compensations.js +6 -6
- package/dist/coreValuePorts.d.ts +3 -1
- package/dist/coreValuePorts.js +4 -0
- package/dist/displayUntrusted.d.ts +4 -2
- package/dist/displayUntrusted.js +45 -22
- package/dist/engineGenerationPort.d.ts +11 -2
- package/dist/engineGenerationPort.js +63 -9
- package/dist/engineHealthFacts.d.ts +5 -0
- package/dist/engineHealthFacts.js +11 -0
- package/dist/eventLeg.d.ts +1 -1
- package/dist/eventLeg.js +23 -3
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +1 -0
- package/dist/generated/sdkFactTables.d.ts +2 -0
- package/dist/generated/sdkFactTables.js +9 -0
- package/dist/headlessReconnectWire.js +31 -4
- package/dist/hitl/askGateWire.js +26 -2
- package/dist/hitl/frameRouter.d.ts +4 -0
- package/dist/hitl/frameRouter.js +14 -0
- package/dist/hitl/gateIdentity.d.ts +1 -0
- package/dist/hitl/gateIdentity.js +3 -0
- package/dist/hitl/livePendingAsk.d.ts +2 -1
- package/dist/hitl/livePendingAsk.js +7 -1
- package/dist/hitl/planReviewCard.d.ts +21 -0
- package/dist/hitl/planReviewCard.js +229 -0
- package/dist/hitl/planReviewWire.d.ts +38 -13
- package/dist/hitl/planReviewWire.js +355 -133
- package/dist/hitl/toolApprovalWire.d.ts +2 -2
- package/dist/hitl/toolApprovalWire.js +53 -32
- package/dist/hostSettingsSource.d.ts +1 -1
- package/dist/hostSettingsSource.js +8 -4
- package/dist/hostTurnSettings.d.ts +1 -1
- package/dist/hostTurnSettings.js +29 -10
- package/dist/i18n/messages.en.d.ts +50 -0
- package/dist/i18n/messages.en.js +50 -0
- package/dist/i18n/messages.zh.js +51 -0
- package/dist/index.d.ts +15 -3
- package/dist/index.js +9 -1
- package/dist/mcpTransportKindsCapability.d.ts +18 -0
- package/dist/mcpTransportKindsCapability.js +75 -0
- package/dist/mcpWireCaps.d.ts +4 -1
- package/dist/mcpWireCaps.js +24 -13
- package/dist/notifications.d.ts +9 -0
- package/dist/notifications.js +11 -2
- package/dist/ownKey.d.ts +4 -0
- package/dist/ownKey.js +8 -0
- package/dist/permissionModeWriteCapability.d.ts +13 -0
- package/dist/permissionModeWriteCapability.js +35 -0
- package/dist/permissionsAllowGrantCapability.d.ts +3 -0
- package/dist/permissionsAllowGrantCapability.js +26 -3
- package/dist/permissionsDeclaration.d.ts +23 -1
- package/dist/permissionsDeclaration.js +60 -30
- package/dist/planReviewCardFacts.d.ts +116 -0
- package/dist/planReviewCardFacts.js +469 -0
- package/dist/reattachWindow.d.ts +8 -1
- package/dist/reattachWindow.js +44 -12
- package/dist/runFollow.d.ts +30 -0
- package/dist/runFollow.js +117 -0
- package/dist/runLedgerSnapshot.d.ts +20 -0
- package/dist/runLedgerSnapshot.js +272 -0
- package/dist/runPermissionModeSwitch.d.ts +57 -0
- package/dist/runPermissionModeSwitch.js +135 -0
- package/dist/runReattachPolicy.d.ts +13 -5
- package/dist/runReattachPolicy.js +58 -23
- package/dist/seam.d.ts +3 -0
- package/dist/seam.js +1 -1
- package/dist/seatContract.js +1 -0
- package/dist/sessionMemoryErase.d.ts +1 -1
- package/dist/sessionMemoryErase.js +5 -0
- package/dist/sessionMemoryStatus.d.ts +27 -1
- package/dist/sessionMemoryStatus.js +117 -0
- package/dist/sseIdleTriage.d.ts +3 -1
- package/dist/sseIdleTriage.js +19 -4
- package/dist/steering.d.ts +1 -0
- package/dist/steering.js +34 -26
- package/dist/subagent/engineSubagentTail.js +2 -0
- package/dist/subagentContentStore.d.ts +3 -0
- package/dist/subagentContentStore.js +10 -1
- package/dist/turnFailurePresentation.d.ts +5 -2
- package/dist/turnFailurePresentation.js +12 -4
- package/docs/INTEGRATION-CLIENTS.md +587 -10
- package/package.json +2 -2
|
@@ -1,46 +1,81 @@
|
|
|
1
1
|
import { STREAM_DRAINING_RECONNECT_MAX, drainingRetryDelayMs, isPreStreamDrainingReject } from './wireErrorTriage.js';
|
|
2
2
|
import { drainingLegStep } from './streamDrainingLegs.js';
|
|
3
|
+
import { mintRunNotFollowed } from './runFollow.js';
|
|
3
4
|
export const REATTACH_MAX_TRIES = 5;
|
|
4
5
|
const DRAINING_TOTAL_MAX = REATTACH_MAX_TRIES * STREAM_DRAINING_RECONNECT_MAX;
|
|
5
6
|
export const REATTACH_BUDGET_FRESH = Object.freeze({ tries: 0, drainingStreak: 0, drainingTotal: 0 });
|
|
7
|
+
export const REATTACH_BUDGET_NONE = Object.freeze({ tries: REATTACH_MAX_TRIES, drainingStreak: 0, drainingTotal: DRAINING_TOTAL_MAX });
|
|
6
8
|
const isCount = (v) => typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
|
|
7
|
-
const giveUp = (
|
|
9
|
+
const giveUp = (notFollowed, budget) => Object.freeze({ action: 'give_up', budget, notFollowed });
|
|
8
10
|
const reattach = (afterMs, tries, drainingStreak, drainingTotal) => Object.freeze({ action: 'reattach', afterMs, budget: Object.freeze({ tries, drainingStreak, drainingTotal }) });
|
|
9
11
|
export function runReattachPolicy(budget, event) {
|
|
12
|
+
let handle;
|
|
10
13
|
try {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const eventOk = typeof event === 'object' && event !== null;
|
|
15
|
+
const runId = eventOk ? event.runId : undefined;
|
|
16
|
+
handle = typeof runId === 'string' && runId !== '' ? runId : undefined;
|
|
17
|
+
const budgetOk = typeof budget === 'object' && budget !== null && isCount(budget.tries) && isCount(budget.drainingStreak) && isCount(budget.drainingTotal);
|
|
18
|
+
const keep = budgetOk ? budget : REATTACH_BUDGET_FRESH;
|
|
19
|
+
if (!eventOk)
|
|
20
|
+
return giveUp(mintRunNotFollowed('bad_input'), keep);
|
|
21
|
+
const bad = () => giveUp(mintRunNotFollowed('bad_input', handle), keep);
|
|
22
|
+
if (!budgetOk)
|
|
23
|
+
return bad();
|
|
24
|
+
const cause = event.cause;
|
|
25
|
+
if (cause !== 'connection_lost' && cause !== 'stream_cap' && cause !== 'stream_draining')
|
|
26
|
+
return bad();
|
|
27
|
+
let draining;
|
|
28
|
+
if (cause === 'stream_draining') {
|
|
29
|
+
const ladder = event.ladder;
|
|
30
|
+
const frame = event.frame;
|
|
31
|
+
if ((ladder === undefined) === (frame === undefined))
|
|
32
|
+
return bad();
|
|
33
|
+
if (ladder !== undefined) {
|
|
34
|
+
if (ladder !== 'exhausted')
|
|
35
|
+
return bad();
|
|
36
|
+
draining = { ladder: true };
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
const madeProgress = event.madeProgress;
|
|
40
|
+
const streak = madeProgress === true ? 0 : budget.drainingStreak;
|
|
41
|
+
const st = drainingLegStep(streak, frame);
|
|
42
|
+
if ('giveUp' in st.decision && st.decision.giveUp === 'not_draining_end')
|
|
43
|
+
return bad();
|
|
44
|
+
draining = { step: st };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (runId === undefined)
|
|
48
|
+
return giveUp(mintRunNotFollowed('no_run_id'), keep);
|
|
49
|
+
if (handle === undefined)
|
|
50
|
+
return bad();
|
|
51
|
+
const exhausted = (brk) => giveUp(mintRunNotFollowed('reattach_exhausted', handle, brk), budget);
|
|
17
52
|
const { tries, drainingStreak, drainingTotal } = budget;
|
|
18
|
-
if (
|
|
53
|
+
if (cause === 'connection_lost') {
|
|
19
54
|
if (tries >= REATTACH_MAX_TRIES)
|
|
20
|
-
return
|
|
55
|
+
return exhausted(cause);
|
|
56
|
+
const error = event.error;
|
|
21
57
|
const next = tries + 1;
|
|
22
|
-
const afterMs = isPreStreamDrainingReject(
|
|
58
|
+
const afterMs = isPreStreamDrainingReject(error) ? drainingRetryDelayMs(error, next - 1) : 1000 * next;
|
|
23
59
|
return reattach(afterMs, next, 0, drainingTotal);
|
|
24
60
|
}
|
|
25
|
-
if (
|
|
61
|
+
if (cause === 'stream_cap') {
|
|
26
62
|
if (tries >= REATTACH_MAX_TRIES)
|
|
27
|
-
return
|
|
63
|
+
return exhausted(cause);
|
|
28
64
|
return reattach(0, tries + 1, 0, drainingTotal);
|
|
29
65
|
}
|
|
30
|
-
if (
|
|
31
|
-
const streak = event.madeProgress === true ? 0 : drainingStreak;
|
|
32
|
-
const { decision, streak: nextStreak } = drainingLegStep(streak, event.frame);
|
|
33
|
-
if ('reconnectAfterMs' in decision && drainingTotal < DRAINING_TOTAL_MAX)
|
|
34
|
-
return reattach(decision.reconnectAfterMs, tries, nextStreak, drainingTotal + 1);
|
|
35
|
-
if ('giveUp' in decision && decision.giveUp === 'not_draining_end')
|
|
36
|
-
return giveUp('bad_input', budget);
|
|
66
|
+
if (draining === undefined || 'ladder' in draining) {
|
|
37
67
|
if (tries >= REATTACH_MAX_TRIES)
|
|
38
|
-
return
|
|
39
|
-
return reattach(0, tries + 1,
|
|
68
|
+
return exhausted(cause);
|
|
69
|
+
return reattach(0, tries + 1, drainingStreak, drainingTotal);
|
|
40
70
|
}
|
|
41
|
-
|
|
71
|
+
const { decision, streak: nextStreak } = draining.step;
|
|
72
|
+
if ('reconnectAfterMs' in decision && drainingTotal < DRAINING_TOTAL_MAX)
|
|
73
|
+
return reattach(decision.reconnectAfterMs, tries, nextStreak, drainingTotal + 1);
|
|
74
|
+
if (tries >= REATTACH_MAX_TRIES)
|
|
75
|
+
return exhausted(cause);
|
|
76
|
+
return reattach(0, tries + 1, nextStreak, drainingTotal);
|
|
42
77
|
}
|
|
43
78
|
catch {
|
|
44
|
-
return giveUp('bad_input', REATTACH_BUDGET_FRESH);
|
|
79
|
+
return giveUp(mintRunNotFollowed('bad_input', handle), REATTACH_BUDGET_FRESH);
|
|
45
80
|
}
|
|
46
81
|
}
|
package/dist/seam.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { WiringManifestAutoMode, WiringManifestModelGate, WiringManifestMcp
|
|
|
5
5
|
import type { ToolRosterView, ToolRosterDeltaView, WiringManifestHandsView } from './toolRoster.js';
|
|
6
6
|
import type { WiringManifestFleetView } from './adapter/downstream/wiringManifestView.js';
|
|
7
7
|
import type { SuspendedReopenReading } from './hitl/suspendedReopen.js';
|
|
8
|
+
import type { PlanReviewCardFacts } from './planReviewCardFacts.js';
|
|
8
9
|
import type { ToolKillCause } from './toolResult.js';
|
|
9
10
|
import type { HumanInputAttachmentView } from './ownKey.js';
|
|
10
11
|
import type { TaskNotificationFields } from './notifications.js';
|
|
@@ -117,6 +118,7 @@ export type ChromeEvent = {
|
|
|
117
118
|
summary: string;
|
|
118
119
|
message: string;
|
|
119
120
|
notification: Readonly<TaskNotificationFields>;
|
|
121
|
+
diagnostics?: string;
|
|
120
122
|
} | {
|
|
121
123
|
kind: 'task_ledger_sync';
|
|
122
124
|
laneProof: LaneProof;
|
|
@@ -159,6 +161,7 @@ export type ChromeEvent = {
|
|
|
159
161
|
kind: 'plan_review_park';
|
|
160
162
|
laneProof: LaneProof;
|
|
161
163
|
result: unknown;
|
|
164
|
+
planReview?: PlanReviewCardFacts;
|
|
162
165
|
} | ({
|
|
163
166
|
kind: 'run_cost_reconciled';
|
|
164
167
|
laneProof: LaneProof;
|
package/dist/seam.js
CHANGED
|
@@ -32,7 +32,7 @@ const CHROME_ARM_TABLE = {
|
|
|
32
32
|
'🔴 `usageMissing` 在场时同行 usage 是**下界**,渲「≥」不渲已知账;' +
|
|
33
33
|
'🔴 终帧的 `_sema_nested_usage_by_task` 是同一份账的**收口快照**,两者**不相加**(本臂是增量、那是合计)',
|
|
34
34
|
},
|
|
35
|
-
plan_review_park: { required: true, duty: '弹 plan 审批卡(fail-soft,不挡后续终态帧)' },
|
|
35
|
+
plan_review_park: { required: true, duty: '弹 plan 审批卡(fail-soft,不挡后续终态帧);卡事实 `planReview` 在场时按它出选项与原因句(只有 shown 给批准档)' },
|
|
36
36
|
run_cost_reconciled: {
|
|
37
37
|
required: false,
|
|
38
38
|
duty: '可选:终局成本对账(own / nested / compaction 三段 + reconciled = own + nested)。' +
|
package/dist/seatContract.js
CHANGED
|
@@ -1254,6 +1254,7 @@ const SUBAGENT_CONTENT_SHAPE = shapeRule("subagent content", {
|
|
|
1254
1254
|
args: optF({ label: "passthrough", test: () => true }),
|
|
1255
1255
|
output: optF(R_STR),
|
|
1256
1256
|
isError: optF(R_BOOL),
|
|
1257
|
+
notExecuted: optF(R_TRUE),
|
|
1257
1258
|
});
|
|
1258
1259
|
export function readSeatSubagentContent(event) {
|
|
1259
1260
|
try {
|
|
@@ -33,7 +33,7 @@ export type SessionMemoryEraseAnswer = {
|
|
|
33
33
|
detail: string;
|
|
34
34
|
};
|
|
35
35
|
export declare function eraseSessionMemory(call: SessionMemoryEraseCall, wire: SessionMemoryEraseWire, opts?: SessionMemoryEraseOptions): Promise<SessionMemoryEraseAnswer>;
|
|
36
|
-
export type SessionMemoryEraseRefusalReason = 'bad_input' | 'no_connection' | 'cancelled_before_send' | 'credentials_required' | 'not_permitted' | 'memory_engine_absent' | 'session_not_found' | 'route_absent' | 'request_rejected' | 'evidence_unavailable' | 'request_id_reused' | 'store_unreadable';
|
|
36
|
+
export type SessionMemoryEraseRefusalReason = 'bad_input' | 'no_connection' | 'cancelled_before_send' | 'credentials_required' | 'not_permitted' | 'memory_engine_absent' | 'session_not_found' | 'route_absent' | 'request_rejected' | 'evidence_unavailable' | 'request_id_reused' | 'store_unreadable' | 'personal_store_unjudged';
|
|
37
37
|
export type SessionMemoryEraseUnconfirmedWhy = 'no_answer' | 'receipt_unreadable' | 'receipt_mismatch' | 'store_link_outside' | 'store_home_not_directory' | 'control_plane_corrupt' | 'engine_fault' | 'unclassified' | 'no_code' | 'unreadable';
|
|
38
38
|
export type SessionMemoryEraseRetry = 'not_needed' | 'same_request_id' | 'new_request_id' | 'needs_operator' | 'needs_consent' | 'human_decision' | 'pointless';
|
|
39
39
|
type SessionMemoryEraseReceipt = Extract<MemoryEraseReceiptReading, {
|
|
@@ -3,6 +3,7 @@ import { INJECTED_WIRE_SETTLE_MS, connectionLostDetail, noAnswerDetailFrom, noAn
|
|
|
3
3
|
import { memoryEraseReplayPosture, readMemoryEraseReceipt } from './memoryEntriesWire.js';
|
|
4
4
|
import { normalizeWirePrincipal } from './principalWire.js';
|
|
5
5
|
import { isSessionIdPathSegment } from './sessionIdSegment.js';
|
|
6
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
6
7
|
const PRINCIPAL_HEADER = 'x-agent-principal';
|
|
7
8
|
const MAX_TIMER_MS = 2_147_483_647;
|
|
8
9
|
const NOT_SENT = ' — nothing was sent';
|
|
@@ -231,6 +232,7 @@ const REFUSAL_TEXT = {
|
|
|
231
232
|
evidence_unavailable: "Nothing was erased: this deployment's memory store cannot keep proof of an erase, so the erase was declined.",
|
|
232
233
|
request_id_reused: 'Nothing was erased: this request id was already used for a different erase.',
|
|
233
234
|
store_unreadable: 'Nothing was erased: part of the memory store could not be read, so the erase was declined before anything changed; the deployment operator needs to repair the store.',
|
|
235
|
+
personal_store_unjudged: renderMessage(msg('session.memoryErase.personalStoreUnjudged')),
|
|
234
236
|
};
|
|
235
237
|
const UNCONFIRMED_TEXT = {
|
|
236
238
|
no_answer: 'Not confirmed: no answer came back from the engine, so the erase may or may not have happened.',
|
|
@@ -290,6 +292,7 @@ const REFUSAL_RETRY = {
|
|
|
290
292
|
evidence_unavailable: 'needs_consent',
|
|
291
293
|
request_id_reused: 'new_request_id',
|
|
292
294
|
store_unreadable: 'needs_operator',
|
|
295
|
+
personal_store_unjudged: 'pointless',
|
|
293
296
|
};
|
|
294
297
|
export const SESSION_MEMORY_ERASE_REFUSAL_REASONS = Object.freeze(Object.keys(REFUSAL_TEXT));
|
|
295
298
|
export const SESSION_MEMORY_ERASE_UNCONFIRMED_WHYS = Object.freeze(Object.keys(UNCONFIRMED_TEXT));
|
|
@@ -350,6 +353,8 @@ function bandOfCode(code) {
|
|
|
350
353
|
return { refused: 'request_id_reused' };
|
|
351
354
|
case 'memory.erasure_census_incomplete':
|
|
352
355
|
return { refused: 'store_unreadable' };
|
|
356
|
+
case 'memory.erasure_store_unjudged':
|
|
357
|
+
return { refused: 'personal_store_unjudged' };
|
|
353
358
|
case 'memory.target_outside_store':
|
|
354
359
|
return { unconfirmed: 'store_link_outside' };
|
|
355
360
|
case 'memory.scope_home_not_directory':
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { SessionMemoryStatus, SessionMemoryStatusResponse } from '@sema-agent/sdk';
|
|
2
|
+
import { type UiLanguage } from './env/uiLanguage.js';
|
|
2
3
|
export interface MemoryStatusClientLike {
|
|
3
4
|
sessions: {
|
|
4
5
|
memoryStatus(sessionId: string, opts?: {
|
|
@@ -8,7 +9,17 @@ export interface MemoryStatusClientLike {
|
|
|
8
9
|
} & SessionMemoryStatus>;
|
|
9
10
|
};
|
|
10
11
|
}
|
|
11
|
-
export type MemoryStatusFacts = Omit<SessionMemoryStatusResponse, 'sessionId'
|
|
12
|
+
export type MemoryStatusFacts = Omit<SessionMemoryStatusResponse, 'sessionId' | 'memorySync'> & {
|
|
13
|
+
readonly memorySync?: MemorySyncFacts;
|
|
14
|
+
};
|
|
15
|
+
export interface MemorySyncFacts {
|
|
16
|
+
readonly parked: readonly MemorySyncParkedFacts[];
|
|
17
|
+
}
|
|
18
|
+
export interface MemorySyncParkedFacts {
|
|
19
|
+
readonly scope: string;
|
|
20
|
+
readonly wayOut: string;
|
|
21
|
+
}
|
|
22
|
+
export declare const MEMORY_SYNC_WAY_OUT_DELETE_CURSOR: "delete_cursor";
|
|
12
23
|
export type MemoryStatusVerdict = {
|
|
13
24
|
readonly kind: 'ok';
|
|
14
25
|
readonly sessionId: string;
|
|
@@ -44,4 +55,19 @@ export declare function readLastCapture(s: SessionMemoryStatus): LastCaptureRead
|
|
|
44
55
|
export declare function readSessionMemoryStatus(client: MemoryStatusClientLike, sessionId: string, opts?: {
|
|
45
56
|
signal?: AbortSignal;
|
|
46
57
|
}): Promise<MemoryStatusVerdict>;
|
|
58
|
+
export type MemorySyncParkingReading = {
|
|
59
|
+
readonly state: 'syncing';
|
|
60
|
+
} | {
|
|
61
|
+
readonly state: 'parked';
|
|
62
|
+
readonly layers: readonly MemorySyncParkedLayerReading[];
|
|
63
|
+
} | {
|
|
64
|
+
readonly state: 'not_reported';
|
|
65
|
+
};
|
|
66
|
+
export interface MemorySyncParkedLayerReading {
|
|
67
|
+
readonly scope: string;
|
|
68
|
+
readonly wayOut: string;
|
|
69
|
+
readonly deleteCursor: boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare function readMemorySyncParking(facts: MemoryStatusFacts | null | undefined): MemorySyncParkingReading;
|
|
72
|
+
export declare function memorySyncParkingNotice(reading: MemorySyncParkingReading, lang?: UiLanguage | (string & {})): string | undefined;
|
|
47
73
|
export declare function readAutoConsolidationArmed(facts: MemoryStatusFacts | null | undefined): 'armed' | 'unarmed' | 'indeterminate';
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { isSessionIdPathSegment } from './sessionIdSegment.js';
|
|
2
2
|
import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
|
|
3
|
+
import { isUiLanguage } from './env/uiLanguage.js';
|
|
4
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
5
|
+
export const MEMORY_SYNC_WAY_OUT_DELETE_CURSOR = 'delete_cursor';
|
|
6
|
+
const MEMORY_SYNC_PARKED_READ_MAX = 256;
|
|
3
7
|
export function classifyMemoryStatusFailure(e) {
|
|
4
8
|
const rawCode = readThrownSlot(e, 'errorCode', 'data');
|
|
5
9
|
const rawStatus = readThrownSlot(e, 'status', 'data');
|
|
@@ -64,6 +68,7 @@ export async function readSessionMemoryStatus(client, sessionId, opts) {
|
|
|
64
68
|
: {}),
|
|
65
69
|
...(typeof o.lastCaptureAt === 'number' ? { lastCaptureAt: o.lastCaptureAt } : {}),
|
|
66
70
|
...(typeof o.autoConsolidationArmed === 'boolean' ? { autoConsolidationArmed: o.autoConsolidationArmed } : {}),
|
|
71
|
+
...memorySyncSpread(o),
|
|
67
72
|
},
|
|
68
73
|
};
|
|
69
74
|
}
|
|
@@ -71,6 +76,118 @@ export async function readSessionMemoryStatus(client, sessionId, opts) {
|
|
|
71
76
|
return classifyMemoryStatusFailure(e);
|
|
72
77
|
}
|
|
73
78
|
}
|
|
79
|
+
function ownDataSlot(o, key) {
|
|
80
|
+
try {
|
|
81
|
+
const d = Object.getOwnPropertyDescriptor(o, key);
|
|
82
|
+
if (d === undefined)
|
|
83
|
+
return { ok: true, value: undefined };
|
|
84
|
+
return Object.hasOwn(d, 'value') ? { ok: true, value: d.value } : { ok: false };
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return { ok: false };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const isPlainObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
91
|
+
function memorySyncFactsOf(raw) {
|
|
92
|
+
try {
|
|
93
|
+
if (!isPlainObject(raw))
|
|
94
|
+
return undefined;
|
|
95
|
+
const parkedSlot = ownDataSlot(raw, 'parked');
|
|
96
|
+
if (!parkedSlot.ok || !Array.isArray(parkedSlot.value))
|
|
97
|
+
return undefined;
|
|
98
|
+
const arr = parkedSlot.value;
|
|
99
|
+
const len = ownDataSlot(arr, 'length');
|
|
100
|
+
if (!len.ok || typeof len.value !== 'number' || !Number.isSafeInteger(len.value) || len.value < 0 || len.value > MEMORY_SYNC_PARKED_READ_MAX)
|
|
101
|
+
return undefined;
|
|
102
|
+
const parked = [];
|
|
103
|
+
for (let i = 0; i < len.value; i++) {
|
|
104
|
+
const el = ownDataSlot(arr, String(i));
|
|
105
|
+
if (!el.ok || !isPlainObject(el.value))
|
|
106
|
+
return undefined;
|
|
107
|
+
const scope = ownDataSlot(el.value, 'scope');
|
|
108
|
+
const wayOut = ownDataSlot(el.value, 'wayOut');
|
|
109
|
+
if (!scope.ok || !wayOut.ok || typeof scope.value !== 'string' || scope.value.length === 0 || typeof wayOut.value !== 'string' || wayOut.value.length === 0)
|
|
110
|
+
return undefined;
|
|
111
|
+
parked.push(Object.freeze({ scope: scope.value, wayOut: wayOut.value }));
|
|
112
|
+
}
|
|
113
|
+
return Object.freeze({ parked: Object.freeze(parked) });
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function memorySyncSpread(o) {
|
|
120
|
+
const slot = ownDataSlot(o, 'memorySync');
|
|
121
|
+
if (!slot.ok || slot.value === undefined)
|
|
122
|
+
return {};
|
|
123
|
+
const facts = memorySyncFactsOf(slot.value);
|
|
124
|
+
return facts === undefined ? {} : { memorySync: facts };
|
|
125
|
+
}
|
|
126
|
+
export function readMemorySyncParking(facts) {
|
|
127
|
+
let sync;
|
|
128
|
+
try {
|
|
129
|
+
if (!isPlainObject(facts))
|
|
130
|
+
return Object.freeze({ state: 'not_reported' });
|
|
131
|
+
const slot = ownDataSlot(facts, 'memorySync');
|
|
132
|
+
sync = slot.ok ? memorySyncFactsOf(slot.value) : undefined;
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
sync = undefined;
|
|
136
|
+
}
|
|
137
|
+
if (sync === undefined)
|
|
138
|
+
return Object.freeze({ state: 'not_reported' });
|
|
139
|
+
if (sync.parked.length === 0)
|
|
140
|
+
return Object.freeze({ state: 'syncing' });
|
|
141
|
+
return Object.freeze({
|
|
142
|
+
state: 'parked',
|
|
143
|
+
layers: Object.freeze(sync.parked.map((p) => Object.freeze({ scope: p.scope, wayOut: p.wayOut, deleteCursor: p.wayOut === MEMORY_SYNC_WAY_OUT_DELETE_CURSOR }))),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
const MEMORY_SYNC_SCOPE_NAME_MAX = 120;
|
|
147
|
+
export function memorySyncParkingNotice(reading, lang) {
|
|
148
|
+
try {
|
|
149
|
+
if (typeof reading !== 'object' || reading === null)
|
|
150
|
+
return undefined;
|
|
151
|
+
const state = Object.getOwnPropertyDescriptor(reading, 'state');
|
|
152
|
+
if (state === undefined || !Object.hasOwn(state, 'value') || state.value !== 'parked')
|
|
153
|
+
return undefined;
|
|
154
|
+
const layersSlot = Object.getOwnPropertyDescriptor(reading, 'layers');
|
|
155
|
+
if (layersSlot === undefined || !Object.hasOwn(layersSlot, 'value') || !Array.isArray(layersSlot.value))
|
|
156
|
+
return undefined;
|
|
157
|
+
const raw = layersSlot.value;
|
|
158
|
+
const lenSlot = Object.getOwnPropertyDescriptor(raw, 'length');
|
|
159
|
+
const count = lenSlot?.value;
|
|
160
|
+
if (typeof count !== 'number' || !Number.isSafeInteger(count) || count < 1 || count > MEMORY_SYNC_PARKED_READ_MAX)
|
|
161
|
+
return undefined;
|
|
162
|
+
const scopes = [];
|
|
163
|
+
let named = true;
|
|
164
|
+
let allDeleteCursor = true;
|
|
165
|
+
for (let i = 0; i < count; i++) {
|
|
166
|
+
const el = Object.getOwnPropertyDescriptor(raw, String(i));
|
|
167
|
+
const layer = el !== undefined && Object.hasOwn(el, 'value') ? el.value : undefined;
|
|
168
|
+
if (typeof layer !== 'object' || layer === null)
|
|
169
|
+
return undefined;
|
|
170
|
+
const scope = Object.getOwnPropertyDescriptor(layer, 'scope');
|
|
171
|
+
const del = Object.getOwnPropertyDescriptor(layer, 'deleteCursor');
|
|
172
|
+
const s = scope !== undefined && Object.hasOwn(scope, 'value') ? scope.value : undefined;
|
|
173
|
+
if (typeof s !== 'string' || s.length === 0 || s.length > MEMORY_SYNC_SCOPE_NAME_MAX || /[\p{Cc}\p{Cf}\p{Zl}\p{Zp}]/u.test(s))
|
|
174
|
+
named = false;
|
|
175
|
+
else
|
|
176
|
+
scopes.push(s);
|
|
177
|
+
if (del === undefined || !Object.hasOwn(del, 'value') || del.value !== true)
|
|
178
|
+
allDeleteCursor = false;
|
|
179
|
+
}
|
|
180
|
+
const wayOut = msg(allDeleteCursor ? 'session.memorySync.wayOut.deleteCursor' : 'session.memorySync.wayOut.unrecognized');
|
|
181
|
+
if (!named)
|
|
182
|
+
return renderMessage(msg(count === 1 ? 'session.memorySync.parkedUnnamed.one' : 'session.memorySync.parkedUnnamed.other', { count, wayOut }), isUiLanguage(lang) ? lang : undefined);
|
|
183
|
+
if (count === 1)
|
|
184
|
+
return renderMessage(msg('session.memorySync.parked.one', { scope: scopes[0] ?? '', wayOut }), isUiLanguage(lang) ? lang : undefined);
|
|
185
|
+
return renderMessage(msg('session.memorySync.parked.other', { count, scopes: scopes.join(lang === 'zh' ? '、' : ', '), wayOut }), isUiLanguage(lang) ? lang : undefined);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
74
191
|
export function readAutoConsolidationArmed(facts) {
|
|
75
192
|
if (typeof facts !== 'object' || facts === null)
|
|
76
193
|
return 'indeterminate';
|
package/dist/sseIdleTriage.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type EnvLike } from './hostEnv.js';
|
|
2
|
+
import { type RunNotFollowed } from './runFollow.js';
|
|
2
3
|
export declare const SSE_HEARTBEAT_GRACE_ENV = "SEMA_SSE_HEARTBEAT_GRACE_MS";
|
|
3
4
|
export declare const SSE_GRACE_MIN_MS = 5000;
|
|
4
5
|
export declare const SSE_GRACE_MAX_MS = 600000;
|
|
@@ -7,9 +8,10 @@ export declare function resolveSseHeartbeatGraceMs(env?: EnvLike): number | unde
|
|
|
7
8
|
export declare function markEngineAliveIdle<E extends Error>(err: E): E;
|
|
8
9
|
export declare function engineAliveIdleElapsedMs(err: unknown): number | undefined;
|
|
9
10
|
export declare function isSseIdleError(err: unknown): boolean;
|
|
11
|
+
export declare function isStreamEndedWithoutTerminalError(err: {} | null | undefined): boolean;
|
|
10
12
|
export declare function probeEngineAlive(baseUrl: string, timeoutMs?: number): Promise<boolean>;
|
|
11
13
|
export declare function diagnoseSseIdleTear<T>(inner: AsyncGenerator<T>, baseUrl: string, signal?: AbortSignal): AsyncGenerator<T>;
|
|
12
14
|
export declare function engineAliveIdleContent(elapsedMs: number, detach?: {
|
|
13
15
|
detached: true;
|
|
14
16
|
taskId?: string;
|
|
15
|
-
}): string;
|
|
17
|
+
}, notFollowed?: RunNotFollowed): string;
|
package/dist/sseIdleTriage.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { hostEnv } from './hostEnv.js';
|
|
2
|
-
import { SseIdleError, probeHealth as sdkProbeHealth } from '@sema-agent/sdk';
|
|
2
|
+
import { SseIdleError, StreamEndedWithoutTerminalError, probeHealth as sdkProbeHealth } from '@sema-agent/sdk';
|
|
3
3
|
import { readThrownSlot, thrownIsInstanceOf } from './wireFailureShape.js';
|
|
4
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
5
|
+
import { runNotFollowedNoticeRef } from './runFollow.js';
|
|
4
6
|
export const SSE_HEARTBEAT_GRACE_ENV = 'SEMA_SSE_HEARTBEAT_GRACE_MS';
|
|
5
7
|
export const SSE_GRACE_MIN_MS = 5_000;
|
|
6
8
|
export const SSE_GRACE_MAX_MS = 600_000;
|
|
@@ -17,8 +19,12 @@ export function resolveSseHeartbeatGraceMs(env = hostEnv()) {
|
|
|
17
19
|
return n;
|
|
18
20
|
}
|
|
19
21
|
export function markEngineAliveIdle(err) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
try {
|
|
23
|
+
;
|
|
24
|
+
err.semaTearVerdict = 'engine-alive-idle';
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
}
|
|
22
28
|
return err;
|
|
23
29
|
}
|
|
24
30
|
export function engineAliveIdleElapsedMs(err) {
|
|
@@ -32,6 +38,11 @@ export function isSseIdleError(err) {
|
|
|
32
38
|
return true;
|
|
33
39
|
return readThrownSlot(err, 'name', 'data') === 'SseIdleError';
|
|
34
40
|
}
|
|
41
|
+
export function isStreamEndedWithoutTerminalError(err) {
|
|
42
|
+
if (thrownIsInstanceOf(err, StreamEndedWithoutTerminalError))
|
|
43
|
+
return true;
|
|
44
|
+
return readThrownSlot(err, 'name', 'data') === 'StreamEndedWithoutTerminalError';
|
|
45
|
+
}
|
|
35
46
|
export async function probeEngineAlive(baseUrl, timeoutMs = 2_000) {
|
|
36
47
|
return (await sdkProbeHealth(baseUrl, timeoutMs)).alive;
|
|
37
48
|
}
|
|
@@ -46,8 +57,12 @@ export async function* diagnoseSseIdleTear(inner, baseUrl, signal) {
|
|
|
46
57
|
throw err;
|
|
47
58
|
}
|
|
48
59
|
}
|
|
49
|
-
export function engineAliveIdleContent(elapsedMs, detach) {
|
|
60
|
+
export function engineAliveIdleContent(elapsedMs, detach, notFollowed) {
|
|
50
61
|
const secs = Math.max(1, Math.round((elapsedMs > 0 ? elapsedMs : SDK_DEFAULT_GRACE_MS) / 1000));
|
|
62
|
+
if (notFollowed !== undefined && notFollowed !== null) {
|
|
63
|
+
const grace = msg('follow.notFollowed.idleGrace', { env: SSE_HEARTBEAT_GRACE_ENV, min: SSE_GRACE_MIN_MS, max: SSE_GRACE_MAX_MS, default: SDK_DEFAULT_GRACE_MS });
|
|
64
|
+
return renderMessage(msg('follow.notFollowed.idleTear', { secs, notice: runNotFollowedNoticeRef(notFollowed), grace }));
|
|
65
|
+
}
|
|
51
66
|
const graceTail = `If your tasks legitimately go quiet this long (e.g. a long build), raise the idle grace: set ${SSE_HEARTBEAT_GRACE_ENV} ` +
|
|
52
67
|
`(settings env, integer ms, ${SSE_GRACE_MIN_MS}-${SSE_GRACE_MAX_MS}; default ${SDK_DEFAULT_GRACE_MS}).`;
|
|
53
68
|
if (detach?.detached) {
|
package/dist/steering.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface EngineTaskStatusAttachment {
|
|
|
11
11
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'killed' | 'parked';
|
|
12
12
|
description: string;
|
|
13
13
|
deltaSummary: null;
|
|
14
|
+
read?: string;
|
|
14
15
|
}
|
|
15
16
|
export type SteeringRenderable = SteeringInjectedAttachment | EngineTaskStatusAttachment;
|
|
16
17
|
export declare function steeringLabel(source: string): string;
|
package/dist/steering.js
CHANGED
|
@@ -25,37 +25,45 @@ const PHRASE_TO_STATUS = [
|
|
|
25
25
|
['failed', 'failed'],
|
|
26
26
|
['killed', 'killed'],
|
|
27
27
|
];
|
|
28
|
+
const BACKGROUND_TASK_LINE = new RegExp('^- \\[([^\\]]+)\\] Task "([\\s\\S]*)" (' +
|
|
29
|
+
PHRASE_TO_STATUS.map(([phrase]) => phrase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') +
|
|
30
|
+
')(?: — ((?:(?!" )[\\s\\S])*))?$');
|
|
28
31
|
function parseBackgroundTaskLine(line) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
32
|
+
const m = BACKGROUND_TASK_LINE.exec(line.trim());
|
|
33
|
+
if (!m)
|
|
34
|
+
return null;
|
|
35
|
+
const taskId = m[1];
|
|
36
|
+
const description = m[2];
|
|
37
|
+
const status = PHRASE_TO_STATUS.find(([phrase]) => phrase === m[3])?.[1];
|
|
38
|
+
if (taskId === undefined || description === undefined || status === undefined)
|
|
39
|
+
return null;
|
|
40
|
+
const read = m[4];
|
|
41
|
+
return {
|
|
42
|
+
type: 'task_status',
|
|
43
|
+
taskId,
|
|
44
|
+
taskType: 'local_bash',
|
|
45
|
+
status,
|
|
46
|
+
description,
|
|
47
|
+
deltaSummary: null,
|
|
48
|
+
...(read !== undefined ? { read } : {}),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function rowBoundariesTrusted(lines) {
|
|
52
|
+
let last = lines.length - 1;
|
|
53
|
+
while (last >= 0 && (lines[last] ?? '').trim() === '')
|
|
54
|
+
last--;
|
|
55
|
+
for (let i = 0; i < last; i++) {
|
|
56
|
+
if (/^- \[[^\]]+\] Task "[^"]*$/.test((lines[i] ?? '').trim()))
|
|
57
|
+
return false;
|
|
50
58
|
}
|
|
51
|
-
return
|
|
59
|
+
return true;
|
|
52
60
|
}
|
|
53
61
|
export function steeringInjectedToAttachments(source, preview) {
|
|
54
62
|
if (source === 'background_tasks') {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
.map(parseBackgroundTaskLine)
|
|
58
|
-
|
|
63
|
+
const lines = preview.split('\n');
|
|
64
|
+
const tasks = rowBoundariesTrusted(lines)
|
|
65
|
+
? lines.map(parseBackgroundTaskLine).filter((t) => t !== null)
|
|
66
|
+
: [];
|
|
59
67
|
if (tasks.length > 0)
|
|
60
68
|
return tasks;
|
|
61
69
|
}
|
|
@@ -6,6 +6,7 @@ import { engineSessionParamFor } from '../engineSessionParam.js';
|
|
|
6
6
|
import { resolveOwnerContext } from './engineSubagentResume.js';
|
|
7
7
|
import { coerceOutput, parentToolCallIdOf, publishSubagentContentEvent, settleSubagentContent, } from '../subagentContentStore.js';
|
|
8
8
|
import { noteBgOwnerAbsence } from './subagentOwnerAbsence.js';
|
|
9
|
+
import { readFrameTrueMark } from '../ownKey.js';
|
|
9
10
|
function usableTailClient(client) {
|
|
10
11
|
return clientHasVerbs(client, [['capabilities'], ['runs', 'subagentStream']]);
|
|
11
12
|
}
|
|
@@ -140,6 +141,7 @@ export function tailEngineSubagent(taskId, opts) {
|
|
|
140
141
|
...(typeof d.toolName === 'string' ? { toolName: d.toolName } : {}),
|
|
141
142
|
...(out !== undefined ? { output: out } : {}),
|
|
142
143
|
...(d.isError === true ? { isError: true } : {}),
|
|
144
|
+
...(readFrameTrueMark(d, 'notExecuted') ? { notExecuted: true } : {}),
|
|
143
145
|
});
|
|
144
146
|
}
|
|
145
147
|
else if (t === 'task_settled') {
|
|
@@ -11,6 +11,7 @@ export type SubagentContentItem = {
|
|
|
11
11
|
input: unknown;
|
|
12
12
|
output?: string;
|
|
13
13
|
isError?: boolean;
|
|
14
|
+
notExecuted?: true;
|
|
14
15
|
} | {
|
|
15
16
|
kind: 'echo';
|
|
16
17
|
text: string;
|
|
@@ -31,6 +32,7 @@ export interface SubagentContentEvent {
|
|
|
31
32
|
args?: unknown;
|
|
32
33
|
output?: string | undefined;
|
|
33
34
|
isError?: boolean | undefined;
|
|
35
|
+
notExecuted?: true | undefined;
|
|
34
36
|
}
|
|
35
37
|
export declare function coerceOutput(v: unknown): string | undefined;
|
|
36
38
|
export declare function subagentContentEventOf(ev: {
|
|
@@ -82,6 +84,7 @@ export type SubagentViewSlot = {
|
|
|
82
84
|
input: unknown;
|
|
83
85
|
output?: string;
|
|
84
86
|
isError?: boolean;
|
|
87
|
+
notExecuted?: true;
|
|
85
88
|
};
|
|
86
89
|
export declare function planSubagentViewSlots(taskId: string): SubagentViewSlot[];
|
|
87
90
|
export declare function parentToolCallIdOf(taskId: string): string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
2
|
+
import { readFrameTrueMark } from './ownKey.js';
|
|
2
3
|
import { toolEndOutputText } from './toolResultContent.js';
|
|
3
4
|
export function coerceOutput(v) {
|
|
4
5
|
return toolEndOutputText(v);
|
|
@@ -23,6 +24,7 @@ export function subagentContentEventOf(ev) {
|
|
|
23
24
|
args: sub.args,
|
|
24
25
|
output: coerceOutput(sub.output),
|
|
25
26
|
isError: sub.isError,
|
|
27
|
+
notExecuted: readFrameTrueMark(sub, 'notExecuted') ? true : undefined,
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
const MAX_ITEMS_PER_TASK = 200;
|
|
@@ -567,12 +569,17 @@ export function publishSubagentContentEvent(ev) {
|
|
|
567
569
|
const before = itemBytesOf(it);
|
|
568
570
|
const outBefore = it.output;
|
|
569
571
|
const errBefore = it.isError;
|
|
572
|
+
const notExecBefore = it.notExecuted;
|
|
570
573
|
it.output = ev.output ?? '';
|
|
571
574
|
it.isError = ev.isError === true;
|
|
575
|
+
if (ev.notExecuted === true)
|
|
576
|
+
it.notExecuted = true;
|
|
577
|
+
else
|
|
578
|
+
delete it.notExecuted;
|
|
572
579
|
const delta = itemBytesOf(it) - before;
|
|
573
580
|
s.itemBytes[at] = (s.itemBytes[at] ?? 0) + delta;
|
|
574
581
|
addBytes(s, delta);
|
|
575
|
-
stampPhase(s, it.id, 'end', ev.eventId, it.output !== outBefore || it.isError !== errBefore);
|
|
582
|
+
stampPhase(s, it.id, 'end', ev.eventId, it.output !== outBefore || it.isError !== errBefore || it.notExecuted !== notExecBefore);
|
|
576
583
|
break;
|
|
577
584
|
}
|
|
578
585
|
const synthId = id ?? `${ev.taskId}-tool-${s.items.length}`;
|
|
@@ -583,6 +590,7 @@ export function publishSubagentContentEvent(ev) {
|
|
|
583
590
|
input: ev.args ?? {},
|
|
584
591
|
output: ev.output ?? '',
|
|
585
592
|
isError: ev.isError === true,
|
|
593
|
+
...(ev.notExecuted === true ? { notExecuted: true } : {}),
|
|
586
594
|
});
|
|
587
595
|
recordCut(s);
|
|
588
596
|
stampPhase(s, synthId, 'end', ev.eventId, true);
|
|
@@ -626,6 +634,7 @@ export function planSubagentViewSlots(taskId) {
|
|
|
626
634
|
input: it.input,
|
|
627
635
|
...(it.output !== undefined ? { output: it.output } : {}),
|
|
628
636
|
...(it.isError === true ? { isError: true } : {}),
|
|
637
|
+
...(it.notExecuted === true ? { notExecuted: true } : {}),
|
|
629
638
|
});
|
|
630
639
|
}
|
|
631
640
|
else if (it.kind === 'text') {
|
|
@@ -4,10 +4,13 @@ import { type LiveModelCatalog } from './liveModelCatalog.js';
|
|
|
4
4
|
import type { TaskRequestLike } from './request/taskRequest.js';
|
|
5
5
|
export type TurnFailureCategory = 'auth' | 'billing' | 'rate_limited' | 'invalid_request' | 'capability_unavailable' | 'timeout' | 'server_error' | 'connection_lost' | 'parked' | 'internal';
|
|
6
6
|
export declare const TURN_FAILURE_CATEGORIES: readonly TurnFailureCategory[];
|
|
7
|
-
export
|
|
7
|
+
export type TurnFailureRetry = {
|
|
8
8
|
readonly offer: boolean;
|
|
9
9
|
readonly basis: 'wire' | 'category';
|
|
10
|
-
}
|
|
10
|
+
} | {
|
|
11
|
+
readonly offer: false;
|
|
12
|
+
readonly basis: 'not_followed';
|
|
13
|
+
};
|
|
11
14
|
export interface TurnFailurePresentation {
|
|
12
15
|
readonly category: TurnFailureCategory;
|
|
13
16
|
readonly kind: TurnWireErrorVerdict['kind'];
|