@sema-agent/client-core 0.99.0 → 0.100.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 +177 -0
- package/README.md +32 -19
- package/dist/adapt/arms.js +60 -36
- package/dist/adapt/panelTasks.d.ts +2 -1
- package/dist/adapt/panelTasks.js +32 -9
- package/dist/adapt/textStream.d.ts +1 -1
- package/dist/adapt/textStream.js +51 -28
- package/dist/adapter/activeRunSelfHeal.d.ts +7 -0
- package/dist/adapter/activeRunSelfHeal.js +58 -11
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
- package/dist/adapter/downstream/eventToSdkMessage.js +125 -9
- package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
- package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
- package/dist/adapter/downstream/wiringManifestView.js +1 -0
- package/dist/adapter/runStream.js +32 -5
- package/dist/adapter/types.d.ts +2 -0
- package/dist/agentsWireCaps.d.ts +7 -0
- package/dist/agentsWireCaps.js +100 -15
- package/dist/cloudConfigWireCaps.d.ts +10 -1
- package/dist/cloudConfigWireCaps.js +156 -62
- package/dist/compactionStatus.d.ts +34 -0
- package/dist/compactionStatus.js +196 -0
- package/dist/decideFailureNote.js +3 -3
- package/dist/displayUntrusted.js +150 -5
- package/dist/engineAgentPanelStore.d.ts +7 -4
- package/dist/engineErrorCodes.d.ts +9 -1
- package/dist/engineErrorCodes.js +9 -5
- package/dist/engineRowRef.js +1 -0
- package/dist/engineToolDirectory.d.ts +3 -0
- package/dist/engineToolDirectory.js +4 -2
- package/dist/eventLeg.d.ts +1 -7
- package/dist/eventLeg.js +7 -8
- package/dist/fileHistoryCaptureCapability.d.ts +0 -3
- package/dist/fileHistoryCaptureCapability.js +0 -4
- package/dist/generated/engineFactTables.d.ts +1 -0
- package/dist/generated/engineFactTables.js +27 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaFns.d.ts +12 -0
- package/dist/generated/settingsSchemaFns.js +13 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
- package/dist/generated/settingsSchemaTables.d.ts +1 -0
- package/dist/generated/settingsSchemaTables.js +5 -0
- package/dist/generated/settingsSchemaTypes.d.ts +28 -0
- package/dist/hitl/allowRuleShadow.js +2 -2
- package/dist/hitl/approvalCardReasons.js +2 -2
- package/dist/hitl/approvalHolds.d.ts +14 -0
- package/dist/hitl/approvalHolds.js +41 -0
- package/dist/hitl/askClassPair.d.ts +2 -2
- package/dist/hitl/askClassPair.js +2 -2
- package/dist/hitl/attributionLadder.d.ts +23 -0
- package/dist/hitl/attributionLadder.js +67 -0
- package/dist/hitl/decisionLedger.d.ts +55 -0
- package/dist/hitl/decisionLedger.js +156 -0
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +1 -1
- package/dist/hitl/decisionSend.d.ts +113 -0
- package/dist/hitl/decisionSend.js +579 -0
- package/dist/hitl/hitlBridge.js +18 -6
- package/dist/hitl/planReviewWire.js +45 -76
- package/dist/hitl/sessionPolicyDeliverable.js +3 -6
- package/dist/hitl/toolApprovalWire.js +43 -109
- package/dist/hostTurnSettings.d.ts +46 -7
- package/dist/hostTurnSettings.js +408 -7
- package/dist/humanTurn.d.ts +2 -1
- package/dist/humanTurn.js +3 -3
- package/dist/i18n/messages.en.d.ts +131 -0
- package/dist/i18n/messages.en.js +143 -12
- package/dist/i18n/messages.zh.js +148 -12
- package/dist/index.d.ts +18 -2
- package/dist/index.js +10 -1
- package/dist/inheritEnvCapability.d.ts +1 -0
- package/dist/inheritEnvCapability.js +9 -2
- package/dist/inheritEnvWire.js +2 -2
- package/dist/injectionLaneNotice.d.ts +5 -0
- package/dist/injectionLaneNotice.js +46 -0
- package/dist/mcpPanel.js +2 -0
- package/dist/mcpReconnect.js +2 -2
- package/dist/mcpToolToggles.d.ts +6 -0
- package/dist/mcpToolToggles.js +46 -0
- package/dist/mcpWireCaps.d.ts +10 -4
- package/dist/mcpWireCaps.js +106 -71
- package/dist/mcpWireTransport.d.ts +4 -0
- package/dist/mcpWireTransport.js +18 -0
- package/dist/modelCapabilityProbe.d.ts +2 -1
- package/dist/modelCapabilityProbe.js +10 -9
- package/dist/modelIdentityResolvability.d.ts +2 -0
- package/dist/modelIdentityResolvability.js +23 -5
- package/dist/ownKey.d.ts +26 -0
- package/dist/ownKey.js +75 -0
- package/dist/panelReduce.d.ts +5 -0
- package/dist/panelReduce.js +45 -13
- package/dist/panelStateHolder.d.ts +1 -0
- package/dist/panelStateHolder.js +10 -1
- package/dist/permissionRuleIssue.d.ts +2 -1
- package/dist/permissionRuleIssue.js +22 -21
- package/dist/pluginHooksWire.js +12 -10
- package/dist/prepareRefusal.d.ts +8 -0
- package/dist/prepareRefusal.js +72 -0
- package/dist/request/taskRequest.d.ts +10 -10
- package/dist/request/taskRequest.js +106 -65
- package/dist/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +22 -4
- package/dist/retryStatus.d.ts +18 -0
- package/dist/retryStatus.js +76 -19
- package/dist/ruleRefusalSentence.d.ts +4 -0
- package/dist/ruleRefusalSentence.js +58 -0
- package/dist/sandboxWire.d.ts +2 -1
- package/dist/sandboxWire.js +55 -21
- package/dist/scenarioRefusal.d.ts +2 -1
- package/dist/scenarioRefusal.js +5 -5
- package/dist/seam.d.ts +24 -9
- package/dist/seam.js +44 -4
- package/dist/seatContract.d.ts +16 -8
- package/dist/seatContract.js +21 -6
- package/dist/settingsCredentialKeyPaths.d.ts +8 -0
- package/dist/settingsCredentialKeyPaths.js +219 -0
- package/dist/skillsWireCaps.d.ts +0 -3
- package/dist/skillsWireCaps.js +1 -2
- package/dist/subagentContentStore.d.ts +1 -0
- package/dist/subagentContentStore.js +135 -27
- package/dist/toolsFlagNames.d.ts +8 -0
- package/dist/toolsFlagNames.js +110 -0
- package/dist/turnFailurePresentation.js +15 -7
- package/dist/wireRefusalCopy.d.ts +51 -17
- package/dist/wireRefusalCopy.js +298 -135
- package/docs/INTEGRATION-CLIENTS.md +423 -26
- package/package.json +4 -4
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { looksLikeKnownSecret, queryCarriesCredential } from './displayUntrusted.js';
|
|
2
|
+
const CREDENTIAL_WORDS = new Set([
|
|
3
|
+
'key', 'keys', 'apikey', 'token', 'tokens', 'secret', 'secrets', 'password', 'passwd', 'pass', 'pwd', 'pin', 'otp',
|
|
4
|
+
'auth', 'authorization', 'credential', 'credentials', 'cookie', 'cookies', 'session', 'private', 'cert', 'signature', 'salt',
|
|
5
|
+
]);
|
|
6
|
+
const CREDENTIAL_STEMS = ['PASSWORD', 'PASSWD', 'SECRET', 'TOKEN', 'APIKEY', 'CREDENTIAL', 'COOKIE', 'PRIVATE'];
|
|
7
|
+
const CREDENTIAL_SUFFIXES = ['PASS', 'PWD', 'KEY', 'AUTH'];
|
|
8
|
+
const SECRET_CONFIG_NAME = /(?:^|[-_.])(?:token|key|secret|password|authorization|credential|cookie)s?$/i;
|
|
9
|
+
export function credentialNameWords(name) {
|
|
10
|
+
if (typeof name !== 'string')
|
|
11
|
+
return [];
|
|
12
|
+
return name
|
|
13
|
+
.replace(/([A-Z])(?=[A-Z][a-z])/g, '$1_')
|
|
14
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1_$2')
|
|
15
|
+
.split(/[_\-.\s]+/)
|
|
16
|
+
.filter((w) => w.length > 0)
|
|
17
|
+
.map((w) => w.toLowerCase());
|
|
18
|
+
}
|
|
19
|
+
export function isCredentialEnvName(name) {
|
|
20
|
+
if (typeof name !== 'string')
|
|
21
|
+
return false;
|
|
22
|
+
if (credentialNameWords(name).some((w) => CREDENTIAL_WORDS.has(w)))
|
|
23
|
+
return true;
|
|
24
|
+
const upper = name.toUpperCase();
|
|
25
|
+
return CREDENTIAL_STEMS.some((stem) => upper.includes(stem)) || CREDENTIAL_SUFFIXES.some((suffix) => upper.endsWith(suffix));
|
|
26
|
+
}
|
|
27
|
+
export function isCredentialConfigKey(name) {
|
|
28
|
+
if (typeof name !== 'string')
|
|
29
|
+
return false;
|
|
30
|
+
const words = credentialNameWords(name);
|
|
31
|
+
const last = words[words.length - 1];
|
|
32
|
+
return SECRET_CONFIG_NAME.test(name) || (last !== undefined && CREDENTIAL_WORDS.has(last));
|
|
33
|
+
}
|
|
34
|
+
const DECIMAL_INTEGER_RE = /^\s*\d+\s*$/;
|
|
35
|
+
function stringCarriesCredential(value) {
|
|
36
|
+
if (looksLikeKnownSecret(value))
|
|
37
|
+
return true;
|
|
38
|
+
const text = value.trim();
|
|
39
|
+
if (!text.includes('://'))
|
|
40
|
+
return false;
|
|
41
|
+
let url;
|
|
42
|
+
try {
|
|
43
|
+
url = new URL(text);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (url.username !== '' || url.password !== '')
|
|
49
|
+
return true;
|
|
50
|
+
return url.search.length > 1 && queryCarriesCredential(url.search.slice(1));
|
|
51
|
+
}
|
|
52
|
+
const ENV_ASSIGNMENT_RE = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/s;
|
|
53
|
+
const LONG_OPTION_RE = /^--?([A-Za-z][A-Za-z0-9_-]*)(?:=(.*))?$/s;
|
|
54
|
+
const HEADER_FORM_RE = /^\s*([A-Za-z][A-Za-z0-9_-]*)\s*:\s*\S/;
|
|
55
|
+
function argvFindings(args) {
|
|
56
|
+
const hits = new Map();
|
|
57
|
+
const add = (i, numericByNameOnly) => {
|
|
58
|
+
hits.set(i, (hits.get(i) ?? true) && numericByNameOnly);
|
|
59
|
+
};
|
|
60
|
+
const valueCarries = (value) => {
|
|
61
|
+
const header = HEADER_FORM_RE.exec(value);
|
|
62
|
+
return stringCarriesCredential(value) || (header !== null && isCredentialConfigKey(header[1] ?? ''));
|
|
63
|
+
};
|
|
64
|
+
args.forEach((arg, i) => {
|
|
65
|
+
if (valueCarries(arg))
|
|
66
|
+
add(i, false);
|
|
67
|
+
const assignment = ENV_ASSIGNMENT_RE.exec(arg);
|
|
68
|
+
if (assignment !== null && assignment[2] !== '') {
|
|
69
|
+
const assigned = assignment[2] ?? '';
|
|
70
|
+
if (valueCarries(assigned))
|
|
71
|
+
add(i, false);
|
|
72
|
+
if (isCredentialEnvName(assignment[1] ?? ''))
|
|
73
|
+
add(i, DECIMAL_INTEGER_RE.test(assigned));
|
|
74
|
+
}
|
|
75
|
+
const option = LONG_OPTION_RE.exec(arg);
|
|
76
|
+
if (option === null)
|
|
77
|
+
return;
|
|
78
|
+
const inline = option[2];
|
|
79
|
+
if (inline !== undefined && inline !== '' && valueCarries(inline))
|
|
80
|
+
add(i, false);
|
|
81
|
+
const optionName = option[1] ?? '';
|
|
82
|
+
if (optionName.length <= 1 || !isCredentialEnvName(optionName))
|
|
83
|
+
return;
|
|
84
|
+
if (inline !== undefined) {
|
|
85
|
+
if (inline !== '')
|
|
86
|
+
add(i, DECIMAL_INTEGER_RE.test(inline));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const next = args[i + 1];
|
|
90
|
+
if (next !== undefined && next !== '')
|
|
91
|
+
add(i + 1, DECIMAL_INTEGER_RE.test(next));
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
return hits;
|
|
95
|
+
}
|
|
96
|
+
function isPresent(value) {
|
|
97
|
+
return value !== undefined && value !== null && value !== '' && value !== false;
|
|
98
|
+
}
|
|
99
|
+
function arrayKindOf(node) {
|
|
100
|
+
try {
|
|
101
|
+
return Array.isArray(node);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function ownKeysOf(node) {
|
|
108
|
+
try {
|
|
109
|
+
return Object.keys(node);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function readSlot(node, key) {
|
|
116
|
+
try {
|
|
117
|
+
return { ok: true, value: node[key] };
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return { ok: false };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function settingsCredentialKeyPaths(doc) {
|
|
124
|
+
const found = [];
|
|
125
|
+
if (doc === null || doc === undefined || typeof doc !== 'object')
|
|
126
|
+
return found;
|
|
127
|
+
const finding = (path, numericByNameOnly) => (numericByNameOnly ? { path, numericByNameOnly: true } : { path });
|
|
128
|
+
const ancestors = new WeakSet();
|
|
129
|
+
const stack = [{ node: doc, path: '', inEnv: false }];
|
|
130
|
+
while (stack.length > 0) {
|
|
131
|
+
const frame = stack.pop();
|
|
132
|
+
if (frame === undefined)
|
|
133
|
+
continue;
|
|
134
|
+
const { node, path, inEnv } = frame;
|
|
135
|
+
if (frame.exit === true) {
|
|
136
|
+
ancestors.delete(node);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (ancestors.has(node))
|
|
140
|
+
continue;
|
|
141
|
+
ancestors.add(node);
|
|
142
|
+
stack.push({ node, path, inEnv, exit: true });
|
|
143
|
+
const isArray = arrayKindOf(node);
|
|
144
|
+
if (isArray === undefined) {
|
|
145
|
+
if (path !== '')
|
|
146
|
+
found.push(finding(path, false));
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (isArray) {
|
|
150
|
+
let items;
|
|
151
|
+
try {
|
|
152
|
+
items = Array.from(node);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
if (path !== '')
|
|
156
|
+
found.push(finding(path, false));
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (items.length > 0 && items.every((item) => typeof item === 'string')) {
|
|
160
|
+
const hits = argvFindings(items);
|
|
161
|
+
for (const i of [...hits.keys()].sort((a, b) => a - b))
|
|
162
|
+
found.push(finding(`${path}[${i}]`, hits.get(i) === true));
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
items.forEach((item, i) => {
|
|
166
|
+
const itemPath = `${path}[${i}]`;
|
|
167
|
+
if (typeof item === 'string') {
|
|
168
|
+
if (stringCarriesCredential(item))
|
|
169
|
+
found.push(finding(itemPath, false));
|
|
170
|
+
}
|
|
171
|
+
else if (item !== null && typeof item === 'object') {
|
|
172
|
+
stack.push({ node: item, path: itemPath, inEnv: false });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const keys = ownKeysOf(node);
|
|
178
|
+
if (keys === undefined) {
|
|
179
|
+
if (path !== '')
|
|
180
|
+
found.push(finding(path, false));
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
for (const key of keys) {
|
|
184
|
+
const keyPath = path === '' ? key : `${path}.${key}`;
|
|
185
|
+
const nameIsCredential = inEnv ? isCredentialEnvName(key) : isCredentialConfigKey(key);
|
|
186
|
+
const slot = readSlot(node, key);
|
|
187
|
+
if (!slot.ok) {
|
|
188
|
+
if (nameIsCredential)
|
|
189
|
+
found.push(finding(keyPath, false));
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const value = slot.value;
|
|
193
|
+
if (typeof value === 'string') {
|
|
194
|
+
const byValue = stringCarriesCredential(value);
|
|
195
|
+
if (byValue || (nameIsCredential && isPresent(value)))
|
|
196
|
+
found.push(finding(keyPath, !byValue && DECIMAL_INTEGER_RE.test(value)));
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (value !== null && typeof value === 'object') {
|
|
200
|
+
let nonEmpty;
|
|
201
|
+
try {
|
|
202
|
+
nonEmpty = Array.isArray(value) ? value.length > 0 : Object.keys(value).length > 0;
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
nonEmpty = true;
|
|
206
|
+
}
|
|
207
|
+
if (nameIsCredential && nonEmpty) {
|
|
208
|
+
found.push(finding(keyPath, false));
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
stack.push({ node: value, path: keyPath, inEnv: key === 'env' });
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (nameIsCredential && isPresent(value))
|
|
215
|
+
found.push(finding(keyPath, typeof value === 'number'));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return found;
|
|
219
|
+
}
|
package/dist/skillsWireCaps.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { SkillSpec } from '@sema-agent/sdk';
|
|
2
2
|
import { type SkillToolListsReading } from './skillToolListsCapability.js';
|
|
3
|
-
export declare const SKILL_CAPS: {
|
|
4
|
-
readonly content: 1048576;
|
|
5
|
-
};
|
|
6
3
|
export interface SkillCmdLike {
|
|
7
4
|
type?: string;
|
|
8
5
|
name?: string;
|
package/dist/skillsWireCaps.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { skillToolListsAvailable } from './skillToolListsCapability.js';
|
|
2
|
-
export const SKILL_CAPS = { content: 1_048_576 };
|
|
3
2
|
export function toCappedSpec(name, description, whenToUse, body) {
|
|
4
3
|
const n = name.trim();
|
|
5
|
-
const c = body.trim()
|
|
4
|
+
const c = body.trim();
|
|
6
5
|
if (!n || !c)
|
|
7
6
|
return null;
|
|
8
7
|
const desc = [description.trim(), whenToUse.trim()]
|
|
@@ -44,6 +44,7 @@ export declare const SUBAGENT_CONTENT_STORE_DEFAULTS: Readonly<SubagentContentSt
|
|
|
44
44
|
export declare function configureSubagentContentStore(next: Partial<SubagentContentStoreConfig>): void;
|
|
45
45
|
export declare function subagentContentStoreConfig(): SubagentContentStoreConfig;
|
|
46
46
|
export declare function __resetSubagentContentStoreConfigForTests(): void;
|
|
47
|
+
export declare function bindSubagentIdentityReader(fn: (id: string) => readonly string[] | undefined): void;
|
|
47
48
|
export declare function registerSubagentContentAlias(parentToolCallId: string, taskId: string): void;
|
|
48
49
|
export declare function registerSubagentAlias(parentToolCallId: string, taskId: string): void;
|
|
49
50
|
export declare function publishSubagentContentEvent(ev: SubagentContentEvent): void;
|
|
@@ -229,8 +229,40 @@ function dropTask(key) {
|
|
|
229
229
|
totalBytes -= s.bytes;
|
|
230
230
|
tasks.delete(key);
|
|
231
231
|
}
|
|
232
|
+
let subagentIdsReader;
|
|
233
|
+
export function bindSubagentIdentityReader(fn) {
|
|
234
|
+
subagentIdsReader = fn;
|
|
235
|
+
}
|
|
236
|
+
function sameSubagentIds(id) {
|
|
237
|
+
let ids;
|
|
238
|
+
try {
|
|
239
|
+
ids = subagentIdsReader?.(id);
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
ids = undefined;
|
|
243
|
+
}
|
|
244
|
+
if (ids === undefined)
|
|
245
|
+
return [id];
|
|
246
|
+
return ids.includes(id) ? ids : [...ids, id];
|
|
247
|
+
}
|
|
248
|
+
function homeKeyOf(key) {
|
|
249
|
+
return sameSubagentIds(key).find((id) => tasks.has(id)) ?? key;
|
|
250
|
+
}
|
|
251
|
+
function contentKeyOf(taskId) {
|
|
252
|
+
const ids = sameSubagentIds(taskId);
|
|
253
|
+
const direct = ids.find((id) => tasks.has(id));
|
|
254
|
+
if (direct !== undefined)
|
|
255
|
+
return direct;
|
|
256
|
+
for (const id of ids) {
|
|
257
|
+
const parked = taskToParent.get(id)?.card;
|
|
258
|
+
if (parked !== undefined && tasks.has(parked))
|
|
259
|
+
return parked;
|
|
260
|
+
}
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
232
263
|
const parentToTask = new Map();
|
|
233
264
|
const taskToParent = new Map();
|
|
265
|
+
let parentStampSeq = 0;
|
|
234
266
|
let notifyListener = null;
|
|
235
267
|
const pendingNotify = new Set();
|
|
236
268
|
let notifyTimer = null;
|
|
@@ -383,7 +415,8 @@ function aliasContentKey(parentToolCallId, taskId) {
|
|
|
383
415
|
export function registerSubagentAlias(parentToolCallId, taskId) {
|
|
384
416
|
if (!aliasContentKey(parentToolCallId, taskId))
|
|
385
417
|
return;
|
|
386
|
-
taskToParent.
|
|
418
|
+
if (taskToParent.get(taskId)?.card !== parentToolCallId)
|
|
419
|
+
taskToParent.set(taskId, { card: parentToolCallId, stamp: ++parentStampSeq });
|
|
387
420
|
}
|
|
388
421
|
function replaySeen(s, ev) {
|
|
389
422
|
const id = ev.eventId;
|
|
@@ -459,7 +492,7 @@ function canonicalKey(ev) {
|
|
|
459
492
|
return parentToTask.get(ev.parentToolCallId) ?? ev.parentToolCallId;
|
|
460
493
|
}
|
|
461
494
|
export function publishSubagentContentEvent(ev) {
|
|
462
|
-
const key = canonicalKey(ev);
|
|
495
|
+
const key = homeKeyOf(canonicalKey(ev));
|
|
463
496
|
const s = stateFor(key, ev.parentToolCallId);
|
|
464
497
|
switch (ev.type) {
|
|
465
498
|
case 'text_delta':
|
|
@@ -561,15 +594,17 @@ export function publishSubagentContentEvent(ev) {
|
|
|
561
594
|
scheduleNotify(key);
|
|
562
595
|
}
|
|
563
596
|
export function pushSubagentLocalEcho(taskId, text) {
|
|
564
|
-
const
|
|
597
|
+
const known = contentKeyOf(taskId);
|
|
598
|
+
const key = known !== '' ? known : taskId;
|
|
599
|
+
const s = stateFor(key, tasks.get(key)?.parentToolCallId ?? '');
|
|
565
600
|
flushBuffers(s);
|
|
566
601
|
pushItem(s, { kind: 'echo', text });
|
|
567
602
|
enforceTaskCap(s);
|
|
568
|
-
enforceTotalCap(
|
|
569
|
-
scheduleNotify(
|
|
603
|
+
enforceTotalCap(key);
|
|
604
|
+
scheduleNotify(key);
|
|
570
605
|
}
|
|
571
606
|
export function getSubagentContentSnapshot(taskId) {
|
|
572
|
-
const key =
|
|
607
|
+
const key = contentKeyOf(taskId);
|
|
573
608
|
const s = tasks.get(key);
|
|
574
609
|
if (!s)
|
|
575
610
|
return null;
|
|
@@ -615,17 +650,42 @@ export function planSubagentViewSlots(taskId) {
|
|
|
615
650
|
return out;
|
|
616
651
|
}
|
|
617
652
|
export function parentToolCallIdOf(taskId) {
|
|
618
|
-
|
|
653
|
+
const ids = sameSubagentIds(taskId);
|
|
654
|
+
let stated;
|
|
655
|
+
let statedStamp = -1;
|
|
656
|
+
for (const id of ids) {
|
|
657
|
+
const hit = taskToParent.get(id);
|
|
658
|
+
if (hit === undefined)
|
|
659
|
+
continue;
|
|
660
|
+
if (stated === undefined || hit.stamp > statedStamp) {
|
|
661
|
+
stated = hit.card;
|
|
662
|
+
statedStamp = hit.stamp;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (stated !== undefined)
|
|
666
|
+
return stated;
|
|
667
|
+
for (const id of ids) {
|
|
668
|
+
const fromContent = tasks.get(id)?.parentToolCallId;
|
|
669
|
+
if (fromContent !== undefined)
|
|
670
|
+
return fromContent;
|
|
671
|
+
}
|
|
672
|
+
return undefined;
|
|
619
673
|
}
|
|
620
674
|
export function settleSubagentContent(taskId) {
|
|
621
|
-
const
|
|
675
|
+
const key = contentKeyOf(taskId);
|
|
676
|
+
const s = tasks.get(key);
|
|
622
677
|
if (!s)
|
|
623
678
|
return;
|
|
624
679
|
flushBuffers(s);
|
|
625
|
-
scheduleNotify(
|
|
680
|
+
scheduleNotify(key);
|
|
626
681
|
}
|
|
627
682
|
export function clearSubagentContent(taskId) {
|
|
628
|
-
|
|
683
|
+
for (;;) {
|
|
684
|
+
const key = contentKeyOf(taskId);
|
|
685
|
+
if (key === '')
|
|
686
|
+
return;
|
|
687
|
+
dropTask(key);
|
|
688
|
+
}
|
|
629
689
|
}
|
|
630
690
|
const bgFacts = new Map();
|
|
631
691
|
export function recordBgTerminalFacts(taskId, facts) {
|
|
@@ -641,10 +701,12 @@ export function recordBgTerminalFacts(taskId, facts) {
|
|
|
641
701
|
scheduleNotify(taskId);
|
|
642
702
|
}
|
|
643
703
|
export function clearBgTerminalFacts(taskId) {
|
|
644
|
-
|
|
704
|
+
for (const id of sameSubagentIds(taskId))
|
|
705
|
+
bgFacts.delete(id);
|
|
645
706
|
}
|
|
646
707
|
export function getBgTerminalFacts(taskId) {
|
|
647
|
-
const
|
|
708
|
+
const ids = sameSubagentIds(taskId);
|
|
709
|
+
const key = ids.find((id) => bgFacts.has(id)) ?? ids.map((id) => taskToParent.get(id)?.card).find((c) => c !== undefined) ?? '';
|
|
648
710
|
touchLru(bgFacts, key);
|
|
649
711
|
return bgFacts.get(key);
|
|
650
712
|
}
|
|
@@ -665,15 +727,35 @@ export function recordBgParentRun(taskId, runId, sessionId, sessionKey) {
|
|
|
665
727
|
export function recordSubagentOwner(taskId, runId, sessionId, sessionKey) {
|
|
666
728
|
if (!taskId || typeof runId !== 'string' || runId === '' || taskId === runId)
|
|
667
729
|
return;
|
|
668
|
-
|
|
730
|
+
const ids = sameSubagentIds(taskId);
|
|
731
|
+
const heldKeys = ids.filter((k) => bgParentRun.has(k));
|
|
732
|
+
const heldRecs = [];
|
|
733
|
+
for (const k of heldKeys) {
|
|
734
|
+
const rec = bgParentRun.get(k);
|
|
735
|
+
if (rec !== undefined)
|
|
736
|
+
heldRecs.push(rec);
|
|
737
|
+
}
|
|
738
|
+
if (bgParentRun.size >= MAX_BG_PARENT_RUNS && heldKeys.length === 0) {
|
|
669
739
|
const oldest = bgParentRun.keys().next().value;
|
|
670
740
|
if (oldest !== undefined)
|
|
671
741
|
bgParentRun.delete(oldest);
|
|
672
742
|
}
|
|
673
|
-
const
|
|
674
|
-
if (
|
|
743
|
+
const quarantinedHere = ids.some((k) => conflictQuarantine.get(k) === runId);
|
|
744
|
+
if (quarantinedHere)
|
|
745
|
+
return;
|
|
746
|
+
const sameRunHeld = heldRecs.filter((r) => r.runId === runId);
|
|
747
|
+
const heldSlots = new Set(sameRunHeld.map((r) => r.sessionKey ?? DEFAULT_SESSION_KEY));
|
|
748
|
+
if (sameRunHeld.length > 1 && heldSlots.size > 1) {
|
|
749
|
+
ownerSessionConflictCount++;
|
|
750
|
+
const pairOf = (r) => ({
|
|
751
|
+
...(r.sessionId !== undefined ? { sessionId: r.sessionId } : {}),
|
|
752
|
+
...(r.sessionKey !== undefined ? { sessionKey: r.sessionKey } : {}),
|
|
753
|
+
});
|
|
754
|
+
lastOwnerSessionConflict = { taskId, runId, prior: pairOf(sameRunHeld[0]), next: pairOf(sameRunHeld[1]) };
|
|
755
|
+
quarantineRun(ids, runId);
|
|
675
756
|
return;
|
|
676
|
-
|
|
757
|
+
}
|
|
758
|
+
const prior = heldRecs.find((r) => r.runId === runId) ?? heldRecs[0];
|
|
677
759
|
const sameRun = prior?.runId === runId;
|
|
678
760
|
const incoming = typeof sessionId === 'string' && sessionId !== '' ? sessionId : undefined;
|
|
679
761
|
const incomingKey = typeof sessionKey === 'string' && sessionKey !== '' ? sessionKey : undefined;
|
|
@@ -707,16 +789,13 @@ export function recordSubagentOwner(taskId, runId, sessionId, sessionKey) {
|
|
|
707
789
|
const priorSlot = prior?.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
708
790
|
const nextSlot = nextPair.sessionKey ?? DEFAULT_SESSION_KEY;
|
|
709
791
|
if (priorSlot !== nextSlot) {
|
|
710
|
-
|
|
711
|
-
if (conflictQuarantine.size >= MAX_BG_PARENT_RUNS && !conflictQuarantine.has(taskId)) {
|
|
712
|
-
const oldestQ = conflictQuarantine.keys().next().value;
|
|
713
|
-
if (oldestQ !== undefined)
|
|
714
|
-
conflictQuarantine.delete(oldestQ);
|
|
715
|
-
}
|
|
716
|
-
conflictQuarantine.set(taskId, runId);
|
|
792
|
+
quarantineRun(ids, runId);
|
|
717
793
|
return;
|
|
718
794
|
}
|
|
719
795
|
}
|
|
796
|
+
for (const k of ids)
|
|
797
|
+
if (k !== taskId)
|
|
798
|
+
bgParentRun.delete(k);
|
|
720
799
|
bgParentRun.delete(taskId);
|
|
721
800
|
bgParentRun.set(taskId, { runId, ...nextPair });
|
|
722
801
|
}
|
|
@@ -733,14 +812,43 @@ export function recordSubagentOwnerFromProgress(ev, ownerRunId, ownerSessionId,
|
|
|
733
812
|
recordSubagentOwner(o.taskId, ownerRunId, ownerSessionId, ownerSessionKey);
|
|
734
813
|
}
|
|
735
814
|
export function getBgParentRun(taskId) {
|
|
736
|
-
|
|
737
|
-
return bgParentRun.get(taskId)?.runId;
|
|
815
|
+
return getBgParentRunOwner(taskId)?.runId;
|
|
738
816
|
}
|
|
739
817
|
export function getBgParentRunOwner(taskId) {
|
|
740
818
|
if (typeof taskId !== 'string' || taskId === '')
|
|
741
819
|
return undefined;
|
|
742
|
-
|
|
743
|
-
|
|
820
|
+
const live = liveOwnerEntries(sameSubagentIds(taskId));
|
|
821
|
+
const first = live[0];
|
|
822
|
+
if (first === undefined)
|
|
823
|
+
return undefined;
|
|
824
|
+
if (!live.every(([, rec]) => sameOwnerRecord(rec, first[1])))
|
|
825
|
+
return undefined;
|
|
826
|
+
touchLru(bgParentRun, first[0]);
|
|
827
|
+
return first[1];
|
|
828
|
+
}
|
|
829
|
+
function liveOwnerEntries(ids) {
|
|
830
|
+
const out = [];
|
|
831
|
+
for (const k of ids) {
|
|
832
|
+
const rec = bgParentRun.get(k);
|
|
833
|
+
if (rec === undefined)
|
|
834
|
+
continue;
|
|
835
|
+
if (ids.some((q) => conflictQuarantine.get(q) === rec.runId))
|
|
836
|
+
continue;
|
|
837
|
+
out.push([k, rec]);
|
|
838
|
+
}
|
|
839
|
+
return out;
|
|
840
|
+
}
|
|
841
|
+
const sameOwnerRecord = (a, b) => a.runId === b.runId && a.sessionId === b.sessionId && a.sessionKey === b.sessionKey;
|
|
842
|
+
function quarantineRun(ids, runId) {
|
|
843
|
+
for (const k of ids) {
|
|
844
|
+
bgParentRun.delete(k);
|
|
845
|
+
if (conflictQuarantine.size >= MAX_BG_PARENT_RUNS && !conflictQuarantine.has(k)) {
|
|
846
|
+
const oldestQ = conflictQuarantine.keys().next().value;
|
|
847
|
+
if (oldestQ !== undefined)
|
|
848
|
+
conflictQuarantine.delete(oldestQ);
|
|
849
|
+
}
|
|
850
|
+
conflictQuarantine.set(k, runId);
|
|
851
|
+
}
|
|
744
852
|
}
|
|
745
853
|
export function __resetSubagentOwnerLedgerForTests() {
|
|
746
854
|
bgParentRun.clear();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ToolsFlagNames {
|
|
2
|
+
readonly kept: readonly string[];
|
|
3
|
+
readonly excluded: readonly string[];
|
|
4
|
+
readonly bare: boolean;
|
|
5
|
+
readonly detached: readonly string[];
|
|
6
|
+
readonly scoped: readonly string[];
|
|
7
|
+
}
|
|
8
|
+
export declare function parseToolsFlagNames(values: readonly string[]): ToolsFlagNames;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
function readableStrings(values) {
|
|
2
|
+
const out = [];
|
|
3
|
+
try {
|
|
4
|
+
if (!Array.isArray(values))
|
|
5
|
+
return out;
|
|
6
|
+
const n = values.length;
|
|
7
|
+
for (let i = 0; i < n; i++) {
|
|
8
|
+
try {
|
|
9
|
+
const v = values[i];
|
|
10
|
+
if (typeof v === 'string')
|
|
11
|
+
out.push(v);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
function splitToolsFlagTokens(values) {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (const value of values) {
|
|
26
|
+
if (value === '')
|
|
27
|
+
continue;
|
|
28
|
+
let cur = '';
|
|
29
|
+
let inParen = false;
|
|
30
|
+
for (const ch of value) {
|
|
31
|
+
if (ch === '(') {
|
|
32
|
+
inParen = true;
|
|
33
|
+
cur += ch;
|
|
34
|
+
}
|
|
35
|
+
else if (ch === ')') {
|
|
36
|
+
inParen = false;
|
|
37
|
+
cur += ch;
|
|
38
|
+
}
|
|
39
|
+
else if (ch === ',') {
|
|
40
|
+
if (inParen)
|
|
41
|
+
cur += ch;
|
|
42
|
+
else {
|
|
43
|
+
if (cur.trim() !== '')
|
|
44
|
+
out.push(cur.trim());
|
|
45
|
+
cur = '';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (ch === ' ') {
|
|
49
|
+
if (inParen)
|
|
50
|
+
cur += ch;
|
|
51
|
+
else if (cur.trim() !== '') {
|
|
52
|
+
out.push(cur.trim());
|
|
53
|
+
cur = '';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else if (cur !== '' || ch.trim() !== '') {
|
|
57
|
+
cur += ch;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (cur.trim() !== '')
|
|
61
|
+
out.push(cur.trim());
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
export function parseToolsFlagNames(values) {
|
|
66
|
+
const tokens = splitToolsFlagTokens(readableStrings(values));
|
|
67
|
+
const kept = [];
|
|
68
|
+
const excluded = new Set();
|
|
69
|
+
const detached = [];
|
|
70
|
+
const scoped = [];
|
|
71
|
+
let bare = false;
|
|
72
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
73
|
+
let token = tokens[i];
|
|
74
|
+
if (token === undefined)
|
|
75
|
+
continue;
|
|
76
|
+
if (!token.startsWith('!')) {
|
|
77
|
+
kept.push(token);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
let name = token.slice(1);
|
|
81
|
+
if (name === '') {
|
|
82
|
+
const next = tokens[i + 1];
|
|
83
|
+
if (next === undefined || next.startsWith('!') || next.startsWith('(')) {
|
|
84
|
+
bare = true;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
i++;
|
|
88
|
+
detached.push(next);
|
|
89
|
+
token = `!${next}`;
|
|
90
|
+
name = next;
|
|
91
|
+
}
|
|
92
|
+
const paren = name.indexOf('(');
|
|
93
|
+
if (paren === 0) {
|
|
94
|
+
bare = true;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (paren > 0) {
|
|
98
|
+
name = name.slice(0, paren);
|
|
99
|
+
scoped.push(token);
|
|
100
|
+
}
|
|
101
|
+
excluded.add(name);
|
|
102
|
+
}
|
|
103
|
+
return Object.freeze({
|
|
104
|
+
kept: Object.freeze(kept),
|
|
105
|
+
excluded: Object.freeze([...excluded]),
|
|
106
|
+
bare,
|
|
107
|
+
detached: Object.freeze(detached),
|
|
108
|
+
scoped: Object.freeze(scoped),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
@@ -3,12 +3,13 @@ import { classifyTurnWireError, effectiveWireErrorCode, isPreStreamDrainingRejec
|
|
|
3
3
|
import { isSseIdleError } from './sseIdleTriage.js';
|
|
4
4
|
import { isCodeClassifiedGateFailure } from './gateFailureCodes.js';
|
|
5
5
|
import { CORRUPT_ROW_ERROR_CODE, CORRUPT_SESSION_ERROR_CODE, MEMORY_CONTROL_PLANE_CORRUPT, SCENARIO_ASSIGNMENT_UNKNOWN_ERROR_CODE } from './engineErrorCodes.js';
|
|
6
|
-
import { bodyShapeRefusalFromError, bodyShapeRefusalTouchesSettings, fleetLeaseUnavailableContent, fleetLeaseUnavailableFromError, hostPostureRefusalContent, hostPostureRefusalFromError,
|
|
6
|
+
import { admissionWallRefusalContent, admissionWallRefusalFromError, bodyShapeRefusalFromError, bodyShapeRefusalTouchesSettings, fleetLeaseUnavailableContent, fleetLeaseUnavailableFromError, hostPostureRefusalContent, hostPostureRefusalFromError, fieldLimitRefusalContent, fieldLimitRefusalFromError, toolDeclarationRefusalContent, toolDeclarationRefusalFromError, usageWindowExhaustedContent, usageWindowExhaustedFromError, userAttachmentRefusalFromError, } from './wireRefusalCopy.js';
|
|
7
7
|
import { THROWN_SLOT_UNREADABLE, readErrorNumber, readThrownSlot, wireFailureTextsOf } from './wireFailureShape.js';
|
|
8
8
|
import { provablyNotSent } from './engineWireFor.js';
|
|
9
9
|
import { corruptStoredRowContent, scenarioDenyFromError, scenarioNotAllowedContent } from './wireErrorTriage.js';
|
|
10
10
|
import { checkpointUnsupportedVersionContent, checkpointUnsupportedVersionFromError, requireExistingSessionRefusalContent, requireExistingSessionRefusalFromError, resumeContextUnavailableContent, resumeContextUnavailableFromError, resumePolicyBlockContent, resumePolicyBlockFromError, resumeRefusalContent, resumeRefusalFromError, } from './resumeRefusalCopy.js';
|
|
11
11
|
import { resumeReopenContent, resumeReopenFromError } from './hitl/suspendedReopen.js';
|
|
12
|
+
import { prepareRefusalCodeOf, prepareRefusalNoteOf } from './prepareRefusal.js';
|
|
12
13
|
import { isCorruptSessionError } from './corruptSession.js';
|
|
13
14
|
import { corruptSessionContent } from './corruptSessionCopy.js';
|
|
14
15
|
import { inheritEnvRefusalContent, inheritEnvRefusalFromError } from './inheritEnvWire.js';
|
|
@@ -309,25 +310,32 @@ function turnFailureNotesOf(err, verdict, ctx, waitSec, lang) {
|
|
|
309
310
|
lines.push(corruptSessionContent(lang));
|
|
310
311
|
const usageWindow = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone ? null : usageWindowExhaustedFromError(err);
|
|
311
312
|
if (usageWindow)
|
|
312
|
-
lines.push(usageWindowExhaustedContent(usageWindow));
|
|
313
|
+
lines.push(usageWindowExhaustedContent(usageWindow, lang));
|
|
313
314
|
const hostPosture = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone || storedRowWhere !== undefined ? null : hostPostureRefusalFromError(err, sentRequest);
|
|
314
315
|
if (hostPosture)
|
|
315
|
-
lines.push(hostPostureRefusalContent(hostPosture));
|
|
316
|
+
lines.push(hostPostureRefusalContent(hostPosture, lang));
|
|
316
317
|
const inheritEnv = hostPosture ? null : inheritEnvRefusalFromError(err, sentRequest);
|
|
317
318
|
if (inheritEnv)
|
|
318
319
|
lines.push(inheritEnvRefusalContent(inheritEnv, lang));
|
|
319
|
-
const bucket = inheritEnv ? null :
|
|
320
|
+
const bucket = inheritEnv ? null : fieldLimitRefusalFromError(err);
|
|
320
321
|
const toolDecl = toolDeclarationRefusalFromError(err);
|
|
321
322
|
if (toolDecl)
|
|
322
|
-
lines.push(toolDeclarationRefusalContent(toolDecl));
|
|
323
|
+
lines.push(toolDeclarationRefusalContent(toolDecl, lang));
|
|
324
|
+
const prepareCode = toolDecl ? undefined : prepareRefusalCodeOf(err);
|
|
325
|
+
const prepareNote = prepareCode === undefined ? undefined : prepareRefusalNoteOf(prepareCode, userAttachmentRefusalFromError(err) ?? undefined);
|
|
326
|
+
if (prepareNote !== undefined)
|
|
327
|
+
lines.push(prepareNote);
|
|
328
|
+
const wall = admissionWallRefusalFromError(err);
|
|
329
|
+
if (wall)
|
|
330
|
+
lines.push(admissionWallRefusalContent(wall));
|
|
323
331
|
const lease = fleetLeaseUnavailableFromError(err);
|
|
324
332
|
if (lease)
|
|
325
|
-
lines.push(fleetLeaseUnavailableContent(lease));
|
|
333
|
+
lines.push(fleetLeaseUnavailableContent(lease, lang));
|
|
326
334
|
const policyBlock = quota || scenarioDeny || resumeRefusal || resumeReopen || resumeGone || usageWindow || hostPosture ? null : resumePolicyBlockFromError(err);
|
|
327
335
|
if (policyBlock)
|
|
328
336
|
lines.push(resumePolicyBlockContent(policyBlock, lang));
|
|
329
337
|
if (bucket)
|
|
330
|
-
lines.push(
|
|
338
|
+
lines.push(fieldLimitRefusalContent(bucket, lang));
|
|
331
339
|
const settingsRefusal = settingsBodyShapeNote(err, sentRequest, lang);
|
|
332
340
|
if (settingsRefusal !== undefined)
|
|
333
341
|
lines.push(settingsRefusal);
|