@sema-agent/client-core 0.108.0 → 0.110.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 +294 -0
- package/README.md +77 -40
- package/dist/adapt/arms.js +41 -13
- package/dist/adapt/textStream.d.ts +2 -0
- package/dist/adapt/textStream.js +37 -16
- package/dist/adapter/activeRunSelfHeal.js +1 -1
- package/dist/adapter/downstream/eventToSdkMessage.js +11 -5
- package/dist/agentSession/engineAgentRegistryRead.js +2 -0
- package/dist/bashExitReading.d.ts +12 -0
- package/dist/bashExitReading.js +44 -0
- package/dist/checkpointRowVerdict.d.ts +1 -1
- package/dist/checkpointRowVerdict.js +4 -2
- package/dist/compensations.js +1 -1
- package/dist/declared/supportFloorDeclared.js +1 -1
- package/dist/displayUntrusted.js +132 -14
- package/dist/engineAgentAbsence.d.ts +2 -0
- package/dist/engineAgentAbsence.js +28 -0
- package/dist/engineErrorCodes.d.ts +7 -0
- package/dist/engineErrorCodes.js +7 -0
- package/dist/engineHealthFacts.d.ts +26 -0
- package/dist/engineHealthFacts.js +63 -4
- package/dist/engineInlineTaskStats.d.ts +4 -3
- package/dist/engineInlineTaskStats.js +18 -2
- package/dist/engineNoticeCodes.d.ts +138 -0
- package/dist/engineNoticeCodes.js +662 -55
- package/dist/engineRepoint.d.ts +140 -0
- package/dist/engineRepoint.js +285 -0
- package/dist/engineRowRef.js +2 -0
- package/dist/engineSessionMessages.d.ts +2 -1
- package/dist/engineSessionMessages.js +5 -0
- package/dist/errorSupplementRoles.js +5 -1
- package/dist/fleet/fleetProjection.js +3 -2
- package/dist/fleetTaskDesc.js +3 -3
- package/dist/generated/engineFactTables.d.ts +3 -0
- package/dist/generated/engineFactTables.js +18 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/sdkFactTables.d.ts +1 -0
- package/dist/generated/sdkFactTables.js +4 -0
- package/dist/hitl/approvalAskers.d.ts +6 -0
- package/dist/hitl/approvalAskers.js +30 -0
- package/dist/hitl/approvalCardReasons.js +25 -4
- package/dist/hitl/approvalRequestFrameReading.d.ts +21 -0
- package/dist/hitl/approvalRequestFrameReading.js +90 -0
- package/dist/hitl/approvalResolution.d.ts +8 -1
- package/dist/hitl/approvalResolution.js +4 -0
- package/dist/hitl/approvalsFeed.js +1 -1
- package/dist/hitl/askGateWire.js +0 -2
- package/dist/hitl/askParkRowRouting.js +5 -2
- package/dist/hitl/automaticAnswerVerdict.d.ts +5 -2
- package/dist/hitl/automaticAnswerVerdict.js +18 -4
- package/dist/hitl/decisionConflict.d.ts +2 -1
- package/dist/hitl/decisionConflict.js +10 -4
- package/dist/hitl/decisionRefusal.js +1 -0
- package/dist/hitl/decisionSend.d.ts +3 -0
- package/dist/hitl/decisionSend.js +29 -11
- package/dist/hitl/editedApprovalAcceptance.d.ts +25 -0
- package/dist/hitl/editedApprovalAcceptance.js +26 -0
- package/dist/hitl/frameRouter.js +13 -19
- package/dist/hitl/gateLedger.d.ts +0 -4
- package/dist/hitl/gateLedger.js +0 -19
- package/dist/hitl/hitlBridge.d.ts +5 -0
- package/dist/hitl/hitlBridge.js +13 -9
- package/dist/hitl/hitlHostSurface.d.ts +1 -0
- package/dist/hitl/hitlHostSurface.js +7 -2
- package/dist/hitl/hostWithdrawal.d.ts +15 -0
- package/dist/hitl/hostWithdrawal.js +38 -0
- package/dist/hitl/livePendingAsk.js +17 -16
- package/dist/hitl/localAllowRule.js +2 -1
- package/dist/hitl/noAllowCause.d.ts +1 -1
- package/dist/hitl/noAllowCause.js +4 -2
- package/dist/hitl/parkExpiryJudgements.js +26 -1
- package/dist/hitl/parkOwnership.d.ts +2 -0
- package/dist/hitl/parkOwnership.js +48 -8
- package/dist/hitl/parkResolver.js +32 -16
- package/dist/hitl/parkedUnresumable.d.ts +13 -0
- package/dist/hitl/parkedUnresumable.js +80 -0
- package/dist/hitl/permissionRuleScope.d.ts +4 -0
- package/dist/hitl/permissionRuleScope.js +31 -0
- package/dist/hitl/persistedRulesWire.d.ts +2 -0
- package/dist/hitl/persistedRulesWire.js +13 -12
- package/dist/hitl/planReviewWire.js +14 -4
- package/dist/hitl/sessionAllowRoute.js +5 -4
- package/dist/hitl/sessionPolicyWire.js +6 -4
- package/dist/hitl/standingRows.d.ts +2 -5
- package/dist/hitl/standingRows.js +30 -15
- package/dist/hitl/toolApprovalWire.d.ts +42 -9
- package/dist/hitl/toolApprovalWire.js +267 -44
- package/dist/hooksWireCaps.js +35 -4
- package/dist/hostSettingsSource.js +2 -0
- package/dist/hostTurnSettings.d.ts +10 -4
- package/dist/hostTurnSettings.js +112 -5
- package/dist/i18n/messages.en.d.ts +251 -0
- package/dist/i18n/messages.en.js +254 -2
- package/dist/i18n/messages.zh.js +264 -2
- package/dist/index.d.ts +48 -12
- package/dist/index.js +29 -7
- package/dist/inheritEnvCapability.js +2 -0
- package/dist/inputAuthor.d.ts +16 -0
- package/dist/inputAuthor.js +44 -0
- package/dist/interruptRefusalNote.d.ts +2 -0
- package/dist/interruptRefusalNote.js +17 -0
- package/dist/liveModelCatalog.d.ts +2 -0
- package/dist/liveModelCatalog.js +21 -7
- package/dist/liveQuestionStore.d.ts +4 -1
- package/dist/liveQuestionStore.js +12 -3
- package/dist/localEngineJudge.d.ts +75 -0
- package/dist/localEngineJudge.js +242 -0
- package/dist/localEngineOccupancy.d.ts +88 -0
- package/dist/localEngineOccupancy.js +269 -0
- package/dist/localEngineSeatReading.d.ts +29 -0
- package/dist/localEngineSeatReading.js +294 -0
- package/dist/localEngineSpawn.d.ts +113 -0
- package/dist/localEngineSpawn.js +486 -0
- package/dist/localEngineStep.d.ts +286 -0
- package/dist/localEngineStep.js +1086 -0
- package/dist/localEngineStopLadder.d.ts +29 -0
- package/dist/localEngineStopLadder.js +139 -0
- package/dist/localEngineSwapCard.d.ts +43 -0
- package/dist/localEngineSwapCard.js +205 -0
- package/dist/localEngineTiming.d.ts +8 -0
- package/dist/localEngineTiming.js +8 -0
- package/dist/mcpEngineLeg.d.ts +3 -0
- package/dist/mcpEngineLeg.js +38 -1
- package/dist/mcpPanel.js +2 -0
- package/dist/mcpReconnect.d.ts +9 -1
- package/dist/mcpReconnect.js +132 -20
- package/dist/mcpWireCaps.js +2 -2
- package/dist/memoryEntriesWire.d.ts +1 -1
- package/dist/memoryEntriesWire.js +5 -0
- package/dist/modelCapabilityProbe.js +4 -3
- package/dist/modsFace.d.ts +8 -1
- package/dist/modsFace.js +27 -0
- package/dist/noticePresentation.d.ts +2 -0
- package/dist/noticePresentation.js +79 -1
- package/dist/notifications.d.ts +17 -6
- package/dist/notifications.js +67 -19
- package/dist/ownKey.d.ts +5 -0
- package/dist/ownKey.js +8 -1
- package/dist/peerFrames.d.ts +40 -2
- package/dist/peerFrames.js +158 -3
- package/dist/pluginHooksWire.d.ts +2 -1
- package/dist/pluginHooksWire.js +56 -1
- package/dist/replayBody.js +10 -2
- package/dist/request/taskRequest.d.ts +5 -0
- package/dist/request/taskRequest.js +138 -21
- package/dist/resumeRefusalCopy.d.ts +1 -3
- package/dist/resumeRefusalCopy.js +2 -1
- package/dist/retryStatus.d.ts +2 -2
- package/dist/retryStatus.js +2 -0
- package/dist/ruleReadings.js +1 -1
- package/dist/seam.d.ts +24 -2
- package/dist/seam.js +15 -2
- package/dist/seatContract.d.ts +125 -10
- package/dist/seatContract.js +373 -7
- package/dist/sessionBackground.js +4 -1
- package/dist/sessionBackgroundHandoff.js +2 -1
- package/dist/sessionEngine.d.ts +2 -0
- package/dist/sessionEngine.js +111 -0
- package/dist/sessionMemoryStatus.d.ts +2 -1
- package/dist/sessionSyncFileHistory.d.ts +4 -0
- package/dist/sessionSyncFileHistory.js +28 -0
- package/dist/sseIdleTriage.d.ts +13 -1
- package/dist/sseIdleTriage.js +24 -6
- package/dist/subagent/engineSubagentTail.js +6 -0
- package/dist/subagentContentStore.d.ts +12 -0
- package/dist/subagentContentStore.js +72 -11
- package/dist/terminalStatuses.d.ts +1 -0
- package/dist/terminalStatuses.js +4 -1
- package/dist/toolResult.js +18 -5
- package/dist/turnFailurePresentation.js +9 -2
- package/dist/typePins.d.ts +11 -0
- package/dist/usageAnalytics.d.ts +17 -0
- package/dist/usageAnalytics.js +44 -2
- package/dist/wireFailureShape.d.ts +22 -5
- package/dist/wireFailureShape.js +47 -26
- package/dist/wireRefusalCopy.d.ts +31 -1
- package/dist/wireRefusalCopy.js +167 -2
- package/docs/INTEGRATION-CLIENTS.md +3269 -21
- package/package.json +5 -5
package/dist/sessionEngine.js
CHANGED
|
@@ -377,6 +377,117 @@ function methodOf(o, key) {
|
|
|
377
377
|
return undefined;
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
|
+
function addressBindingOf(raw) {
|
|
381
|
+
if (typeof raw !== 'string')
|
|
382
|
+
return undefined;
|
|
383
|
+
const b = addressBinding(raw);
|
|
384
|
+
return b.ok && b.identityKind === 'address' ? b : undefined;
|
|
385
|
+
}
|
|
386
|
+
function enginesTableOf(record) {
|
|
387
|
+
const slot = slotReadOf(record, 'engines');
|
|
388
|
+
if (slot.presence === 'absent' || (slot.presence === 'present' && slot.value === undefined))
|
|
389
|
+
return 'absent';
|
|
390
|
+
return slot.presence === 'present' && isObj(slot.value) ? slot.value : 'unreadable';
|
|
391
|
+
}
|
|
392
|
+
function movedEngines(table, dropKey, putKey, entry) {
|
|
393
|
+
const out = {};
|
|
394
|
+
for (const k of Object.keys(table)) {
|
|
395
|
+
if (k === dropKey)
|
|
396
|
+
continue;
|
|
397
|
+
const slot = slotReadOf(table, k);
|
|
398
|
+
if (slot.presence !== 'present')
|
|
399
|
+
return undefined;
|
|
400
|
+
Object.defineProperty(out, k, { value: slot.value, writable: true, enumerable: true, configurable: true });
|
|
401
|
+
}
|
|
402
|
+
Object.defineProperty(out, putKey, { value: entry, writable: true, enumerable: true, configurable: true });
|
|
403
|
+
return out;
|
|
404
|
+
}
|
|
405
|
+
function repointStep(prior, from, to, fromNs, toNs, now) {
|
|
406
|
+
try {
|
|
407
|
+
const reading = readSessionEngine(prior);
|
|
408
|
+
if (reading.kind === 'none')
|
|
409
|
+
return { result: 'unaffected' };
|
|
410
|
+
if (reading.kind === 'unresolved' || prior === undefined)
|
|
411
|
+
return { result: 'unreadable' };
|
|
412
|
+
const table = enginesTableOf(prior);
|
|
413
|
+
if (reading.kind === 'bound') {
|
|
414
|
+
const id = reading.binding.identity;
|
|
415
|
+
if (id.identityKind !== 'address' || id.key !== from.key)
|
|
416
|
+
return { result: 'unaffected' };
|
|
417
|
+
if (table === 'absent' || table === 'unreadable')
|
|
418
|
+
return { result: 'unreadable' };
|
|
419
|
+
if (Object.hasOwn(table, to.key))
|
|
420
|
+
return { result: 'conflict' };
|
|
421
|
+
const entry = slotReadOf(table, from.key);
|
|
422
|
+
if (entry.presence !== 'present' || !isObj(entry.value))
|
|
423
|
+
return { result: 'unreadable' };
|
|
424
|
+
const engines = movedEngines(table, from.key, to.key, entry.value);
|
|
425
|
+
if (engines === undefined)
|
|
426
|
+
return { result: 'unreadable' };
|
|
427
|
+
return {
|
|
428
|
+
result: 'moved',
|
|
429
|
+
next: { ...prior, boundEngine: snapshotOf({ kind: reading.binding.kind, identity: to }), engines, updatedAt: now },
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (table === 'absent')
|
|
433
|
+
return { result: 'unaffected' };
|
|
434
|
+
if (table === 'unreadable')
|
|
435
|
+
return { result: 'unreadable' };
|
|
436
|
+
if (!Object.hasOwn(table, fromNs))
|
|
437
|
+
return { result: 'unaffected' };
|
|
438
|
+
if (Object.hasOwn(table, toNs))
|
|
439
|
+
return { result: 'conflict' };
|
|
440
|
+
const entry = slotReadOf(table, fromNs);
|
|
441
|
+
if (entry.presence !== 'present' || !isObj(entry.value))
|
|
442
|
+
return { result: 'unreadable' };
|
|
443
|
+
const engines = movedEngines(table, fromNs, toNs, entry.value);
|
|
444
|
+
if (engines === undefined)
|
|
445
|
+
return { result: 'unreadable' };
|
|
446
|
+
return { result: 'moved', next: { ...prior, engines, updatedAt: now } };
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
return { result: 'unreadable' };
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
export function repointSessionEngine(store, from, to) {
|
|
453
|
+
let readMergeWrite;
|
|
454
|
+
let fromB;
|
|
455
|
+
let toB;
|
|
456
|
+
try {
|
|
457
|
+
if (!isObj(store))
|
|
458
|
+
return 'request-invalid';
|
|
459
|
+
const rmw = methodOf(store, 'readMergeWrite');
|
|
460
|
+
if (rmw === undefined)
|
|
461
|
+
return 'request-invalid';
|
|
462
|
+
readMergeWrite = (build) => rmw.call(store, build);
|
|
463
|
+
const f = addressBindingOf(from);
|
|
464
|
+
const t = addressBindingOf(to);
|
|
465
|
+
if (f === undefined || t === undefined || f.key === t.key)
|
|
466
|
+
return 'request-invalid';
|
|
467
|
+
fromB = f;
|
|
468
|
+
toB = t;
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
return 'request-invalid';
|
|
472
|
+
}
|
|
473
|
+
const fromNs = engineNamespaceKeyFor(from);
|
|
474
|
+
const toNs = engineNamespaceKeyFor(to);
|
|
475
|
+
let step;
|
|
476
|
+
try {
|
|
477
|
+
const returned = readMergeWrite((prior) => {
|
|
478
|
+
step = repointStep(prior, fromB, toB, fromNs, toNs, new Date().toISOString());
|
|
479
|
+
return Object.hasOwn(step, 'next') ? step.next : undefined;
|
|
480
|
+
});
|
|
481
|
+
if (step === undefined)
|
|
482
|
+
return 'store-failed';
|
|
483
|
+
if (Object.hasOwn(step, 'next') && !isObj(returned))
|
|
484
|
+
return 'store-failed';
|
|
485
|
+
return step.result;
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
return 'store-failed';
|
|
489
|
+
}
|
|
490
|
+
}
|
|
380
491
|
const REFUSAL_KEYS = {
|
|
381
492
|
'not-wired': 'session.engine.dispatch.notWired',
|
|
382
493
|
'scope-mismatch': 'session.engine.dispatch.scopeMismatch',
|
|
@@ -9,7 +9,8 @@ export interface MemoryStatusClientLike {
|
|
|
9
9
|
} & SessionMemoryStatus>;
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
|
-
export type MemoryStatusFacts =
|
|
12
|
+
export type MemoryStatusFacts = SessionMemoryStatus & {
|
|
13
|
+
autoConsolidationArmed?: SessionMemoryStatusResponse['autoConsolidationArmed'];
|
|
13
14
|
readonly memorySync?: MemorySyncFacts;
|
|
14
15
|
};
|
|
15
16
|
export interface MemorySyncFacts {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import type { RowBitsOutcome } from '@sema-agent/sdk';
|
|
2
|
+
import { type UiLanguage } from './env/uiLanguage.js';
|
|
1
3
|
export declare const FILE_HISTORY_SKIPPED_NOTICE: string;
|
|
2
4
|
export declare function fileHistorySyncNotice(result: unknown): string | undefined;
|
|
3
5
|
export declare function fileHistorySyncNoticeIdentity(result: unknown): string | undefined;
|
|
4
6
|
export declare function isFileHistoryBlobMissing(err: unknown): boolean;
|
|
7
|
+
export type PushRowBitsWord = RowBitsOutcome | 'writer_side';
|
|
8
|
+
export declare function sessionPushRowBitsNotice(result: {} | null | undefined, lang?: UiLanguage | (string & {})): string | undefined;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NOT_FOUND_BLOB } from './engineErrorCodes.js';
|
|
2
2
|
import { effectiveWireErrorCode } from './wireErrorTriage.js';
|
|
3
3
|
import { readThrownSlot } from './wireFailureShape.js';
|
|
4
|
+
import { isUiLanguage } from './env/uiLanguage.js';
|
|
5
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
4
6
|
export const FILE_HISTORY_SKIPPED_NOTICE = 'File history was not copied: only the conversation was synced, because one of the two engines does not confirm that it can ' +
|
|
5
7
|
'transfer file history (the record /rewind uses to restore files). Syncing this session again will not add it until ' +
|
|
6
8
|
'the conversation has new turns and both engines can transfer file history.';
|
|
@@ -64,3 +66,29 @@ export function isFileHistoryBlobMissing(err) {
|
|
|
64
66
|
return false;
|
|
65
67
|
}
|
|
66
68
|
}
|
|
69
|
+
function pushRowBitsSpeaks(word) {
|
|
70
|
+
switch (word) {
|
|
71
|
+
case 'writer_side':
|
|
72
|
+
return true;
|
|
73
|
+
case 'mirrored':
|
|
74
|
+
case 'unsupported':
|
|
75
|
+
case 'absent':
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function isPushRowBitsWord(v) {
|
|
80
|
+
return v === 'mirrored' || v === 'unsupported' || v === 'absent' || v === 'writer_side';
|
|
81
|
+
}
|
|
82
|
+
export function sessionPushRowBitsNotice(result, lang) {
|
|
83
|
+
if (result === null || typeof result !== 'object')
|
|
84
|
+
return undefined;
|
|
85
|
+
try {
|
|
86
|
+
const word = getOwn(result, 'rowBits');
|
|
87
|
+
if (typeof word !== 'string' || !isPushRowBitsWord(word) || !pushRowBitsSpeaks(word))
|
|
88
|
+
return undefined;
|
|
89
|
+
return renderMessage(msg('session.sync.pushRowBitsWriterSide'), isUiLanguage(lang) ? lang : undefined);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
package/dist/sseIdleTriage.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type EnvLike } from './hostEnv.js';
|
|
2
|
+
import { SDK_STREAM_ENDED_REASONS } from './generated/sdkFactTables.js';
|
|
2
3
|
import { type RunNotFollowed } from './runFollow.js';
|
|
3
4
|
export declare const SSE_HEARTBEAT_GRACE_ENV = "SEMA_SSE_HEARTBEAT_GRACE_MS";
|
|
4
5
|
export declare const SSE_GRACE_MIN_MS = 5000;
|
|
@@ -8,8 +9,19 @@ export declare function resolveSseHeartbeatGraceMs(env?: EnvLike): number | unde
|
|
|
8
9
|
export declare function markEngineAliveIdle<E extends Error>(err: E): E;
|
|
9
10
|
export declare function engineAliveIdleElapsedMs(err: unknown): number | undefined;
|
|
10
11
|
export declare function isSseIdleError(err: unknown): boolean;
|
|
12
|
+
export type StreamEndedReasonWord = (typeof SDK_STREAM_ENDED_REASONS)[number];
|
|
13
|
+
export type StreamEndedUnknownWhy = 'not_this_class' | 'reason_unreadable' | 'reason_unrecognized';
|
|
14
|
+
export type StreamEndedReading = {
|
|
15
|
+
readonly kind: 'read';
|
|
16
|
+
readonly reason: StreamEndedReasonWord;
|
|
17
|
+
readonly cause?: {} | null;
|
|
18
|
+
} | {
|
|
19
|
+
readonly kind: 'unknown';
|
|
20
|
+
readonly why: StreamEndedUnknownWhy;
|
|
21
|
+
};
|
|
22
|
+
export declare function streamEndedReasonOf(err: {} | null | undefined): StreamEndedReading;
|
|
11
23
|
export declare function isStreamEndedWithoutTerminalError(err: {} | null | undefined): boolean;
|
|
12
|
-
export declare function probeEngineAlive(baseUrl: string
|
|
24
|
+
export declare function probeEngineAlive(baseUrl: string): Promise<boolean>;
|
|
13
25
|
export declare function diagnoseSseIdleTear<T>(inner: AsyncGenerator<T>, baseUrl: string, signal?: AbortSignal): AsyncGenerator<T>;
|
|
14
26
|
export declare function engineAliveIdleContent(elapsedMs: number, detach?: {
|
|
15
27
|
detached: true;
|
package/dist/sseIdleTriage.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { hostEnv } from './hostEnv.js';
|
|
2
2
|
import { SseIdleError, StreamEndedWithoutTerminalError, probeHealth as sdkProbeHealth } from '@sema-agent/sdk';
|
|
3
|
-
import { readThrownSlot, thrownIsInstanceOf } from './wireFailureShape.js';
|
|
3
|
+
import { THROWN_SLOT_UNREADABLE, readThrownSlot, thrownIsInstanceOf } from './wireFailureShape.js';
|
|
4
|
+
import { SDK_STREAM_ENDED_REASONS } from './generated/sdkFactTables.js';
|
|
4
5
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
5
6
|
import { runNotFollowedNoticeRef } from './runFollow.js';
|
|
6
7
|
export const SSE_HEARTBEAT_GRACE_ENV = 'SEMA_SSE_HEARTBEAT_GRACE_MS';
|
|
@@ -38,13 +39,30 @@ export function isSseIdleError(err) {
|
|
|
38
39
|
return true;
|
|
39
40
|
return readThrownSlot(err, 'name', 'data') === 'SseIdleError';
|
|
40
41
|
}
|
|
42
|
+
function streamEndedUnknown(why) {
|
|
43
|
+
return Object.freeze({ kind: 'unknown', why });
|
|
44
|
+
}
|
|
45
|
+
function isStreamEndedClass(err) {
|
|
46
|
+
return thrownIsInstanceOf(err, StreamEndedWithoutTerminalError) || readThrownSlot(err, 'name', 'data') === 'StreamEndedWithoutTerminalError';
|
|
47
|
+
}
|
|
48
|
+
export function streamEndedReasonOf(err) {
|
|
49
|
+
if (!isStreamEndedClass(err))
|
|
50
|
+
return streamEndedUnknown('not_this_class');
|
|
51
|
+
const raw = readThrownSlot(err, 'reason', 'data');
|
|
52
|
+
if (raw === THROWN_SLOT_UNREADABLE || raw === undefined)
|
|
53
|
+
return streamEndedUnknown('reason_unreadable');
|
|
54
|
+
const reason = SDK_STREAM_ENDED_REASONS.find((w) => w === raw);
|
|
55
|
+
if (reason === undefined)
|
|
56
|
+
return streamEndedUnknown('reason_unrecognized');
|
|
57
|
+
const cause = readThrownSlot(err, 'cause', 'data');
|
|
58
|
+
return Object.freeze(cause === THROWN_SLOT_UNREADABLE || cause === undefined ? { kind: 'read', reason } : { kind: 'read', reason, cause: cause });
|
|
59
|
+
}
|
|
41
60
|
export function isStreamEndedWithoutTerminalError(err) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return readThrownSlot(err, 'name', 'data') === 'StreamEndedWithoutTerminalError';
|
|
61
|
+
const reading = streamEndedReasonOf(err);
|
|
62
|
+
return reading.kind !== 'unknown' || reading.why !== 'not_this_class';
|
|
45
63
|
}
|
|
46
|
-
export async function probeEngineAlive(baseUrl
|
|
47
|
-
return (await sdkProbeHealth(baseUrl
|
|
64
|
+
export async function probeEngineAlive(baseUrl) {
|
|
65
|
+
return (await sdkProbeHealth(baseUrl)).alive;
|
|
48
66
|
}
|
|
49
67
|
export async function* diagnoseSseIdleTear(inner, baseUrl, signal) {
|
|
50
68
|
try {
|
|
@@ -7,6 +7,7 @@ import { resolveOwnerContext } from './engineSubagentResume.js';
|
|
|
7
7
|
import { coerceOutput, parentToolCallIdOf, publishSubagentContentEvent, settleSubagentContent, } from '../subagentContentStore.js';
|
|
8
8
|
import { noteBgOwnerAbsence } from './subagentOwnerAbsence.js';
|
|
9
9
|
import { readFrameTrueMark } from '../ownKey.js';
|
|
10
|
+
import { publishEngineInlineTaskModel } from '../engineInlineTaskStats.js';
|
|
10
11
|
function usableTailClient(client) {
|
|
11
12
|
return clientHasVerbs(client, [['capabilities'], ['runs', 'subagentStream']]);
|
|
12
13
|
}
|
|
@@ -149,6 +150,11 @@ export function tailEngineSubagent(taskId, opts) {
|
|
|
149
150
|
hostLog('debug', `[subagent-tail] ${taskId} settled (${String(d.status)}${typeof d.seq === 'number' ? ` seq=${d.seq}` : ''}${typeof d.summary === 'string' ? ` summary=${d.summary.slice(0, 80)}` : ''}) — close`);
|
|
150
151
|
break;
|
|
151
152
|
}
|
|
153
|
+
else if (t === 'task_progress' || t === 'task_started') {
|
|
154
|
+
const card = parentToolCallIdOf(taskId);
|
|
155
|
+
if (card !== undefined && card !== taskId && typeof d.model === 'string')
|
|
156
|
+
publishEngineInlineTaskModel(card, d.model);
|
|
157
|
+
}
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
catch (e) {
|
|
@@ -49,6 +49,18 @@ export declare function __resetSubagentContentStoreConfigForTests(): void;
|
|
|
49
49
|
export declare function bindSubagentIdentityReader(fn: (id: string) => readonly string[] | undefined): void;
|
|
50
50
|
export declare function registerSubagentContentAlias(parentToolCallId: string, taskId: string): void;
|
|
51
51
|
export declare function registerSubagentAlias(parentToolCallId: string, taskId: string): void;
|
|
52
|
+
export declare const SUBAGENT_ALIAS_SCOPES: readonly ["content", "full"];
|
|
53
|
+
export type SubagentAliasScope = (typeof SUBAGENT_ALIAS_SCOPES)[number];
|
|
54
|
+
export type SubagentAliasOutcome = 'new' | 'unchanged' | 'rejected';
|
|
55
|
+
export declare function applySubagentAlias(parentToolCallId: string, taskId: string, scope: SubagentAliasScope, seq?: number): SubagentAliasOutcome;
|
|
56
|
+
export interface SeatSubagentAlias {
|
|
57
|
+
readonly parentToolCallId: string;
|
|
58
|
+
readonly taskId: string;
|
|
59
|
+
readonly scope: SubagentAliasScope;
|
|
60
|
+
readonly seq?: number;
|
|
61
|
+
}
|
|
62
|
+
export declare function readSeatSubagentAlias(ev: object | null | undefined): SeatSubagentAlias | undefined;
|
|
63
|
+
export declare function noteSeatSubagentAlias(ev: object | null | undefined): 'registered' | 'ignored';
|
|
52
64
|
export declare function publishSubagentContentEvent(ev: SubagentContentEvent): void;
|
|
53
65
|
export declare function pushSubagentLocalEcho(taskId: string, text: string): void;
|
|
54
66
|
export interface SubagentContentSnapshot {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
2
|
-
import { readFrameTrueMark } from './ownKey.js';
|
|
2
|
+
import { readFrameTrueMark, readOwnDataNonEmptyString, readOwnDataValue } from './ownKey.js';
|
|
3
|
+
import { cycleSeqValue } from './cycleOrder.js';
|
|
3
4
|
import { toolEndOutputText } from './toolResultContent.js';
|
|
4
5
|
export function coerceOutput(v) {
|
|
5
6
|
return toolEndOutputText(v);
|
|
@@ -398,7 +399,7 @@ function scheduleNotify(taskId) {
|
|
|
398
399
|
}, NOTIFY_COALESCE_MS);
|
|
399
400
|
}
|
|
400
401
|
export function registerSubagentContentAlias(parentToolCallId, taskId) {
|
|
401
|
-
|
|
402
|
+
applySubagentAlias(parentToolCallId, taskId, 'content');
|
|
402
403
|
}
|
|
403
404
|
function aliasContentKey(parentToolCallId, taskId) {
|
|
404
405
|
if (!parentToolCallId || !taskId || parentToolCallId === taskId)
|
|
@@ -415,10 +416,72 @@ function aliasContentKey(parentToolCallId, taskId) {
|
|
|
415
416
|
return true;
|
|
416
417
|
}
|
|
417
418
|
export function registerSubagentAlias(parentToolCallId, taskId) {
|
|
419
|
+
applySubagentAlias(parentToolCallId, taskId, 'full');
|
|
420
|
+
}
|
|
421
|
+
export const SUBAGENT_ALIAS_SCOPES = ['content', 'full'];
|
|
422
|
+
export function applySubagentAlias(parentToolCallId, taskId, scope, seq) {
|
|
423
|
+
const hadContent = parentToTask.get(parentToolCallId) === taskId;
|
|
418
424
|
if (!aliasContentKey(parentToolCallId, taskId))
|
|
419
|
-
return;
|
|
420
|
-
|
|
421
|
-
|
|
425
|
+
return 'rejected';
|
|
426
|
+
let changed = !hadContent;
|
|
427
|
+
if (scope === 'full') {
|
|
428
|
+
const cycle = cycleSeqValue(seq);
|
|
429
|
+
const cur = taskToParent.get(taskId);
|
|
430
|
+
if (cur?.card !== parentToolCallId) {
|
|
431
|
+
const stale = cur !== undefined && cycle !== undefined && cur.seq !== undefined && cycle < cur.seq;
|
|
432
|
+
if (!stale) {
|
|
433
|
+
taskToParent.set(taskId, { card: parentToolCallId, stamp: ++parentStampSeq, ...(cycle !== undefined ? { seq: cycle } : {}) });
|
|
434
|
+
changed = true;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
else if (cycle !== undefined && (cur.seq === undefined || cycle > cur.seq)) {
|
|
438
|
+
taskToParent.set(taskId, { card: cur.card, stamp: cur.stamp, seq: cycle });
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return changed ? 'new' : 'unchanged';
|
|
442
|
+
}
|
|
443
|
+
export function readSeatSubagentAlias(ev) {
|
|
444
|
+
try {
|
|
445
|
+
if (typeof ev !== 'object' || ev === null)
|
|
446
|
+
return undefined;
|
|
447
|
+
if (readOwnDataValue(ev, 'kind') !== 'subagent_alias')
|
|
448
|
+
return undefined;
|
|
449
|
+
const parentToolCallId = readOwnDataNonEmptyString(ev, 'parentToolCallId');
|
|
450
|
+
const taskId = readOwnDataNonEmptyString(ev, 'taskId');
|
|
451
|
+
const scope = readOwnDataNonEmptyString(ev, 'scope');
|
|
452
|
+
if (parentToolCallId === undefined || taskId === undefined || scope === undefined)
|
|
453
|
+
return undefined;
|
|
454
|
+
if (!SUBAGENT_ALIAS_SCOPES.includes(scope))
|
|
455
|
+
return undefined;
|
|
456
|
+
const proof = readOwnDataValue(ev, 'laneProof');
|
|
457
|
+
if (typeof proof !== 'object' || proof === null)
|
|
458
|
+
return undefined;
|
|
459
|
+
if (readOwnDataValue(proof, 'lane') !== 'subagent')
|
|
460
|
+
return undefined;
|
|
461
|
+
if (readOwnDataNonEmptyString(proof, 'parentToolCallId') !== parentToolCallId)
|
|
462
|
+
return undefined;
|
|
463
|
+
const seqDesc = Object.getOwnPropertyDescriptor(ev, 'seq');
|
|
464
|
+
let seq;
|
|
465
|
+
if (seqDesc !== undefined) {
|
|
466
|
+
if (!Object.hasOwn(seqDesc, 'value'))
|
|
467
|
+
return undefined;
|
|
468
|
+
if (seqDesc.value !== undefined) {
|
|
469
|
+
seq = cycleSeqValue(seqDesc.value);
|
|
470
|
+
if (seq === undefined)
|
|
471
|
+
return undefined;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return { parentToolCallId, taskId, scope: scope, ...(seq !== undefined ? { seq } : {}) };
|
|
475
|
+
}
|
|
476
|
+
catch {
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
export function noteSeatSubagentAlias(ev) {
|
|
481
|
+
const alias = readSeatSubagentAlias(ev);
|
|
482
|
+
if (alias === undefined)
|
|
483
|
+
return 'ignored';
|
|
484
|
+
return applySubagentAlias(alias.parentToolCallId, alias.taskId, alias.scope, alias.seq) === 'new' ? 'registered' : 'ignored';
|
|
422
485
|
}
|
|
423
486
|
function replaySeen(s, ev) {
|
|
424
487
|
const id = ev.eventId;
|
|
@@ -661,18 +724,16 @@ export function planSubagentViewSlots(taskId) {
|
|
|
661
724
|
export function parentToolCallIdOf(taskId) {
|
|
662
725
|
const ids = sameSubagentIds(taskId);
|
|
663
726
|
let stated;
|
|
664
|
-
let statedStamp = -1;
|
|
665
727
|
for (const id of ids) {
|
|
666
728
|
const hit = taskToParent.get(id);
|
|
667
729
|
if (hit === undefined)
|
|
668
730
|
continue;
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
}
|
|
731
|
+
const newer = hit.seq !== undefined && stated?.seq !== undefined && hit.seq !== stated.seq ? hit.seq > stated.seq : hit.stamp > (stated?.stamp ?? -1);
|
|
732
|
+
if (stated === undefined || newer)
|
|
733
|
+
stated = hit;
|
|
673
734
|
}
|
|
674
735
|
if (stated !== undefined)
|
|
675
|
-
return stated;
|
|
736
|
+
return stated.card;
|
|
676
737
|
for (const id of ids) {
|
|
677
738
|
const fromContent = tasks.get(id)?.parentToolCallId;
|
|
678
739
|
if (fromContent !== undefined)
|
|
@@ -26,6 +26,7 @@ export type CoreSemaTaskTerminalStatus = (typeof CORE_SEMA_TASK_TERMINAL_STATUSE
|
|
|
26
26
|
export declare function isCoreSemaTaskTerminal(status: unknown): status is CoreSemaTaskTerminalStatus;
|
|
27
27
|
export declare const CORE_WORKFLOW_RUN_TERMINAL_STATUSES: readonly ["completed", "failed"];
|
|
28
28
|
export declare function isCoreWorkflowRunTerminal(status: unknown): status is (typeof CORE_WORKFLOW_RUN_TERMINAL_STATUSES)[number];
|
|
29
|
+
export declare function isCoreWorkflowRunParkedEnd(status: unknown, errorCode: unknown): boolean;
|
|
29
30
|
export declare const CORE_TASK_PROGRESS_TERMINAL_STATUSES: readonly ["completed", "failed"];
|
|
30
31
|
export declare function isCoreTaskProgressTerminal(status: unknown): status is (typeof CORE_TASK_PROGRESS_TERMINAL_STATUSES)[number];
|
|
31
32
|
export declare function isCoreTaskProgressTerminalNotSuccess(status: unknown): status is 'failed';
|
package/dist/terminalStatuses.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CORE_TERMINAL_CAUSE_KINDS, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES as GENERATED_TASK_NOTIFICATION_TERMINAL_STATUSES } from './generated/engineFactTables.js';
|
|
1
|
+
import { CORE_TERMINAL_CAUSE_KINDS, CORE_TASK_NOTIFICATION_TERMINAL_STATUSES as GENERATED_TASK_NOTIFICATION_TERMINAL_STATUSES, CORE_WORKFLOW_AGENT_PARKED_ERROR_CODE, } from './generated/engineFactTables.js';
|
|
2
2
|
function memberOf(table, word) {
|
|
3
3
|
return typeof word === 'string' && table.includes(word);
|
|
4
4
|
}
|
|
@@ -53,6 +53,9 @@ export const CORE_WORKFLOW_RUN_TERMINAL_STATUSES = Object.freeze(['completed', '
|
|
|
53
53
|
export function isCoreWorkflowRunTerminal(status) {
|
|
54
54
|
return memberOf(CORE_WORKFLOW_RUN_TERMINAL_STATUSES, status);
|
|
55
55
|
}
|
|
56
|
+
export function isCoreWorkflowRunParkedEnd(status, errorCode) {
|
|
57
|
+
return status === 'failed' && errorCode === CORE_WORKFLOW_AGENT_PARKED_ERROR_CODE;
|
|
58
|
+
}
|
|
56
59
|
export const CORE_TASK_PROGRESS_TERMINAL_STATUSES = Object.freeze(['completed', 'failed']);
|
|
57
60
|
export function isCoreTaskProgressTerminal(status) {
|
|
58
61
|
return memberOf(CORE_TASK_PROGRESS_TERMINAL_STATUSES, status);
|
package/dist/toolResult.js
CHANGED
|
@@ -3,7 +3,7 @@ import { markEngineWorkflowNotified, registerOutstandingBgTask, registerOutstand
|
|
|
3
3
|
import { parseWorkflowPollEnvelope, projectWorkflowTaskOutput } from './workflow.js';
|
|
4
4
|
import { asModelFallbackReason } from './engineErrorCodes.js';
|
|
5
5
|
import { frozenSet } from './frozenSet.js';
|
|
6
|
-
import { bashExitOf, bashExitReadingFailed } from './bashExitReading.js';
|
|
6
|
+
import { bashCurtailedResultPart, bashCurtailmentOf, bashCurtailmentSentence, bashExitOf, bashExitReadingFailed } from './bashExitReading.js';
|
|
7
7
|
import { guardedRead, ownDataField, ownSnapshotWhenTyped, readFrameTrueMark, readFrameTrueMarkReading, readOwnDataFiniteNumber, readOwnDataNonEmptyString, readOwnDataValue, toolResultBlockOf, } from './ownKey.js';
|
|
8
8
|
import { displayUntrusted } from './displayUntrusted.js';
|
|
9
9
|
import { isCoreSemaTaskTerminal } from './terminalStatuses.js';
|
|
@@ -370,6 +370,7 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
|
|
|
370
370
|
let parsedMemo;
|
|
371
371
|
const parseOnce = () => (parsedMemo === undefined ? (parsedMemo = parseModelFacingBash(text)) : parsedMemo);
|
|
372
372
|
const exit = bashExitOf(structured, parseOnce);
|
|
373
|
+
const cut = bashCurtailmentOf(structured);
|
|
373
374
|
const structuredSlots = sType === 'bash' && (typeof s?.stdout === 'string' || typeof s?.stderr === 'string');
|
|
374
375
|
const textSlots = structuredSlots ? null : parseOnce();
|
|
375
376
|
const slots = structuredSlots
|
|
@@ -392,26 +393,37 @@ export function wireOutputToBody(toolName, output, isError, truncated, flatten,
|
|
|
392
393
|
}
|
|
393
394
|
if (body.trim() === '' && text.trim() !== '')
|
|
394
395
|
body = text;
|
|
396
|
+
else if (cut !== undefined) {
|
|
397
|
+
if (body.trim() === '')
|
|
398
|
+
body = bashCurtailmentSentence(cut);
|
|
399
|
+
else if (reason.trim() !== '')
|
|
400
|
+
body = `${bashCurtailmentSentence(cut)}\n${body}`;
|
|
401
|
+
}
|
|
395
402
|
return { content: truncated ? `${body}\n…(truncated)` : body, isError: true };
|
|
396
403
|
}
|
|
397
404
|
const stdout = truncated ? `${slots.stdout}\n…(truncated)` : slots.stdout;
|
|
398
405
|
const processedStdout = stdout.replace(/^(\s*\n)+/, '').trimEnd();
|
|
399
406
|
return {
|
|
400
|
-
content: [processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
|
|
407
|
+
content: [cut !== undefined ? bashCurtailmentSentence(cut) : '', processedStdout, slots.stderr.trim()].filter(Boolean).join('\n'),
|
|
401
408
|
isError: false,
|
|
402
409
|
toolUseResult: {
|
|
403
410
|
stdout,
|
|
404
|
-
|
|
411
|
+
...bashCurtailedResultPart(slots.stderr, cut),
|
|
405
412
|
interrupted: false,
|
|
406
413
|
...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
|
|
407
414
|
},
|
|
408
415
|
};
|
|
409
416
|
}
|
|
410
417
|
const stdout = truncated ? `${text}\n…(truncated)` : text;
|
|
418
|
+
const cutSentence = cut !== undefined ? bashCurtailmentSentence(cut) : undefined;
|
|
411
419
|
if (isError || bashExitReadingFailed(exit)) {
|
|
420
|
+
if (cutSentence !== undefined && text.trim() === '' && exit.exitCode !== 137) {
|
|
421
|
+
return { content: truncated ? `${cutSentence}\n…(truncated)` : cutSentence, isError: true };
|
|
422
|
+
}
|
|
412
423
|
return { content: exit.exitCode === 137 ? `${stdout}\n${killedBySignalSentence(killCauseOf)}` : stdout, isError: true };
|
|
413
424
|
}
|
|
414
|
-
|
|
425
|
+
const okContent = cutSentence === undefined ? stdout : text.trim() === '' ? (truncated ? `${cutSentence}\n…(truncated)` : cutSentence) : `${cutSentence}\n${stdout}`;
|
|
426
|
+
return { content: okContent, isError, toolUseResult: { stdout, ...bashCurtailedResultPart('', cut), interrupted: false } };
|
|
415
427
|
}
|
|
416
428
|
if (name === 'taskoutput' || name === 'task_output') {
|
|
417
429
|
const body = truncated ? `${text}\n…(truncated)` : text;
|
|
@@ -498,10 +510,11 @@ export function structuredToToolUseResult(structured, modelText, leaderLedger =
|
|
|
498
510
|
return null;
|
|
499
511
|
const exit = bashExitOf(structured, () => null);
|
|
500
512
|
const benignInterp = exit.benignNote;
|
|
513
|
+
const cut = bashCurtailmentOf(structured);
|
|
501
514
|
return {
|
|
502
515
|
toolUseResult: {
|
|
503
516
|
stdout: typeof s.stdout === 'string' ? s.stdout : '',
|
|
504
|
-
|
|
517
|
+
...bashCurtailedResultPart(typeof s.stderr === 'string' ? s.stderr : '', cut),
|
|
505
518
|
interrupted: false,
|
|
506
519
|
...(benignInterp !== undefined ? { returnCodeInterpretation: benignInterp } : {}),
|
|
507
520
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
2
2
|
import { classifyTurnWireError, isPreStreamDrainingReject } from './wireErrorTriage.js';
|
|
3
|
-
import { isSseIdleError } from './sseIdleTriage.js';
|
|
3
|
+
import { isSseIdleError, streamEndedReasonOf } from './sseIdleTriage.js';
|
|
4
4
|
import { runNotFollowedOf } from './runFollow.js';
|
|
5
5
|
import { isCodeClassifiedGateFailure } from './gateFailureCodes.js';
|
|
6
6
|
import { CORRUPT_ROW_ERROR_CODE, CORRUPT_SESSION_ERROR_CODE, MEMORY_CONTROL_PLANE_CORRUPT, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
|
|
@@ -36,6 +36,13 @@ const TURN_FAILURE_HEADLINE_KEYS = Object.freeze({
|
|
|
36
36
|
internal: 'notice.failure.headline.internal',
|
|
37
37
|
cause_unreadable: 'notice.failure.headline.causeUnreadable',
|
|
38
38
|
});
|
|
39
|
+
const STREAM_ENDED_HEADLINE_KEYS = Object.freeze({
|
|
40
|
+
empty_legs: 'notice.streamEnded.emptyLegs.headline',
|
|
41
|
+
consecutive_failures: 'notice.streamEnded.consecutiveFailures.headline',
|
|
42
|
+
});
|
|
43
|
+
function parkedHeadlineKeyOf(reading) {
|
|
44
|
+
return reading.kind === 'read' ? STREAM_ENDED_HEADLINE_KEYS[reading.reason] : TURN_FAILURE_HEADLINE_KEYS.parked;
|
|
45
|
+
}
|
|
39
46
|
function waitSecOf(err) {
|
|
40
47
|
const ms = readThrownSlot(err, 'retryAfterMs', 'data');
|
|
41
48
|
if (typeof ms === 'number' && Number.isFinite(ms) && ms > 0)
|
|
@@ -128,7 +135,7 @@ export function turnFailurePresentation(err, evidence, notesCtx, lang) {
|
|
|
128
135
|
}
|
|
129
136
|
else if (verdict.kind === 'stream-ended-without-terminal') {
|
|
130
137
|
shape = { category: 'parked', offer: false };
|
|
131
|
-
headlineKey =
|
|
138
|
+
headlineKey = parkedHeadlineKeyOf(streamEndedReasonOf(err));
|
|
132
139
|
detail = wireFailureTextsOf(err).reason;
|
|
133
140
|
}
|
|
134
141
|
else if (verdict.kind === 'transport') {
|
package/dist/typePins.d.ts
CHANGED
|
@@ -8,4 +8,15 @@ type WritableKeys<T> = {
|
|
|
8
8
|
}, P, never>;
|
|
9
9
|
}[keyof T];
|
|
10
10
|
export type AllReadonly<T> = [WritableKeys<T>] extends [never] ? true : false;
|
|
11
|
+
export type Same<A, B> = [Exclude<A, B>, Exclude<B, A>] extends [never, never] ? true : false;
|
|
12
|
+
export type KeysEq<A, B> = Same<keyof A, keyof B>;
|
|
13
|
+
export type Fits<A, B> = [A] extends [B] ? true : false;
|
|
14
|
+
export type Present<T> = [T] extends [never] ? false : true;
|
|
15
|
+
export type RequiredKeys<T> = {
|
|
16
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? never : K;
|
|
17
|
+
}[keyof T];
|
|
18
|
+
export type NeverValuedKeys<T> = {
|
|
19
|
+
[K in keyof T]-?: [Exclude<T[K], undefined>] extends [never] ? K : never;
|
|
20
|
+
}[keyof T];
|
|
21
|
+
export type NoNeverValues<T> = Same<NeverValuedKeys<T>, never>;
|
|
11
22
|
export {};
|
package/dist/usageAnalytics.d.ts
CHANGED
|
@@ -144,3 +144,20 @@ export declare function projectUsageAnalytics(inputs: UsageAnalyticsInputs, wind
|
|
|
144
144
|
export declare function readUsageAnalytics(client: UsageAnalyticsClientLike, window: UsageAnalyticsWindow, opts?: {
|
|
145
145
|
signal?: AbortSignal;
|
|
146
146
|
}): Promise<UsageAnalyticsView>;
|
|
147
|
+
export declare const CENTER_USAGE_COST_UNKNOWN_WHYS: readonly ["declared_unknown", "basis_unrecognized", "estimated_zero", "amount_absent"];
|
|
148
|
+
export type CenterUsageCostUnknownWhy = (typeof CENTER_USAGE_COST_UNKNOWN_WHYS)[number];
|
|
149
|
+
export interface CenterUsageCostAmount {
|
|
150
|
+
readonly value: number;
|
|
151
|
+
readonly bound: Extract<UsageBound, 'exact' | 'lower'>;
|
|
152
|
+
}
|
|
153
|
+
export interface CenterUsageCostAmountReading {
|
|
154
|
+
readonly state: 'amount';
|
|
155
|
+
readonly amount: CenterUsageCostAmount;
|
|
156
|
+
readonly unpriced: boolean;
|
|
157
|
+
}
|
|
158
|
+
export interface CenterUsageCostUnknownReading {
|
|
159
|
+
readonly state: 'unknown';
|
|
160
|
+
readonly why: CenterUsageCostUnknownWhy;
|
|
161
|
+
}
|
|
162
|
+
export type CenterUsageCostReading = CenterUsageCostAmountReading | CenterUsageCostUnknownReading;
|
|
163
|
+
export declare function centerUsageCostOf(body: object | null | undefined): CenterUsageCostReading;
|
package/dist/usageAnalytics.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readThrownSlot, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
|
|
1
|
+
import { readThrownSlot, slotReadOf, THROWN_SLOT_UNREADABLE } from './wireFailureShape.js';
|
|
2
2
|
export const USAGE_SENTENCES = Object.freeze({
|
|
3
3
|
analyticsUnavailable: 'Usage analytics aren’t available on this backend.',
|
|
4
4
|
analyticsUnread: 'Usage analytics couldn’t be read just now.',
|
|
@@ -161,6 +161,9 @@ export function readUsageBreakdown(client, opts = {}) {
|
|
|
161
161
|
export function usageBoundPrefix(bound) {
|
|
162
162
|
return bound === 'lower' ? '≥' : bound === 'approximate' ? '≈' : '';
|
|
163
163
|
}
|
|
164
|
+
function costBoundOf(precision, truncated) {
|
|
165
|
+
return precision === 'exact' && !truncated ? 'exact' : 'lower';
|
|
166
|
+
}
|
|
164
167
|
const DAY_MS = 86_400_000;
|
|
165
168
|
export const USAGE_HEATMAP_MAX_DAYS = 70;
|
|
166
169
|
export function usageWindowOfRange(range, now) {
|
|
@@ -275,7 +278,7 @@ export function projectUsageAnalytics(inputs, window) {
|
|
|
275
278
|
readings.tokens = { value: sv.tokensIn + sv.tokensOut, bound: !exact ? 'approximate' : sv.truncated ? 'lower' : 'exact' };
|
|
276
279
|
}
|
|
277
280
|
if (sv.cost !== undefined)
|
|
278
|
-
readings.cost = { value: sv.cost, bound:
|
|
281
|
+
readings.cost = { value: sv.cost, bound: costBoundOf(sv.precision, sv.truncated) };
|
|
279
282
|
const day = inputs.daySeries;
|
|
280
283
|
if (day.kind === 'ok' && isWhole(day.value)) {
|
|
281
284
|
const dayValues = new Map();
|
|
@@ -328,3 +331,42 @@ export async function readUsageAnalytics(client, window, opts = {}) {
|
|
|
328
331
|
]);
|
|
329
332
|
return projectUsageAnalytics({ summary, daySeries, hourSeries, modelBreakdown }, window);
|
|
330
333
|
}
|
|
334
|
+
const CENTER_COST_BASIS_WORDS = ['exact', 'lowerBound', 'unknown'];
|
|
335
|
+
export const CENTER_USAGE_COST_UNKNOWN_WHYS = Object.freeze(['declared_unknown', 'basis_unrecognized', 'estimated_zero', 'amount_absent']);
|
|
336
|
+
const unknownCost = (why) => ({ state: 'unknown', why });
|
|
337
|
+
const amountCost = (value, bound, unpriced) => ({ state: 'amount', amount: { value, bound }, unpriced });
|
|
338
|
+
const flagNotRuledOut = (r) => r.value === true || r.presence === 'unreadable';
|
|
339
|
+
export function centerUsageCostOf(body) {
|
|
340
|
+
try {
|
|
341
|
+
if (!isRecord(body))
|
|
342
|
+
return unknownCost('amount_absent');
|
|
343
|
+
const basis = slotReadOf(body, 'costBasis');
|
|
344
|
+
let word;
|
|
345
|
+
if (basis.presence === 'present') {
|
|
346
|
+
word = CENTER_COST_BASIS_WORDS.find((w) => w === basis.value);
|
|
347
|
+
if (word === undefined)
|
|
348
|
+
return unknownCost('basis_unrecognized');
|
|
349
|
+
}
|
|
350
|
+
else if (basis.presence === 'unreadable') {
|
|
351
|
+
return unknownCost('basis_unrecognized');
|
|
352
|
+
}
|
|
353
|
+
if (word === 'unknown')
|
|
354
|
+
return unknownCost('declared_unknown');
|
|
355
|
+
const cost = slotReadOf(body, 'costUsd').value;
|
|
356
|
+
if (!nonNeg(cost))
|
|
357
|
+
return unknownCost('amount_absent');
|
|
358
|
+
const est = slotReadOf(body, 'estimated');
|
|
359
|
+
const trunc = slotReadOf(body, 'truncated');
|
|
360
|
+
const unpriced = est.value === true;
|
|
361
|
+
if (word === 'lowerBound')
|
|
362
|
+
return amountCost(cost, 'lower', unpriced);
|
|
363
|
+
if (word === 'exact')
|
|
364
|
+
return flagNotRuledOut(est) || flagNotRuledOut(trunc) ? amountCost(cost, 'lower', unpriced) : amountCost(cost, 'exact', false);
|
|
365
|
+
if (unpriced && cost === 0)
|
|
366
|
+
return unknownCost('estimated_zero');
|
|
367
|
+
return amountCost(cost, costBoundOf(precisionOf(est.value), flagNotRuledOut(trunc)), unpriced);
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
return unknownCost('amount_absent');
|
|
371
|
+
}
|
|
372
|
+
}
|