@sema-agent/client-core 0.83.6 → 0.84.1
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 +176 -0
- package/README.md +20 -13
- package/dist/abortableSleep.d.ts +10 -0
- package/dist/abortableSleep.js +37 -0
- package/dist/adapt/wireShapes.js +3 -2
- package/dist/adapter/activeRunSelfHeal.js +7 -7
- package/dist/adapter/downstream/eventToSdkMessage.js +6 -2
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +1 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +10 -5
- package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
- package/dist/adapter/downstream/wiringManifestView.js +1 -0
- package/dist/agentSession/engineAgentRegistryRead.d.ts +18 -0
- package/dist/agentSession/engineAgentRegistryRead.js +167 -0
- package/dist/agentsWireCaps.js +10 -1
- package/dist/attachmentsWireCaps.js +2 -2
- package/dist/controlRouter.js +1 -1
- package/dist/decideFailureNote.d.ts +2 -1
- package/dist/decideFailureNote.js +5 -3
- package/dist/detachWire.d.ts +1 -0
- package/dist/detachWire.js +13 -5
- package/dist/displayUntrusted.js +114 -18
- package/dist/engineAgentAbsence.d.ts +37 -0
- package/dist/engineAgentAbsence.js +142 -0
- package/dist/engineErrorCodes.d.ts +2 -0
- package/dist/engineErrorCodes.js +9 -5
- package/dist/engineNoticeCodes.d.ts +43 -0
- package/dist/engineNoticeCodes.js +118 -5
- package/dist/engineWireSdk.d.ts +2 -0
- package/dist/fleet/fleetProjection.js +3 -2
- package/dist/frozenSet.d.ts +1 -0
- package/dist/frozenSet.js +20 -0
- package/dist/handsSeam.d.ts +3 -0
- package/dist/handsSeam.js +19 -0
- package/dist/hitl/askGateWire.d.ts +1 -1
- package/dist/hitl/askGateWire.js +1 -1
- package/dist/hitl/hitlHostSurface.js +1 -1
- package/dist/hitl/parkResolver.d.ts +1 -0
- package/dist/hitl/parkResolver.js +9 -3
- package/dist/hitl/planReviewWire.d.ts +30 -3
- package/dist/hitl/planReviewWire.js +139 -32
- package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
- package/dist/hitl/sessionPolicyDeliverable.js +14 -3
- package/dist/hitl/sessionPolicyWire.d.ts +40 -0
- package/dist/hitl/sessionPolicyWire.js +210 -0
- package/dist/hitl/toolApprovalWire.js +2 -2
- package/dist/index.d.ts +24 -13
- package/dist/index.js +13 -13
- package/dist/liveInitToolFace.js +28 -10
- package/dist/model/catalogLoader.js +3 -3
- package/dist/model/tierVocabulary.js +1 -1
- package/dist/request/taskRequest.js +15 -5
- package/dist/resumeRefusalCopy.d.ts +11 -0
- package/dist/resumeRefusalCopy.js +39 -1
- package/dist/rewindWireCaps.d.ts +0 -1
- package/dist/seam.d.ts +2 -1
- package/dist/seatContract.js +2 -2
- package/dist/systemReminderTag.d.ts +5 -0
- package/dist/systemReminderTag.js +20 -9
- package/dist/toolResult.js +2 -6
- package/dist/toolRoster.d.ts +16 -0
- package/dist/toolRoster.js +46 -5
- package/dist/wireErrorTriage.js +1 -11
- package/dist/workflowClient.js +4 -3
- package/dist/workflowMonitor.d.ts +1 -1
- package/docs/INTEGRATION-CLIENTS.md +701 -37
- package/package.json +3 -3
|
@@ -3,14 +3,16 @@ import { stamp, snapshotSegmentIdentity, } from '../types.js';
|
|
|
3
3
|
import { turnUsageToModelUsage } from './turnUsageToModelUsage.js';
|
|
4
4
|
import { ccToolDenialKindForToolEnd, gateOutcomeOf } from '../../gateOutcome.js';
|
|
5
5
|
import { projectToolRoster, projectToolRosterDelta } from '../../toolRoster.js';
|
|
6
|
+
import { projectHandsSection } from '../../handsSeam.js';
|
|
6
7
|
import { readMcpLiveness } from '../../mcpLiveness.js';
|
|
7
8
|
import { SEGMENT_END_IDENTITY_KEYS } from '../types.js';
|
|
9
|
+
import { frozenSet } from '../../frozenSet.js';
|
|
8
10
|
function armBody(body) {
|
|
9
11
|
return body;
|
|
10
12
|
}
|
|
11
13
|
const SUGGESTION_BATCH_CAP = 8;
|
|
12
14
|
const SUGGESTION_CHARS_CAP = 200;
|
|
13
|
-
export const INTERNAL_SDK_ARM_TYPES =
|
|
15
|
+
export const INTERNAL_SDK_ARM_TYPES = frozenSet([
|
|
14
16
|
'tool_disclosure',
|
|
15
17
|
'tool_progress',
|
|
16
18
|
'tool_roster_delta',
|
|
@@ -546,7 +548,8 @@ function wiringManifestSupersetBody(ev) {
|
|
|
546
548
|
const writeProtection = projectWriteProtectionSection(ev.writeProtection);
|
|
547
549
|
const autoConsolidation = projectAutoConsolidationSection(ev.autoConsolidation);
|
|
548
550
|
const readDeny = projectReadDenySection(ev.readDeny);
|
|
549
|
-
|
|
551
|
+
const hands = projectHandsSection(ev);
|
|
552
|
+
if (modelGate === undefined && autoMode === undefined && mcp === undefined && tools === undefined && hooks === undefined && lsp === undefined && writeProtection === undefined && autoConsolidation === undefined && readDeny === undefined && hands === undefined)
|
|
550
553
|
return undefined;
|
|
551
554
|
return {
|
|
552
555
|
...(modelGate !== undefined ? { _sema_modelGate: modelGate } : {}),
|
|
@@ -558,6 +561,7 @@ function wiringManifestSupersetBody(ev) {
|
|
|
558
561
|
...(writeProtection !== undefined ? { _sema_writeProtection: writeProtection } : {}),
|
|
559
562
|
...(autoConsolidation !== undefined ? { _sema_autoConsolidation: autoConsolidation } : {}),
|
|
560
563
|
...(readDeny !== undefined ? { _sema_readDeny: readDeny } : {}),
|
|
564
|
+
...(hands !== undefined ? { _sema_hands: hands } : {}),
|
|
561
565
|
};
|
|
562
566
|
}
|
|
563
567
|
function projectWriteProtectionSection(raw) {
|
|
@@ -30,6 +30,7 @@ export interface SemaPermissionDenial {
|
|
|
30
30
|
readonly tool_use_id?: string;
|
|
31
31
|
readonly tool_input?: Record<string, unknown>;
|
|
32
32
|
readonly _sema_tool_input_source?: 'tool_start';
|
|
33
|
+
readonly _sema_tool_input_redacted?: true;
|
|
33
34
|
readonly _sema_tool_arg?: string;
|
|
34
35
|
readonly deniedBy?: DeniedBy;
|
|
35
36
|
readonly _sema_denied_by_source?: 'tool_end';
|
|
@@ -40,14 +40,15 @@ function joinableToolInput(args) {
|
|
|
40
40
|
if (args === null || typeof args !== 'object' || Array.isArray(args))
|
|
41
41
|
return undefined;
|
|
42
42
|
let nodes = 0;
|
|
43
|
+
let transportRedacted = false;
|
|
43
44
|
const stack = [{ v: args, depth: 0 }];
|
|
44
45
|
while (stack.length > 0) {
|
|
45
46
|
const { v, depth } = stack.pop();
|
|
46
47
|
if (++nodes > TOOL_INPUT_SCAN_MAX_NODES || depth > TOOL_INPUT_SCAN_MAX_DEPTH)
|
|
47
48
|
return undefined;
|
|
48
49
|
if (typeof v === 'string') {
|
|
49
|
-
if (v.includes(REDACTION_MARKER_PREFIX) || isTransportPlaceholderLeaf(v))
|
|
50
|
-
|
|
50
|
+
if (!transportRedacted && (v.includes(REDACTION_MARKER_PREFIX) || isTransportPlaceholderLeaf(v)))
|
|
51
|
+
transportRedacted = true;
|
|
51
52
|
continue;
|
|
52
53
|
}
|
|
53
54
|
if (v === null || typeof v !== 'object')
|
|
@@ -56,7 +57,7 @@ function joinableToolInput(args) {
|
|
|
56
57
|
for (const c of children)
|
|
57
58
|
stack.push({ v: c, depth: depth + 1 });
|
|
58
59
|
}
|
|
59
|
-
return args;
|
|
60
|
+
return { input: args, transportRedacted };
|
|
60
61
|
}
|
|
61
62
|
const GATE_DENIED_DECISIONS = new Set(['deny']);
|
|
62
63
|
const GATE_NON_DENIAL_DECISIONS = new Set(['allow', 'approve', 'edit', 'reject']);
|
|
@@ -92,9 +93,10 @@ function permissionDenialParts(stats, observed) {
|
|
|
92
93
|
const ledgerInput = rawInput !== null && typeof rawInput === 'object' && !Array.isArray(rawInput)
|
|
93
94
|
? rawInput
|
|
94
95
|
: undefined;
|
|
95
|
-
const
|
|
96
|
+
const joined = ledgerInput === undefined && toolUseId !== undefined && toolInputByCallId?.has(toolUseId) === true
|
|
96
97
|
? joinableToolInput(toolInputByCallId.get(toolUseId))
|
|
97
98
|
: undefined;
|
|
99
|
+
const joinedInput = joined?.input;
|
|
98
100
|
const toolInput = ledgerInput ?? joinedInput;
|
|
99
101
|
const ledgerDeniedByRaw = row.deniedBy;
|
|
100
102
|
const ledgerDeniedBy = typeof ledgerDeniedByRaw === 'string' && isGateDeniedByWord(ledgerDeniedByRaw)
|
|
@@ -116,6 +118,7 @@ function permissionDenialParts(stats, observed) {
|
|
|
116
118
|
...(toolUseId !== undefined ? { tool_use_id: toolUseId } : {}),
|
|
117
119
|
...(toolInput !== undefined ? { tool_input: toolInput } : {}),
|
|
118
120
|
...(joinedInput !== undefined ? { _sema_tool_input_source: 'tool_start' } : {}),
|
|
121
|
+
...(joined?.transportRedacted === true ? { _sema_tool_input_redacted: true } : {}),
|
|
119
122
|
...(deniedBy !== undefined ? { deniedBy } : {}),
|
|
120
123
|
...(joinedDeniedBy !== undefined && ledgerDeniedBy === undefined
|
|
121
124
|
? { _sema_denied_by_source: 'tool_end' }
|
|
@@ -145,7 +148,8 @@ function permissionDenialParts(stats, observed) {
|
|
|
145
148
|
continue;
|
|
146
149
|
}
|
|
147
150
|
const toolName = nonEmptyStr(toolNameRaw);
|
|
148
|
-
const
|
|
151
|
+
const joined = toolInputByCallId?.has(callId) === true ? joinableToolInput(toolInputByCallId.get(callId)) : undefined;
|
|
152
|
+
const joinedInput = joined?.input;
|
|
149
153
|
const deniedByRaw = gateDeniedByByCallId?.has(callId) === true ? gateDeniedByByCallId.get(callId) : undefined;
|
|
150
154
|
const deniedBy = typeof deniedByRaw === 'string' && isGateDeniedByWord(deniedByRaw) ? deniedByRaw : undefined;
|
|
151
155
|
const toolDenialKind = isCcToolDenialKind(mergedKind) ? mergedKind : undefined;
|
|
@@ -153,6 +157,7 @@ function permissionDenialParts(stats, observed) {
|
|
|
153
157
|
...(toolName !== undefined ? { tool_name: toolName } : {}),
|
|
154
158
|
tool_use_id: callId,
|
|
155
159
|
...(joinedInput !== undefined ? { tool_input: joinedInput, _sema_tool_input_source: 'tool_start' } : {}),
|
|
160
|
+
...(joined?.transportRedacted === true ? { _sema_tool_input_redacted: true } : {}),
|
|
156
161
|
...(deniedBy !== undefined ? { deniedBy, _sema_denied_by_source: 'tool_end' } : {}),
|
|
157
162
|
...(toolDenialKind !== undefined ? { toolDenialKind } : {}),
|
|
158
163
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WiringManifestModelGate, WiringManifestAutoMode, WiringManifestMcpEntryView, WiringManifestHookEntryView, WiringManifestLspSeamView, WiringManifestWriteProtectionView, WiringManifestAutoConsolidationView, WiringManifestReadDenyView } from './eventToSdkMessage.js';
|
|
2
|
-
import type { ToolRosterView } from '../../toolRoster.js';
|
|
2
|
+
import type { ToolRosterView, WiringManifestHandsView } from '../../toolRoster.js';
|
|
3
3
|
export type WiringManifestSections = {
|
|
4
4
|
_sema_modelGate?: WiringManifestModelGate;
|
|
5
5
|
_sema_autoMode?: WiringManifestAutoMode;
|
|
@@ -10,6 +10,7 @@ export type WiringManifestSections = {
|
|
|
10
10
|
_sema_writeProtection?: WiringManifestWriteProtectionView;
|
|
11
11
|
_sema_autoConsolidation?: WiringManifestAutoConsolidationView;
|
|
12
12
|
_sema_readDeny?: WiringManifestReadDenyView;
|
|
13
|
+
_sema_hands?: WiringManifestHandsView;
|
|
13
14
|
eventId?: string;
|
|
14
15
|
};
|
|
15
16
|
export interface WiringManifestView {
|
|
@@ -22,6 +23,7 @@ export interface WiringManifestView {
|
|
|
22
23
|
writeProtection?: WiringManifestWriteProtectionView;
|
|
23
24
|
autoConsolidation?: WiringManifestAutoConsolidationView;
|
|
24
25
|
readDeny?: WiringManifestReadDenyView;
|
|
26
|
+
hands?: WiringManifestHandsView;
|
|
25
27
|
eventId?: string;
|
|
26
28
|
}
|
|
27
29
|
export declare function wiringManifestViewOf(s: WiringManifestSections): WiringManifestView | undefined;
|
|
@@ -14,6 +14,7 @@ export function wiringManifestViewOf(s) {
|
|
|
14
14
|
...(isObj(s._sema_writeProtection) ? { writeProtection: s._sema_writeProtection } : {}),
|
|
15
15
|
...(isObj(s._sema_autoConsolidation) ? { autoConsolidation: s._sema_autoConsolidation } : {}),
|
|
16
16
|
...(isObj(s._sema_readDeny) ? { readDeny: s._sema_readDeny } : {}),
|
|
17
|
+
...(isObj(s._sema_hands) && typeof s._sema_hands.mounted === 'boolean' ? { hands: s._sema_hands } : {}),
|
|
17
18
|
};
|
|
18
19
|
if (Object.keys(view).length === 0)
|
|
19
20
|
return undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { AgentClient, Capabilities } from '@sema-agent/sdk';
|
|
2
|
+
import type { EngineAgentRegistryListing, EngineAgentRegistryRowView } from '../engineAgentAbsence.js';
|
|
3
|
+
export interface EngineAgentRegistryClient {
|
|
4
|
+
readonly sessions: Pick<AgentClient['sessions'], 'background'>;
|
|
5
|
+
}
|
|
6
|
+
export declare function registryClockNowMs(): number;
|
|
7
|
+
export interface RegistryListingProvenance {
|
|
8
|
+
readonly superseded: boolean;
|
|
9
|
+
readonly sessionId: string;
|
|
10
|
+
readonly rows: readonly EngineAgentRegistryRowView[];
|
|
11
|
+
readonly rawRowCount: number;
|
|
12
|
+
firstSeenAtMs(id: string): number | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function registryListingProvenanceOf(listing: EngineAgentRegistryListing | null | undefined): RegistryListingProvenance | undefined;
|
|
15
|
+
export declare function isEngineAgentRegistryListingSuperseded(listing: EngineAgentRegistryListing | null | undefined): boolean;
|
|
16
|
+
export declare function readEngineAgentRegistry(client: EngineAgentRegistryClient, sessionId: string, caps: Pick<Capabilities, 'background'> | null | undefined, opts?: {
|
|
17
|
+
readonly signal?: AbortSignal;
|
|
18
|
+
}): Promise<EngineAgentRegistryListing>;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { errCodes } from '../controlRouter.js';
|
|
2
|
+
import { hostLog } from '../host.js';
|
|
3
|
+
const unavailable = (why) => ({
|
|
4
|
+
kind: 'unavailable',
|
|
5
|
+
why,
|
|
6
|
+
});
|
|
7
|
+
function noteReadFailed(cause, diag) {
|
|
8
|
+
try {
|
|
9
|
+
const bits = [
|
|
10
|
+
diag?.status !== undefined ? `status=${diag.status}` : '',
|
|
11
|
+
diag?.errorCode !== undefined ? `errorCode=${diag.errorCode}` : '',
|
|
12
|
+
].filter((b) => b.length > 0);
|
|
13
|
+
hostLog('debug', `[sema][registry] read_failed (${cause})${bits.length > 0 ? ` ${bits.join(' ')}` : ''}`);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const readLedgers = new WeakMap();
|
|
19
|
+
const listingRecords = new WeakMap();
|
|
20
|
+
function ledgerFor(sessions, sessionId) {
|
|
21
|
+
let bySession = readLedgers.get(sessions);
|
|
22
|
+
if (bySession === undefined) {
|
|
23
|
+
bySession = new Map();
|
|
24
|
+
readLedgers.set(sessions, bySession);
|
|
25
|
+
}
|
|
26
|
+
let ledger = bySession.get(sessionId);
|
|
27
|
+
if (ledger === undefined) {
|
|
28
|
+
ledger = { issued: 0, deliveredMax: 0, firstSeen: new Map() };
|
|
29
|
+
bySession.set(sessionId, ledger);
|
|
30
|
+
}
|
|
31
|
+
return ledger;
|
|
32
|
+
}
|
|
33
|
+
export function registryClockNowMs() {
|
|
34
|
+
const p = globalThis.performance;
|
|
35
|
+
if (typeof p === 'object' && p !== null && typeof p.now === 'function' && typeof p.timeOrigin === 'number') {
|
|
36
|
+
const v = p.timeOrigin + p.now.call(p);
|
|
37
|
+
if (Number.isFinite(v))
|
|
38
|
+
return v;
|
|
39
|
+
}
|
|
40
|
+
return Date.now();
|
|
41
|
+
}
|
|
42
|
+
export function registryListingProvenanceOf(listing) {
|
|
43
|
+
if (typeof listing !== 'object' || listing === null)
|
|
44
|
+
return undefined;
|
|
45
|
+
const rec = listingRecords.get(listing);
|
|
46
|
+
if (rec === undefined)
|
|
47
|
+
return undefined;
|
|
48
|
+
return {
|
|
49
|
+
superseded: rec.ledger.deliveredMax > rec.seq,
|
|
50
|
+
sessionId: rec.sessionId,
|
|
51
|
+
rows: rec.rows,
|
|
52
|
+
rawRowCount: rec.rawRowCount,
|
|
53
|
+
firstSeenAtMs: (id) => rec.ledger.firstSeen.get(id),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function isEngineAgentRegistryListingSuperseded(listing) {
|
|
57
|
+
return registryListingProvenanceOf(listing)?.superseded === true;
|
|
58
|
+
}
|
|
59
|
+
function listFaceOn(caps) {
|
|
60
|
+
if (typeof caps !== 'object' || caps === null || !Object.hasOwn(caps, 'background'))
|
|
61
|
+
return false;
|
|
62
|
+
const bg = caps.background;
|
|
63
|
+
if (typeof bg !== 'object' || bg === null || !Object.hasOwn(bg, 'listFace'))
|
|
64
|
+
return false;
|
|
65
|
+
return bg.listFace === true;
|
|
66
|
+
}
|
|
67
|
+
function readRow(v) {
|
|
68
|
+
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
69
|
+
return undefined;
|
|
70
|
+
const o = v;
|
|
71
|
+
const id = Object.hasOwn(o, 'id') ? o.id : undefined;
|
|
72
|
+
const type = Object.hasOwn(o, 'type') ? o.type : undefined;
|
|
73
|
+
const status = Object.hasOwn(o, 'status') ? o.status : undefined;
|
|
74
|
+
if (typeof id !== 'string' || id.length === 0 || typeof type !== 'string' || type.length === 0 || typeof status !== 'string' || status.length === 0)
|
|
75
|
+
return undefined;
|
|
76
|
+
const description = Object.hasOwn(o, 'description') ? o.description : undefined;
|
|
77
|
+
const createdAt = Object.hasOwn(o, 'createdAt') ? o.createdAt : undefined;
|
|
78
|
+
return {
|
|
79
|
+
id,
|
|
80
|
+
type,
|
|
81
|
+
status,
|
|
82
|
+
...(typeof description === 'string' && description.length > 0 ? { description } : {}),
|
|
83
|
+
...(typeof createdAt === 'number' && Number.isFinite(createdAt) ? { createdAt } : {}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export async function readEngineAgentRegistry(client, sessionId, caps, opts) {
|
|
87
|
+
try {
|
|
88
|
+
return await readOnce(client, sessionId, caps, opts);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
noteReadFailed('reader threw');
|
|
92
|
+
return unavailable('read_failed');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function readOnce(client, sessionId, caps, opts) {
|
|
96
|
+
if (!listFaceOn(caps))
|
|
97
|
+
return unavailable('no_list_face');
|
|
98
|
+
if (typeof sessionId !== 'string' || sessionId.length === 0) {
|
|
99
|
+
noteReadFailed('bad session id');
|
|
100
|
+
return unavailable('read_failed');
|
|
101
|
+
}
|
|
102
|
+
if (typeof client !== 'object' || client === null) {
|
|
103
|
+
noteReadFailed('bad client');
|
|
104
|
+
return unavailable('read_failed');
|
|
105
|
+
}
|
|
106
|
+
const sessions = client.sessions;
|
|
107
|
+
if (typeof sessions !== 'object' || sessions === null) {
|
|
108
|
+
noteReadFailed('bad client');
|
|
109
|
+
return unavailable('read_failed');
|
|
110
|
+
}
|
|
111
|
+
const ledger = ledgerFor(sessions, sessionId);
|
|
112
|
+
const seq = ++ledger.issued;
|
|
113
|
+
let body;
|
|
114
|
+
try {
|
|
115
|
+
const signal = opts?.signal;
|
|
116
|
+
body = await sessions.background(sessionId, signal !== undefined ? { signal } : undefined);
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
const { code, status } = errCodes(e);
|
|
120
|
+
if (status === 404 && code === 'not_found.route')
|
|
121
|
+
return unavailable('route_absent');
|
|
122
|
+
if (status === 501 && code === 'capability.session_ownership_required')
|
|
123
|
+
return unavailable('ownership_required');
|
|
124
|
+
const diag = {
|
|
125
|
+
...(typeof status === 'number' && Number.isInteger(status) ? { status } : {}),
|
|
126
|
+
...(typeof code === 'string' && code.length > 0 ? { errorCode: code } : {}),
|
|
127
|
+
};
|
|
128
|
+
noteReadFailed('request failed', diag);
|
|
129
|
+
return { kind: 'unavailable', why: 'read_failed', ...diag };
|
|
130
|
+
}
|
|
131
|
+
if (typeof body !== 'object' || body === null || !Object.hasOwn(body, 'rows')) {
|
|
132
|
+
noteReadFailed('body is not { rows }');
|
|
133
|
+
return unavailable('read_failed');
|
|
134
|
+
}
|
|
135
|
+
const raw = body.rows;
|
|
136
|
+
if (!Array.isArray(raw)) {
|
|
137
|
+
noteReadFailed('body is not { rows }');
|
|
138
|
+
return unavailable('read_failed');
|
|
139
|
+
}
|
|
140
|
+
const rows = [];
|
|
141
|
+
for (const r of raw) {
|
|
142
|
+
const row = readRow(r);
|
|
143
|
+
if (row === undefined) {
|
|
144
|
+
noteReadFailed('a row could not be read');
|
|
145
|
+
return unavailable('read_failed');
|
|
146
|
+
}
|
|
147
|
+
rows.push(Object.freeze(row));
|
|
148
|
+
}
|
|
149
|
+
const rawRowCount = raw.length;
|
|
150
|
+
if (seq > ledger.deliveredMax) {
|
|
151
|
+
ledger.deliveredMax = seq;
|
|
152
|
+
const now = registryClockNowMs();
|
|
153
|
+
const present = new Set();
|
|
154
|
+
for (const row of rows) {
|
|
155
|
+
present.add(row.id);
|
|
156
|
+
if (!ledger.firstSeen.has(row.id))
|
|
157
|
+
ledger.firstSeen.set(row.id, now);
|
|
158
|
+
}
|
|
159
|
+
for (const id of [...ledger.firstSeen.keys()])
|
|
160
|
+
if (!present.has(id))
|
|
161
|
+
ledger.firstSeen.delete(id);
|
|
162
|
+
}
|
|
163
|
+
const frozenRows = Object.freeze(rows);
|
|
164
|
+
const listing = Object.freeze({ kind: 'rows', rows: frozenRows, sessionId, seq });
|
|
165
|
+
listingRecords.set(listing, { ledger, seq, sessionId, rows: frozenRows, rawRowCount });
|
|
166
|
+
return listing;
|
|
167
|
+
}
|
package/dist/agentsWireCaps.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { hostEnv } from './hostEnv.js';
|
|
2
2
|
import { makeEngineWireClient } from './engineWireSdk.js';
|
|
3
|
+
import { frozenSet } from './frozenSet.js';
|
|
4
|
+
import { settleWithinDeadline } from './abortableSleep.js';
|
|
3
5
|
export const MAX_TASK_AGENTS = 32;
|
|
4
6
|
export const MAX_AGENT_NAME_CHARS = 64;
|
|
5
7
|
export const MAX_AGENT_TEXT_CHARS = 4_096;
|
|
@@ -25,7 +27,7 @@ export const TASK_AGENT_WIRE_FIELDS = [
|
|
|
25
27
|
'observer',
|
|
26
28
|
'observerMessage',
|
|
27
29
|
];
|
|
28
|
-
export const AGENT_MEMORY_WORDS =
|
|
30
|
+
export const AGENT_MEMORY_WORDS = frozenSet(['user', 'project', 'local']);
|
|
29
31
|
const SOURCE_RANK = {
|
|
30
32
|
policySettings: 0,
|
|
31
33
|
flagSettings: 1,
|
|
@@ -172,6 +174,13 @@ export function projectAgentsForWire(defs, deps) {
|
|
|
172
174
|
return { agents: out.length > 0 ? out : undefined, warnings };
|
|
173
175
|
}
|
|
174
176
|
export async function engineSupportsTaskAgents(baseUrl, opts) {
|
|
177
|
+
if (opts?.client !== undefined) {
|
|
178
|
+
const injected = opts.client;
|
|
179
|
+
if (typeof injected?.capabilities !== 'function')
|
|
180
|
+
return undefined;
|
|
181
|
+
const got = await settleWithinDeadline(opts.timeoutMs ?? 3000, (signal) => injected.capabilities({ signal }));
|
|
182
|
+
return got.kind === 'value' ? got.value?.taskAgents === true : undefined;
|
|
183
|
+
}
|
|
175
184
|
const client = makeEngineWireClient({
|
|
176
185
|
baseUrl,
|
|
177
186
|
...(opts?.authToken ? { token: opts.authToken } : {}),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { hostEnv } from './hostEnv.js';
|
|
2
2
|
import { envFlagOff } from './envFlag.js';
|
|
3
3
|
export const ATTACHMENTS_ENV = 'SEMA_ATTACHMENTS';
|
|
4
|
-
export const ATTACHMENTS_SPEC_KEYS = [
|
|
4
|
+
export const ATTACHMENTS_SPEC_KEYS = Object.freeze([
|
|
5
5
|
'todoReminder',
|
|
6
6
|
'todoReminderMode',
|
|
7
7
|
'changedFiles',
|
|
@@ -12,7 +12,7 @@ export const ATTACHMENTS_SPEC_KEYS = [
|
|
|
12
12
|
'mcpInstructions',
|
|
13
13
|
'agentListing',
|
|
14
14
|
'skillsListing',
|
|
15
|
-
];
|
|
15
|
+
]);
|
|
16
16
|
export const ATTACHMENTS_DEFAULT_ON_KEYS = ['agentListing', 'skillsListing', 'backgroundTasks'];
|
|
17
17
|
const OPT_IN_KEYS = [
|
|
18
18
|
'todoReminder',
|
package/dist/controlRouter.js
CHANGED
|
@@ -83,7 +83,7 @@ export class ControlRouter {
|
|
|
83
83
|
}
|
|
84
84
|
if (isCancelSuspendedConflict(e)) {
|
|
85
85
|
throw new ControlSafetyError('runs.cancel 409 — the pending gate was decided or expired concurrently (lost CAS race); ' +
|
|
86
|
-
'
|
|
86
|
+
'check what that decision did to the run before retrying the cancel', 'cancel_lost_race', e);
|
|
87
87
|
}
|
|
88
88
|
if (isNotFound(e)) {
|
|
89
89
|
throw new ControlSafetyError('runs.cancel 404 — non-owner / unknown run (no existence leak)', 'not_found', e);
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ParkedResumeStartupDecision } from './resumeRefusalCopy.js';
|
|
2
|
+
export declare function decideFailureNote(err: unknown, decision?: ParkedResumeStartupDecision): string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { corruptStoredRowContent, corruptStoredRowWhere } from './wireErrorTriage.js';
|
|
2
|
-
import { resumePolicyBlockContent, resumePolicyBlockFromError } from './resumeRefusalCopy.js';
|
|
3
|
-
export function decideFailureNote(err) {
|
|
2
|
+
import { parkedResumeStartupContent, parkedResumeStartupFromError, resumePolicyBlockContent, resumePolicyBlockFromError, } from './resumeRefusalCopy.js';
|
|
3
|
+
export function decideFailureNote(err, decision) {
|
|
4
4
|
const where = corruptStoredRowWhere(err);
|
|
5
5
|
const fold = resumePolicyBlockFromError(err);
|
|
6
|
+
const startup = parkedResumeStartupFromError(err, decision);
|
|
6
7
|
return ((where === undefined ? '' : ` — ${corruptStoredRowContent(where)}`) +
|
|
7
|
-
(fold === null ? '' : ` — ${resumePolicyBlockContent(fold)}`)
|
|
8
|
+
(fold === null ? '' : ` — ${resumePolicyBlockContent(fold)}`) +
|
|
9
|
+
(startup === null ? '' : ` — ${parkedResumeStartupContent(startup)}`));
|
|
8
10
|
}
|
package/dist/detachWire.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export declare function resolveHeadlessDetach(baseUrl: string, env?: EnvLike, op
|
|
|
26
26
|
timeoutMs?: number;
|
|
27
27
|
}): Promise<DetachResolution>;
|
|
28
28
|
export declare const DETACH_DURABLE_OFF_400_ANCHOR = "x-detach-on-disconnect requires a durable run";
|
|
29
|
+
export declare function isDetachDurableOff400(err: unknown): boolean;
|
|
29
30
|
export declare function detachDurableOffHint(err: unknown): string | null;
|
|
30
31
|
export interface DetachCancelArm {
|
|
31
32
|
baseUrl: string;
|
package/dist/detachWire.js
CHANGED
|
@@ -57,14 +57,22 @@ export async function resolveHeadlessDetach(baseUrl, env = hostEnv(), opts) {
|
|
|
57
57
|
return { on: true, reason: 'default-on' };
|
|
58
58
|
}
|
|
59
59
|
export const DETACH_DURABLE_OFF_400_ANCHOR = 'x-detach-on-disconnect requires a durable run';
|
|
60
|
+
export function isDetachDurableOff400(err) {
|
|
61
|
+
try {
|
|
62
|
+
const e = err;
|
|
63
|
+
if (e?.status !== 400)
|
|
64
|
+
return false;
|
|
65
|
+
const msg = e?.message;
|
|
66
|
+
return typeof msg === 'string' && msg.includes(DETACH_DURABLE_OFF_400_ANCHOR);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
60
72
|
export function detachDurableOffHint(err) {
|
|
61
73
|
if (!isDetachArmed())
|
|
62
74
|
return null;
|
|
63
|
-
|
|
64
|
-
if (e?.status !== 400)
|
|
65
|
-
return null;
|
|
66
|
-
const msg = typeof e?.message === 'string' ? e.message : '';
|
|
67
|
-
if (!msg.includes(DETACH_DURABLE_OFF_400_ANCHOR))
|
|
75
|
+
if (!isDetachDurableOff400(err))
|
|
68
76
|
return null;
|
|
69
77
|
return 'engine has durable runs disabled — detach-on-disconnect unavailable; interrupted turns will abort (SEMA_HEADLESS_DETACH=false to silence)';
|
|
70
78
|
}
|