@sema-agent/client-core 0.88.0 → 0.89.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 +104 -0
- package/README.md +11 -10
- package/dist/adapter/activeRunSelfHeal.js +4 -2
- package/dist/adapter/downstream/eventToSdkMessage.js +4 -2
- package/dist/adapter/downstream/wiringManifestView.d.ts +9 -0
- package/dist/adapter/downstream/wiringManifestView.js +27 -0
- package/dist/controlRouter.d.ts +7 -1
- package/dist/controlRouter.js +43 -1
- package/dist/disableSkillsWire.d.ts +17 -0
- package/dist/disableSkillsWire.js +52 -0
- package/dist/displayUntrusted.js +122 -55
- package/dist/engineNoticeCodes.d.ts +24 -1
- package/dist/engineNoticeCodes.js +145 -44
- package/dist/generated/engineNoticeTables.d.ts +3 -0
- package/dist/generated/engineNoticeTables.js +108 -0
- package/dist/hitl/toolApprovalWire.d.ts +6 -2
- package/dist/hitl/toolApprovalWire.js +30 -0
- package/dist/hooksWireCaps.js +80 -12
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -3
- package/dist/pluginHooksWire.d.ts +46 -4
- package/dist/pluginHooksWire.js +277 -24
- package/dist/providerRejection.d.ts +6 -0
- package/dist/providerRejection.js +52 -0
- package/dist/request/taskRequest.d.ts +2 -0
- package/dist/request/taskRequest.js +40 -8
- package/dist/runTerminal.d.ts +6 -0
- package/dist/runTerminal.js +23 -0
- package/dist/seam.d.ts +3 -0
- package/dist/seatContract.d.ts +9 -1
- package/dist/seatContract.js +10 -0
- package/dist/subagent/engineSubagentSteer.d.ts +8 -1
- package/dist/subagent/engineSubagentSteer.js +26 -3
- package/docs/INTEGRATION-CLIENTS.md +403 -11
- package/package.json +3 -3
package/dist/controlRouter.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface RunsResourceLike {
|
|
|
17
17
|
export interface ControlClientLike {
|
|
18
18
|
runs: RunsResourceLike;
|
|
19
19
|
}
|
|
20
|
-
export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found';
|
|
20
|
+
export type ControlSafetyCode = 'not_running' | 'invalid_content' | 'queue_full' | 'duplicate_input_id' | 'ambiguous_target' | 'still_running' | 'blocked_by_hook' | 'ledger_unavailable' | 'steering_other' | 'cancel_lost_race' | 'cancel_run_not_running' | 'not_found';
|
|
21
21
|
export declare class ControlSafetyError extends Error {
|
|
22
22
|
readonly code: ControlSafetyCode;
|
|
23
23
|
readonly cause?: unknown | undefined;
|
|
@@ -71,3 +71,9 @@ export interface ErrCodes {
|
|
|
71
71
|
status?: number | undefined;
|
|
72
72
|
}
|
|
73
73
|
export declare function errCodes(e: unknown): ErrCodes;
|
|
74
|
+
export declare function steeringStatusIs4xx(e: object): boolean;
|
|
75
|
+
export interface SteeringRefusedBeforeEngine {
|
|
76
|
+
safety: ControlSafetyCode;
|
|
77
|
+
advice: string;
|
|
78
|
+
}
|
|
79
|
+
export declare function steeringRefusedBeforeEngine(e: object): SteeringRefusedBeforeEngine | undefined;
|
package/dist/controlRouter.js
CHANGED
|
@@ -64,8 +64,9 @@ export class ControlRouter {
|
|
|
64
64
|
catch (e) {
|
|
65
65
|
const verdict = steeringVerdict(e);
|
|
66
66
|
if (verdict !== undefined) {
|
|
67
|
+
const safety = steeringSafetyOf(e, verdict);
|
|
67
68
|
const wireCode = errCodes(e).code ?? errCodes(e).name ?? 'steering.<unknown>';
|
|
68
|
-
throw new ControlSafetyError(`${wireCode} — ${
|
|
69
|
+
throw new ControlSafetyError(`${wireCode} — ${steeringAdviceOf(e, safety) ?? 'steering refused'}`, safety, e);
|
|
69
70
|
}
|
|
70
71
|
throw e;
|
|
71
72
|
}
|
|
@@ -138,12 +139,14 @@ const STEERING_CODE_TO_SAFETY = new Map([
|
|
|
138
139
|
['steering.ambiguous_label', 'ambiguous_target'],
|
|
139
140
|
['steering.still_running', 'still_running'],
|
|
140
141
|
['steering.blocked_by_hook', 'blocked_by_hook'],
|
|
142
|
+
['steering.ledger_unavailable', 'ledger_unavailable'],
|
|
141
143
|
]);
|
|
142
144
|
const STEERING_NAME_TO_SAFETY = new Map([
|
|
143
145
|
['SteeringNotRunningError', 'not_running'],
|
|
144
146
|
['SteeringInvalidContentError', 'invalid_content'],
|
|
145
147
|
['SteeringAmbiguousTargetError', 'ambiguous_target'],
|
|
146
148
|
['SteeringStillRunningError', 'still_running'],
|
|
149
|
+
['SteeringLedgerUnavailableError', 'ledger_unavailable'],
|
|
147
150
|
['SteeringError', 'steering_other'],
|
|
148
151
|
]);
|
|
149
152
|
const STEERING_ADVICE = new Map([
|
|
@@ -154,8 +157,47 @@ const STEERING_ADVICE = new Map([
|
|
|
154
157
|
['ambiguous_target', 'more than one live target matches — address it uniquely (sub-agent: parentToolCallId; workflow: a more specific label); retrying verbatim yields the same result'],
|
|
155
158
|
['still_running', 'the target is STILL RUNNING — steer it instead of resuming, or wait for it to settle (this is the exact opposite of not_running: never collapse the two)'],
|
|
156
159
|
['blocked_by_hook', "this deployment's userPromptSubmit gate refused the input (block, timeout and crash all report this one code, fail-closed) — the input was NOT accepted: no human_input frame, the inputId is not on the ledger, so editing the text and sending again is a normal retry, not a duplicate"],
|
|
160
|
+
['ledger_unavailable', 'the server could not record this steer in its user-input ledger and refused it before anything reached the engine — the input was NOT delivered; resend the same text later (the same Idempotency-Key is fine)'],
|
|
157
161
|
['steering_other', 'an unrecognized steering.* refusal (open set) — the steer did NOT land; log the errorCode verbatim, do not guess its meaning'],
|
|
158
162
|
]);
|
|
163
|
+
const STEERING_OTHER_UNKNOWN_ADVICE = 'an unrecognized steering.* refusal (open set) — treat delivery as unknown (do not resend as if it had certainly been dropped); log the errorCode verbatim, do not guess its meaning';
|
|
164
|
+
export function steeringStatusIs4xx(e) {
|
|
165
|
+
let status;
|
|
166
|
+
try {
|
|
167
|
+
status = errCodes(e).status;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return status !== undefined && status >= 400 && status < 500;
|
|
173
|
+
}
|
|
174
|
+
function steeringAdviceOf(e, safety) {
|
|
175
|
+
if (safety === 'steering_other' && !(typeof e === 'object' && e !== null && steeringStatusIs4xx(e)))
|
|
176
|
+
return STEERING_OTHER_UNKNOWN_ADVICE;
|
|
177
|
+
return STEERING_ADVICE.get(safety);
|
|
178
|
+
}
|
|
179
|
+
const STEERING_REFUSED_BEFORE_ENGINE = new Map([['ledger_unavailable', 503]]);
|
|
180
|
+
export function steeringRefusedBeforeEngine(e) {
|
|
181
|
+
try {
|
|
182
|
+
const { status } = errCodes(e);
|
|
183
|
+
if (status === undefined)
|
|
184
|
+
return undefined;
|
|
185
|
+
const safety = steeringVerdict(e);
|
|
186
|
+
if (safety === undefined || STEERING_REFUSED_BEFORE_ENGINE.get(safety) !== status)
|
|
187
|
+
return undefined;
|
|
188
|
+
const advice = STEERING_ADVICE.get(safety);
|
|
189
|
+
return advice === undefined ? undefined : { safety, advice };
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
function steeringSafetyOf(e, verdict) {
|
|
196
|
+
if (!STEERING_REFUSED_BEFORE_ENGINE.has(verdict))
|
|
197
|
+
return verdict;
|
|
198
|
+
const refused = typeof e === 'object' && e !== null ? steeringRefusedBeforeEngine(e) : undefined;
|
|
199
|
+
return refused !== undefined && refused.safety === verdict ? verdict : 'steering_other';
|
|
200
|
+
}
|
|
159
201
|
function steeringVerdict(e) {
|
|
160
202
|
const { code, name } = errCodes(e);
|
|
161
203
|
if (typeof code === 'string' && code.startsWith('steering.')) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function refuseBadDisableSkills(v: unknown, who: string): void;
|
|
2
|
+
export declare function refuseDisableSkillsConflict(disableSkills: unknown, skills: unknown, agents: unknown, who: string): void;
|
|
3
|
+
type DisableSkillsWithheldCause = 'not_reported' | 'unsupported' | 'unprobed' | 'unreadable';
|
|
4
|
+
export type DisableSkillsDeclaration = {
|
|
5
|
+
readonly field: {
|
|
6
|
+
readonly disableSkills: true;
|
|
7
|
+
};
|
|
8
|
+
readonly withheld?: undefined;
|
|
9
|
+
} | {
|
|
10
|
+
readonly field: Readonly<Record<string, never>>;
|
|
11
|
+
readonly withheld?: {
|
|
12
|
+
readonly cause: DisableSkillsWithheldCause;
|
|
13
|
+
readonly text: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare function disableSkillsDeclaration(want: unknown, baseUrl: string | undefined): DisableSkillsDeclaration;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { engineCapState } from './engineCapsCache.js';
|
|
2
|
+
const KEY = 'disableSkills';
|
|
3
|
+
const shapeOf = (v) => {
|
|
4
|
+
try {
|
|
5
|
+
return v === null ? 'null' : Array.isArray(v) ? 'typeof=object / array' : typeof v === 'string' ? `typeof=string(长 ${v.length})` : `typeof=${typeof v}`;
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return `typeof=${typeof v} / unreadable`;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export function refuseBadDisableSkills(v, who) {
|
|
12
|
+
if (v === undefined || v === null || v === true || v === false)
|
|
13
|
+
return;
|
|
14
|
+
throw new TypeError(`${who}: disableSkills 只接受布尔或缺席(undefined/null)—— 收到 ${shapeOf(v)}。` +
|
|
15
|
+
'这一位是「这一发一只技能都不装」的声明:本层若把坏值折成缺席,这一次运行会照常装上技能而声明人不会知道;' +
|
|
16
|
+
'上游对非布尔值同样拒收。错误文本只报形状,不回显值。');
|
|
17
|
+
}
|
|
18
|
+
const nonEmptyArray = (v) => Array.isArray(v) && v.length > 0;
|
|
19
|
+
const anyAgentCarriesSkills = (agents) => Array.isArray(agents) && agents.some((a) => typeof a === 'object' && a !== null && nonEmptyArray(a.skills));
|
|
20
|
+
export function refuseDisableSkillsConflict(disableSkills, skills, agents, who) {
|
|
21
|
+
if (disableSkills !== true)
|
|
22
|
+
return;
|
|
23
|
+
const inSkills = nonEmptyArray(skills);
|
|
24
|
+
const inAgents = anyAgentCarriesSkills(agents);
|
|
25
|
+
if (!inSkills && !inAgents)
|
|
26
|
+
return;
|
|
27
|
+
const which = inSkills && inAgents ? 'skills 与 agents[].skills' : inSkills ? 'skills' : 'agents[].skills';
|
|
28
|
+
throw new TypeError(`${who}: disableSkills: true(这一发一只技能都不装)与非空的 ${which} 同在 —— 二选一:要关技能就别交技能,要交技能就别带 disableSkills。` +
|
|
29
|
+
'上游对这一组合同样拒收(在任何东西跑起来之前);本层在装配前拒,不让它走一次往返。错误文本只报键名,不回显技能名。');
|
|
30
|
+
}
|
|
31
|
+
const WITHHELD_TEXT = Object.freeze({
|
|
32
|
+
not_reported: 'Skills were not turned off for this request: the connected engine does not report that it can turn them off, and an engine that does not know this setting rejects the whole request, so the setting was left out and this run keeps its usual skills.',
|
|
33
|
+
unsupported: 'Skills were not turned off for this request: the connected engine reports that it cannot turn them off, so the setting was left out and this run keeps its usual skills.',
|
|
34
|
+
unprobed: 'Skills were not turned off for this request: what the connected engine supports has not been read yet, and an engine that does not know this setting rejects the whole request, so the setting was held back and this run keeps its usual skills.',
|
|
35
|
+
unreadable: 'Skills were not turned off for this request: the connected engine reported whether it can turn them off in a form this version cannot read, so the setting was left out and this run keeps its usual skills.',
|
|
36
|
+
});
|
|
37
|
+
const WITHHELD_CAUSE_OF = {
|
|
38
|
+
absent: 'not_reported',
|
|
39
|
+
false: 'unsupported',
|
|
40
|
+
unprobed: 'unprobed',
|
|
41
|
+
non_boolean: 'unreadable',
|
|
42
|
+
};
|
|
43
|
+
export function disableSkillsDeclaration(want, baseUrl) {
|
|
44
|
+
refuseBadDisableSkills(want, 'disableSkillsDeclaration');
|
|
45
|
+
if (want !== true)
|
|
46
|
+
return Object.freeze({ field: Object.freeze({}) });
|
|
47
|
+
const state = engineCapState(baseUrl, KEY);
|
|
48
|
+
if (state === 'true')
|
|
49
|
+
return Object.freeze({ field: Object.freeze({ disableSkills: true }) });
|
|
50
|
+
const cause = WITHHELD_CAUSE_OF[state];
|
|
51
|
+
return Object.freeze({ field: Object.freeze({}), withheld: Object.freeze({ cause, text: WITHHELD_TEXT[cause] }) });
|
|
52
|
+
}
|
package/dist/displayUntrusted.js
CHANGED
|
@@ -66,7 +66,7 @@ const TEXT_BY_KIND = {
|
|
|
66
66
|
};
|
|
67
67
|
const isStructuralKind = (kind) => kind !== 'secret';
|
|
68
68
|
const MARKER_WITH_DOTS = /^[. ]*(?:(?:\u00abredacted(?::[a-z-]{1,16}){0,2}\u00bb|\*{3})[. ]*)+$/;
|
|
69
|
-
function valueIsWholeMarker(S, start, end) {
|
|
69
|
+
function valueIsWholeMarker(S, start, end, tokenInner = true) {
|
|
70
70
|
const text = S.text;
|
|
71
71
|
let k = start;
|
|
72
72
|
while (k < end && (S.dropped(k) || text[k] === '.' || text[k] === ' '))
|
|
@@ -92,11 +92,11 @@ function valueIsWholeMarker(S, start, end) {
|
|
|
92
92
|
if (retired) {
|
|
93
93
|
while (j < end && (S.dropped(j) || S.painted(j) || text[j] === '.' || text[j] === ' '))
|
|
94
94
|
j++;
|
|
95
|
-
return j >= end || credentialWordStartsExactlyAt(text, j) || credentialPairAt(S, j);
|
|
95
|
+
return j >= end || credentialWordStartsExactlyAt(text, j, tokenInner) || credentialPairAt(S, j);
|
|
96
96
|
}
|
|
97
97
|
while (j < end && (S.dropped(j) || S.painted(j)))
|
|
98
98
|
j++;
|
|
99
|
-
return j >= end || !isKeyWordChar(text.charCodeAt(j)) || credentialWordStartsExactlyAt(text, j) || credentialPairAt(S, j);
|
|
99
|
+
return j >= end || !isKeyWordChar(text.charCodeAt(j)) || credentialWordStartsExactlyAt(text, j, tokenInner) || credentialPairAt(S, j);
|
|
100
100
|
}
|
|
101
101
|
const CREDENTIAL_NAME = /(?:(?:access|refresh|id|client|api|x[-_]api|session|auth)[-_]?)?(?:token|key|secret|password|authorization|credential)s?|bearer|basic/iy;
|
|
102
102
|
const LABEL_SEPARATOR = /(?:\\*["'])?[\s\u115F\u1160\u3164\uFFA0\u2800]*[:=\uFF1A\uFF1D]/y;
|
|
@@ -379,7 +379,7 @@ function urlCandidates(text, out, regions, unitPos = () => false, soft) {
|
|
|
379
379
|
let p = end;
|
|
380
380
|
while (p < text.length && (text[p] === VIEW_SEPARATOR || isUnicodeBlank(text.charCodeAt(p))))
|
|
381
381
|
p++;
|
|
382
|
-
if (
|
|
382
|
+
if (nextPairBeyondFragmentAt(text, p))
|
|
383
383
|
break;
|
|
384
384
|
end = p;
|
|
385
385
|
continue;
|
|
@@ -759,7 +759,8 @@ const NAME_BLANK_RANGES = [
|
|
|
759
759
|
const isNameBlank = (cp) => NAME_BLANK_RANGES.some(([a, b]) => cp >= a && cp <= b);
|
|
760
760
|
const isFoldedBlank = (c) => isNameBlank(c) && isRegexSpace(c);
|
|
761
761
|
const isUnicodeBlank = (c) => (c > 0x7f && isRegexSpace(c) && c !== 0xfeff) || isNameBlank(c);
|
|
762
|
-
const SECRET_SCHEME_WORD = /(?:\b|(?<=\\[A-Za-z"']))(bearer|basic)[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]+/gi;
|
|
762
|
+
const SECRET_SCHEME_WORD = /(?:\b|(?<=\\[A-Za-z"']))(bearer|basic|token)[\s:=\uFF1A\uFF1D\u115F\u1160\u3164\uFFA0\u2800]+/gi;
|
|
763
|
+
const schemeWordIsInner = (word, tokenInner) => tokenInner || word.toLowerCase() !== 'token';
|
|
763
764
|
const SECRET_LABELLED_WORD = /(?:\b|(?<=_)|(?<=\\[A-Za-z"']))((?:access[-_ ]?|refresh[-_ ]?|id[-_ ]?|client[-_ ]?|api[-_ ]?|x[-_]api[-_ ]?|session[-_ ]?|auth[-_ ]?)?(?:token|key|secret|password|authorization|credential)s?)(?:\\*["'])?[\s\u115F\u1160\u3164\uFFA0\u2800]*[:=\uFF1A\uFF1D][\s\u115F\u1160\u3164\uFFA0\u2800]*/gi;
|
|
764
765
|
const DIAGNOSTIC_VALUE_WORDS = new Set([
|
|
765
766
|
'missing', 'required', 'invalid', 'expired', 'unauthorized', 'unauthenticated', 'authentication',
|
|
@@ -777,6 +778,37 @@ const SCHEME_FOLLOWER_WORDS = new Set([
|
|
|
777
778
|
'setup', 'plan', 'tier', 'info', 'information', 'support', 'level', 'string', 'config', 'configuration', 'settings',
|
|
778
779
|
'version', 'check', 'validation', 'error', 'errors', 'failed', 'failure', 'credentials', 'user', 'username',
|
|
779
780
|
]);
|
|
781
|
+
const TOKEN_FOLLOWER_WORDS = new Set([
|
|
782
|
+
...SCHEME_FOLLOWER_WORDS,
|
|
783
|
+
'count', 'counts', 'counting', 'counter', 'counters', 'limit', 'limits', 'budget', 'budgets', 'window', 'windows', 'estimate', 'estimates',
|
|
784
|
+
'estimation', 'estimator', 'length', 'size', 'cost', 'costs', 'price', 'pricing', 'rate', 'rates', 'quota', 'quotas', 'cap', 'caps', 'ceiling',
|
|
785
|
+
'threshold', 'total', 'totals', 'accounting', 'allocation', 'consumption', 'overflow', 'savings', 'reduction', 'spend', 'metrics', 'stats',
|
|
786
|
+
'boundary', 'boundaries', 'stream', 'streaming', 'position', 'positions', 'index', 'offset', 'probability', 'probabilities', 'logprob',
|
|
787
|
+
'logprobs', 'sequence', 'encoding', 'tokenizer', 'vocabulary', 'id', 'ids', 'maximum', 'minimum', 'max', 'min', 'ratio', 'table', 'line',
|
|
788
|
+
'lines', 'unit', 'units', 'indices',
|
|
789
|
+
'refresh', 'refreshed', 'refreshes', 'refreshing', 'exchange', 'exchanged', 'endpoint', 'endpoints', 'request', 'requests', 'response',
|
|
790
|
+
'responses', 'store', 'stored', 'storage', 'cache', 'cached', 'caching', 'file', 'files', 'path', 'dir', 'directory', 'source', 'provider',
|
|
791
|
+
'providers', 'supplier', 'helper', 'command', 'env', 'environment', 'variable', 'lifetime', 'ttl', 'expiry', 'expiration', 'expires', 'expiring',
|
|
792
|
+
'rotation', 'rotated', 'revocation', 'revoke', 'introspection', 'verification', 'verified', 'generation', 'generated', 'issuer', 'issued',
|
|
793
|
+
'audience', 'claims', 'scope', 'scopes', 'permission', 'permissions', 'owner', 'name', 'label', 'hash', 'signature', 'payload', 'body',
|
|
794
|
+
'cookie', 'kind', 'types', 'data', 'metadata', 'envelope', 'binding', 'bound', 'renewal', 'minted', 'acquired', 'fetch', 'fetched', 'parsing',
|
|
795
|
+
'parse', 'parsed', 'persisted', 'url', 'urls', 'client', 'argument', 'flag', 'option', 'field', 'governance', 'target',
|
|
796
|
+
'has', 'have', 'had', 'will', 'would', 'could', 'may', 'might', 'does', 'did', 'do', 'doesn', 'isn', 'wasn', 'hasn', 'didn', 'won', 'couldn',
|
|
797
|
+
'wouldn', 'shouldn', 'aren', 'weren', 'haven', 'been', 'being', 'needs', 'need', 'appears', 'seems', 'looks', 'lives', 'stays', 'remains',
|
|
798
|
+
'starts', 'stopped', 'closed', 'arrived', 'surfaced', 'vanished', 'belongs', 'carries', 'contains', 'lacks', 'matches', 'match', 'changed',
|
|
799
|
+
'created', 'deleted', 'removed', 'updated', 'exceeded', 'exceeds', 'exhausted', 'reached', 'returned', 'returns', 'received', 'provided',
|
|
800
|
+
'supplied', 'found', 'used', 'using', 'saved', 'loaded', 'accepted', 'validated', 'passed', 'sent', 'fails', 'works', 'already', 'still',
|
|
801
|
+
'also', 'only', 'never', 'now', 'here', 'there', 'then', 'than', 'so', 'but', 'as', 'if', 'when', 'while', 'until', 'before', 'after',
|
|
802
|
+
'since', 'because', 'via', 'into', 'over', 'under', 'within', 'without', 'per', 'each', 'every', 'any', 'all', 'its', 'which', 'whose',
|
|
803
|
+
'please', 'run', 'try', 'retry', 'see', 'use', 'visit', 'reauthenticate', 'reconnect',
|
|
804
|
+
]);
|
|
805
|
+
function schemeFollowerReleased(scheme, value, afterPathSlash) {
|
|
806
|
+
const word = value.replace(/[.,;:!?)]+$/, '').toLowerCase();
|
|
807
|
+
const isToken = scheme.toLowerCase() === 'token';
|
|
808
|
+
if (isToken && afterPathSlash && /^\d{3}$/.test(word))
|
|
809
|
+
return true;
|
|
810
|
+
return (isToken ? TOKEN_FOLLOWER_WORDS : SCHEME_FOLLOWER_WORDS).has(word);
|
|
811
|
+
}
|
|
780
812
|
const AUTH_SCHEME_WORDS = new Set([
|
|
781
813
|
'bearer', 'basic', 'digest', 'token', 'bot', 'ssws', 'api-key', 'apikey', 'key', 'hmac', 'oauth', 'oauth2', 'jwt',
|
|
782
814
|
'negotiate', 'ntlm', 'hawk', 'mac', 'dsn', 'splunk', 'sapisidhash', 'googlelogin', 'aws', 'client-id', 'pat',
|
|
@@ -786,9 +818,11 @@ const BARE_VALUE_STOP_CHARS = new Set([',', ';', '"', "'", '\\', '(', ')', '[',
|
|
|
786
818
|
const isBareValueStop = (ch) => ch <= ' ' || BARE_VALUE_STOP_CHARS.has(ch);
|
|
787
819
|
class InnerWordIndex {
|
|
788
820
|
text;
|
|
821
|
+
tokenInner;
|
|
789
822
|
probes;
|
|
790
|
-
constructor(text) {
|
|
823
|
+
constructor(text, tokenInner = true) {
|
|
791
824
|
this.text = text;
|
|
825
|
+
this.tokenInner = tokenInner;
|
|
792
826
|
this.probes = [
|
|
793
827
|
{ re: new RegExp(SECRET_LABELLED_WORD.source, SECRET_LABELLED_WORD.flags), scheme: false, from: -1, hit: null },
|
|
794
828
|
{ re: new RegExp(SECRET_SCHEME_WORD.source, SECRET_SCHEME_WORD.flags), scheme: true, from: -1, hit: null },
|
|
@@ -800,7 +834,11 @@ class InnerWordIndex {
|
|
|
800
834
|
const reusable = p.from !== -1 && q >= p.from && (p.hit === null || q <= p.hit.start);
|
|
801
835
|
if (!reusable) {
|
|
802
836
|
p.re.lastIndex = q;
|
|
803
|
-
|
|
837
|
+
let m = p.re.exec(this.text);
|
|
838
|
+
while (m !== null && p.scheme && !schemeWordIsInner(m[1] ?? '', this.tokenInner)) {
|
|
839
|
+
p.re.lastIndex = m.index + 1;
|
|
840
|
+
m = p.re.exec(this.text);
|
|
841
|
+
}
|
|
804
842
|
p.from = q;
|
|
805
843
|
if (m === null)
|
|
806
844
|
p.hit = null;
|
|
@@ -885,7 +923,7 @@ function scanSecretValue(text, from, idx) {
|
|
|
885
923
|
let p = j;
|
|
886
924
|
while (p < text.length && text[p] === VIEW_SEPARATOR)
|
|
887
925
|
p++;
|
|
888
|
-
if (credentialWordStartsNear(text, p))
|
|
926
|
+
if (credentialWordStartsNear(text, p, idx?.tokenInner ?? true))
|
|
889
927
|
break;
|
|
890
928
|
j = p;
|
|
891
929
|
continue;
|
|
@@ -935,6 +973,22 @@ function isTokenCountLabel(text, at, label) {
|
|
|
935
973
|
const lastSep = Math.max(head.lastIndexOf('_'), head.lastIndexOf('-'));
|
|
936
974
|
return TOKEN_COUNT_HEAD_WORDS.has(head.slice(lastSep + 1));
|
|
937
975
|
}
|
|
976
|
+
function isParserDiagnosticToken(text, at, label) {
|
|
977
|
+
if (label.toLowerCase() !== 'token' || at < 1)
|
|
978
|
+
return false;
|
|
979
|
+
if (text.charAt(at - 1) !== ' ')
|
|
980
|
+
return false;
|
|
981
|
+
const head = 'unexpected';
|
|
982
|
+
const start = at - 1 - head.length;
|
|
983
|
+
if (start < 0 || text.slice(start, at - 1).toLowerCase() !== head)
|
|
984
|
+
return false;
|
|
985
|
+
if (start === 0)
|
|
986
|
+
return true;
|
|
987
|
+
const before = text.charAt(start - 1);
|
|
988
|
+
if (!/[A-Za-z0-9_]/.test(before))
|
|
989
|
+
return true;
|
|
990
|
+
return start >= 2 && text.charAt(start - 2) === '\\' && /[A-Za-z"']/.test(before);
|
|
991
|
+
}
|
|
938
992
|
const BACKTICKED_CREDENTIAL_NAME = /^\x60[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+\x60[.,;:!?)]*$/;
|
|
939
993
|
const CREDENTIAL_NAME_SEGMENTS = new Set([
|
|
940
994
|
'KEY', 'KEYS', 'TOKEN', 'TOKENS', 'SECRET', 'SECRETS', 'PASSWORD', 'PASSWD', 'PWD', 'CREDENTIAL', 'CREDENTIALS',
|
|
@@ -961,29 +1015,41 @@ function labelStartsAt(text, at) {
|
|
|
961
1015
|
re.lastIndex = at;
|
|
962
1016
|
return re.test(text);
|
|
963
1017
|
}
|
|
964
|
-
function credentialWordStartsAt(text, at) {
|
|
1018
|
+
function credentialWordStartsAt(text, at, tokenInner = true) {
|
|
965
1019
|
if (at >= text.length)
|
|
966
1020
|
return false;
|
|
967
|
-
if (credentialWordStartsExactlyAt(text, at))
|
|
1021
|
+
if (credentialWordStartsExactlyAt(text, at, tokenInner))
|
|
968
1022
|
return true;
|
|
969
1023
|
let k = at;
|
|
970
1024
|
while (k < text.length && text.charCodeAt(k) === 0x5c)
|
|
971
1025
|
k++;
|
|
972
1026
|
if (text[k] === '"' || text[k] === "'")
|
|
973
1027
|
k++;
|
|
974
|
-
return k > at && credentialWordStartsExactlyAt(text, k);
|
|
1028
|
+
return k > at && credentialWordStartsExactlyAt(text, k, tokenInner);
|
|
975
1029
|
}
|
|
976
|
-
function credentialWordStartsExactlyAt(text, at) {
|
|
1030
|
+
function credentialWordStartsExactlyAt(text, at, tokenInner = true) {
|
|
977
1031
|
if (at >= text.length)
|
|
978
1032
|
return false;
|
|
979
1033
|
if (labelStartsAt(text, at))
|
|
980
1034
|
return true;
|
|
981
1035
|
const re = new RegExp(SECRET_SCHEME_WORD.source, 'iy');
|
|
982
1036
|
re.lastIndex = at;
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1037
|
+
const m = re.exec(text);
|
|
1038
|
+
return m !== null && schemeWordIsInner(m[1] ?? '', tokenInner);
|
|
1039
|
+
}
|
|
1040
|
+
function credentialWordStartsNear(text, at, tokenInner = true) {
|
|
1041
|
+
return credentialWordStartsAt(text, at, tokenInner) || credentialWordStartsAt(text, at + 1, tokenInner);
|
|
1042
|
+
}
|
|
1043
|
+
function innerWordMatchAt(text, at, tokenInner) {
|
|
1044
|
+
const lab = new RegExp(SECRET_LABELLED_WORD.source, 'iy');
|
|
1045
|
+
lab.lastIndex = at;
|
|
1046
|
+
const m = lab.exec(text);
|
|
1047
|
+
if (m !== null)
|
|
1048
|
+
return m;
|
|
1049
|
+
const sch = new RegExp(SECRET_SCHEME_WORD.source, 'iy');
|
|
1050
|
+
sch.lastIndex = at;
|
|
1051
|
+
const s = sch.exec(text);
|
|
1052
|
+
return s !== null && schemeWordIsInner(s[1] ?? '', tokenInner) ? s : null;
|
|
987
1053
|
}
|
|
988
1054
|
function nextPairBeyondFragmentAt(text, at) {
|
|
989
1055
|
for (const p of [at, at + 1]) {
|
|
@@ -1195,13 +1261,15 @@ function addressExtentEnd(text, from) {
|
|
|
1195
1261
|
}
|
|
1196
1262
|
return end;
|
|
1197
1263
|
}
|
|
1198
|
-
function trailingLabelStart(text, from, end) {
|
|
1264
|
+
function trailingLabelStart(text, from, end, tokenInner = true) {
|
|
1199
1265
|
const window = text.slice(from, Math.min(text.length, end + 12));
|
|
1200
1266
|
const segLen = end - from;
|
|
1201
1267
|
let best = -1;
|
|
1202
1268
|
for (const src of [SECRET_SCHEME_WORD, SECRET_LABELLED_WORD]) {
|
|
1203
1269
|
const re = new RegExp(src.source, src.flags);
|
|
1204
1270
|
for (let hit = re.exec(window); hit !== null && hit.index < segLen; hit = re.exec(window)) {
|
|
1271
|
+
if (src === SECRET_SCHEME_WORD && !schemeWordIsInner(hit[1] ?? '', tokenInner))
|
|
1272
|
+
continue;
|
|
1205
1273
|
if (hit.index + hit[0].length >= segLen && (best === -1 || hit.index < best))
|
|
1206
1274
|
best = hit.index;
|
|
1207
1275
|
}
|
|
@@ -1257,14 +1325,8 @@ function isTokenCountAt(text, at) {
|
|
|
1257
1325
|
return m !== null && isTokenCountLabel(text, at, m[1] ?? '');
|
|
1258
1326
|
}
|
|
1259
1327
|
function innerWordHasValue(text, at, idx) {
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
re.lastIndex = at;
|
|
1263
|
-
const m = re.exec(text);
|
|
1264
|
-
if (m !== null)
|
|
1265
|
-
return scanSecretValue(text, at + m[0].length, idx) !== null;
|
|
1266
|
-
}
|
|
1267
|
-
return false;
|
|
1328
|
+
const m = innerWordMatchAt(text, at, idx.tokenInner);
|
|
1329
|
+
return m !== null && scanSecretValue(text, at + m[0].length, idx) !== null;
|
|
1268
1330
|
}
|
|
1269
1331
|
function quoteSwallowedBefore(S, at) {
|
|
1270
1332
|
let k = at - 1;
|
|
@@ -1411,11 +1473,13 @@ function quotedAddressEnd(S, from, to) {
|
|
|
1411
1473
|
}
|
|
1412
1474
|
return to;
|
|
1413
1475
|
}
|
|
1414
|
-
function labelCandidates(S,
|
|
1476
|
+
function labelCandidates(S, pass, regions, out) {
|
|
1415
1477
|
const text = S.text;
|
|
1416
1478
|
const unitAt = (k) => S.unitAt(k);
|
|
1417
|
-
const
|
|
1418
|
-
const
|
|
1479
|
+
const re = pass === 'label' ? SECRET_LABELLED_WORD : SECRET_SCHEME_WORD;
|
|
1480
|
+
const schemePass = pass !== 'label';
|
|
1481
|
+
const tokenPass = pass === 'token';
|
|
1482
|
+
const idx = new InnerWordIndex(text, tokenPass);
|
|
1419
1483
|
const extensionCache = new Map();
|
|
1420
1484
|
let stops;
|
|
1421
1485
|
const push = (start, end, kindText, te = -1, cls) => {
|
|
@@ -1482,7 +1546,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1482
1546
|
cut--;
|
|
1483
1547
|
if (cut > p) {
|
|
1484
1548
|
const rest = withoutSeparators(text.slice(p, cut));
|
|
1485
|
-
if (rest.trim() !== '' && !valueIsWholeMarker(S, p, cut) && !isDiagnosticValue(rest))
|
|
1549
|
+
if (rest.trim() !== '' && !valueIsWholeMarker(S, p, cut, idx.tokenInner) && !isDiagnosticValue(rest))
|
|
1486
1550
|
push(p, cut, REDACTED_SECRET);
|
|
1487
1551
|
}
|
|
1488
1552
|
if (markerHit && marker !== null) {
|
|
@@ -1492,14 +1556,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1492
1556
|
}
|
|
1493
1557
|
if (!hasInner || inner === null)
|
|
1494
1558
|
return;
|
|
1495
|
-
const
|
|
1496
|
-
lab.lastIndex = inner.start;
|
|
1497
|
-
let m = lab.exec(text);
|
|
1498
|
-
if (m === null) {
|
|
1499
|
-
const sch = new RegExp(SECRET_SCHEME_WORD.source, 'iy');
|
|
1500
|
-
sch.lastIndex = inner.start;
|
|
1501
|
-
m = sch.exec(text);
|
|
1502
|
-
}
|
|
1559
|
+
const m = innerWordMatchAt(text, inner.start, idx.tokenInner);
|
|
1503
1560
|
if (m === null)
|
|
1504
1561
|
return;
|
|
1505
1562
|
const after = inner.start + m[0].length;
|
|
@@ -1533,14 +1590,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1533
1590
|
const close = text.indexOf(q, from);
|
|
1534
1591
|
outerEnd = close === -1 ? text.length : close;
|
|
1535
1592
|
}
|
|
1536
|
-
const
|
|
1537
|
-
lab.lastIndex = at;
|
|
1538
|
-
let m = lab.exec(text);
|
|
1539
|
-
if (m === null) {
|
|
1540
|
-
const sch = new RegExp(SECRET_SCHEME_WORD.source, 'iy');
|
|
1541
|
-
sch.lastIndex = at;
|
|
1542
|
-
m = sch.exec(text);
|
|
1543
|
-
}
|
|
1593
|
+
const m = innerWordMatchAt(text, at, idx.tokenInner);
|
|
1544
1594
|
if (m === null)
|
|
1545
1595
|
return;
|
|
1546
1596
|
const inner = { start: at };
|
|
@@ -1583,10 +1633,16 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1583
1633
|
re.lastIndex = 0;
|
|
1584
1634
|
for (let hit = re.exec(text); hit !== null; hit = re.exec(text)) {
|
|
1585
1635
|
const label = hit[1] ?? '';
|
|
1636
|
+
if (schemePass && (label.toLowerCase() === 'token') !== tokenPass)
|
|
1637
|
+
continue;
|
|
1586
1638
|
if (isTokenCountLabel(text, hit.index, label))
|
|
1587
1639
|
continue;
|
|
1640
|
+
if (schemePass && isParserDiagnosticToken(text, hit.index, label))
|
|
1641
|
+
continue;
|
|
1642
|
+
if (schemePass && labelStartsAt(text, hit.index))
|
|
1643
|
+
continue;
|
|
1588
1644
|
const from = hit.index + hit[0].length;
|
|
1589
|
-
if (credentialWordStartsAt(text, from)) {
|
|
1645
|
+
if (credentialWordStartsAt(text, from, idx.tokenInner)) {
|
|
1590
1646
|
pushInnerRemainder(from);
|
|
1591
1647
|
re.lastIndex = from;
|
|
1592
1648
|
continue;
|
|
@@ -1640,7 +1696,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1640
1696
|
continue;
|
|
1641
1697
|
}
|
|
1642
1698
|
}
|
|
1643
|
-
if (valueIsWholeMarker(S, v.start, v.end)) {
|
|
1699
|
+
if (valueIsWholeMarker(S, v.start, v.end, idx.tokenInner)) {
|
|
1644
1700
|
re.lastIndex = quoted ? from : v.end;
|
|
1645
1701
|
continue;
|
|
1646
1702
|
}
|
|
@@ -1672,7 +1728,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1672
1728
|
v.end = a;
|
|
1673
1729
|
}
|
|
1674
1730
|
if (!quoted) {
|
|
1675
|
-
const trailing = trailingLabelStart(text, v.start, v.end);
|
|
1731
|
+
const trailing = trailingLabelStart(text, v.start, v.end, idx.tokenInner);
|
|
1676
1732
|
if (trailing > 0 && innerWordHasValue(text, v.start + trailing, idx)) {
|
|
1677
1733
|
let e = v.start + trailing;
|
|
1678
1734
|
while (e > v.start && (isCutDelimiter(text.charAt(e - 1)) || text[e - 1] === VIEW_SEPARATOR))
|
|
@@ -1691,7 +1747,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1691
1747
|
re.lastIndex = quoted ? from : v.end;
|
|
1692
1748
|
continue;
|
|
1693
1749
|
}
|
|
1694
|
-
if (schemePass && !quoted &&
|
|
1750
|
+
if (schemePass && !quoted && schemeFollowerReleased(label, value, text.charCodeAt(hit.index - 1) === 0x2f)) {
|
|
1695
1751
|
re.lastIndex = v.end;
|
|
1696
1752
|
continue;
|
|
1697
1753
|
}
|
|
@@ -1730,7 +1786,7 @@ function labelCandidates(S, re, regions, out) {
|
|
|
1730
1786
|
if (isAddressShaped(value, rawValue) || rawAddress) {
|
|
1731
1787
|
const extentFrom = forbiddenAddress ? forbiddenAt : v.start;
|
|
1732
1788
|
let end = quoted ? quotedAddressEnd(S, extentFrom, v.end) : addressExtentEnd(text, extentFrom);
|
|
1733
|
-
const trailing = trailingLabelStart(text, v.start, end);
|
|
1789
|
+
const trailing = trailingLabelStart(text, v.start, end, idx.tokenInner);
|
|
1734
1790
|
if (trailing !== -1)
|
|
1735
1791
|
end = v.start + trailing;
|
|
1736
1792
|
if (gluedToSingleUnit(v.start, hit.index, unitAt) || userinfoHostHidden(text, v.start, unitAt)) {
|
|
@@ -2357,7 +2413,7 @@ function joinedSurface(raw, V, spacesKept = false, M = null) {
|
|
|
2357
2413
|
function screenSurfaces(text, o) {
|
|
2358
2414
|
const face = o.face;
|
|
2359
2415
|
if (face === null)
|
|
2360
|
-
return { surfaces: [], rawSoft: null, rawPlain: null };
|
|
2416
|
+
return { surfaces: [], rawSoft: null, rawPlain: null, contents: [] };
|
|
2361
2417
|
const unsafe = face.unsafe === null ? null : new RegExp(face.unsafe.source, 'u');
|
|
2362
2418
|
const keepBlanks = face.keepBlanks === true;
|
|
2363
2419
|
const chars = [];
|
|
@@ -2431,7 +2487,7 @@ function screenSurfaces(text, o) {
|
|
|
2431
2487
|
i += w;
|
|
2432
2488
|
}
|
|
2433
2489
|
if (!changed)
|
|
2434
|
-
return { surfaces: [], rawSoft: null, rawPlain: null };
|
|
2490
|
+
return { surfaces: [], rawSoft: null, rawPlain: null, contents: [] };
|
|
2435
2491
|
const screen = chars.join('');
|
|
2436
2492
|
const M = { ps: Int32Array.from(ps), pe: Int32Array.from(pe), pdot: Uint8Array.from(pdot), rawDot };
|
|
2437
2493
|
const V = buildScanView(screen, o);
|
|
@@ -2451,7 +2507,8 @@ function screenSurfaces(text, o) {
|
|
|
2451
2507
|
const joinedSpaced = o.escapeSpaces !== null ? joinedSurface(text, V, true, M) : null;
|
|
2452
2508
|
if (joinedSpaced !== null)
|
|
2453
2509
|
out.push(joinedSpaced);
|
|
2454
|
-
|
|
2510
|
+
const contents = V.contents.map(([a, b]) => ({ sub: screen.slice(a, b), rawAt: (k) => M.ps[a + k] ?? 0, rawEndAt: (k) => M.pe[a + k] ?? 0 }));
|
|
2511
|
+
return { surfaces: out, rawSoft, rawPlain, contents };
|
|
2455
2512
|
}
|
|
2456
2513
|
function finalIsStructural(text, at) {
|
|
2457
2514
|
if (text.charCodeAt(at) !== 0x5c)
|
|
@@ -2735,8 +2792,9 @@ function collectCandidates(text, o, nested) {
|
|
|
2735
2792
|
if (o.words) {
|
|
2736
2793
|
editsToCandidates(pemEdits(S, (blk) => { if (S === regionSurface)
|
|
2737
2794
|
pemBlocksSeen.push(pemBlockToRaw(S, blk)); }), 'pem', cands);
|
|
2738
|
-
labelCandidates(S,
|
|
2739
|
-
labelCandidates(S,
|
|
2795
|
+
labelCandidates(S, 'scheme', regions, cands);
|
|
2796
|
+
labelCandidates(S, 'token', regions, cands);
|
|
2797
|
+
labelCandidates(S, 'label', regions, cands);
|
|
2740
2798
|
editsToCandidates(authParamEdits(S.text), 'param', cands);
|
|
2741
2799
|
editsToCandidates(proseLiteralEdits(S.text), 'prose', cands);
|
|
2742
2800
|
}
|
|
@@ -2754,6 +2812,15 @@ function collectCandidates(text, o, nested) {
|
|
|
2754
2812
|
raw.push({ start: a + iv.start, end: a + iv.end, kind: iv.kind, cls: 'nested', tokenEnd: a + iv.end, pretrimmed: true });
|
|
2755
2813
|
}
|
|
2756
2814
|
}
|
|
2815
|
+
for (const c of screen.contents) {
|
|
2816
|
+
const inner = collectCandidates(c.sub, o, true);
|
|
2817
|
+
for (const iv of resolveCandidates(c.sub, inner.cands, inner.rawUnit, inner.rawDot, o.words ? pemRegions(inner.pemBlocksSeen) : [], inner.rawSoft, inner.rawPlain)) {
|
|
2818
|
+
const start = c.rawAt(iv.start);
|
|
2819
|
+
const end = c.rawEndAt(iv.end - 1);
|
|
2820
|
+
if (end > start)
|
|
2821
|
+
raw.push({ start, end, kind: iv.kind, cls: 'nested', tokenEnd: end, pretrimmed: true });
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2757
2824
|
}
|
|
2758
2825
|
return { cands: raw, rawUnit: V.rawUnit, rawDot: screen.surfaces[0]?.rawDot ?? null, rawSoft: screen.rawSoft, rawPlain: screen.rawPlain, pemBlocksSeen };
|
|
2759
2826
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { CORE_TOOL_TURN_INCOMPLETE_CAUSES, CORE_USER_STEER_UNDRAINED_CAUSES } from './generated/engineNoticeTables.js';
|
|
1
2
|
export type NoticeAudience = 'user' | 'operator';
|
|
2
3
|
export declare const ENGINE_NOTICE_CODES: readonly string[];
|
|
3
|
-
export declare const SERVER_NOTICE_AUDIENCE: Readonly<Record<string, NoticeAudience>>;
|
|
4
4
|
export declare function engineNoticeInCatalog(code: unknown): boolean;
|
|
5
5
|
export declare const ENGINE_NOTICE_AUDIENCE: Readonly<Record<string, NoticeAudience>>;
|
|
6
6
|
export declare function noticeAudienceOf(code: unknown): NoticeAudience;
|
|
@@ -155,6 +155,26 @@ export interface ModelUnreachableFactsView {
|
|
|
155
155
|
sessionId: string;
|
|
156
156
|
}
|
|
157
157
|
export declare function readModelUnreachable(notice: unknown): ModelUnreachableFactsView | undefined;
|
|
158
|
+
export type ToolTurnIncompleteCause = (typeof CORE_TOOL_TURN_INCOMPLETE_CAUSES)[number];
|
|
159
|
+
export interface ToolTurnIncompleteFactsView {
|
|
160
|
+
cause: string;
|
|
161
|
+
count: number;
|
|
162
|
+
toolCallIds?: readonly string[];
|
|
163
|
+
sessionId: string;
|
|
164
|
+
runId: string;
|
|
165
|
+
}
|
|
166
|
+
export declare function readToolTurnIncomplete(notice: unknown): ToolTurnIncompleteFactsView | undefined;
|
|
167
|
+
export type UserSteerUndrainedCause = (typeof CORE_USER_STEER_UNDRAINED_CAUSES)[number];
|
|
168
|
+
export interface UserInputUndrainedFactsView {
|
|
169
|
+
kind: 'steer' | 'followUp';
|
|
170
|
+
count: number;
|
|
171
|
+
cause?: string;
|
|
172
|
+
taskId?: string;
|
|
173
|
+
sessionId?: string;
|
|
174
|
+
runId?: string;
|
|
175
|
+
}
|
|
176
|
+
export declare function readUserInputUndrained(notice: unknown): UserInputUndrainedFactsView | undefined;
|
|
177
|
+
export declare function userInputUndrainedNotice(facts: Pick<UserInputUndrainedFactsView, 'kind' | 'count' | 'cause'>): string | undefined;
|
|
158
178
|
export declare const ENGINE_NOTICE_FACT_READERS: Readonly<{
|
|
159
179
|
readonly 'mcp.injection_dropped': typeof readMcpInjectionDrop;
|
|
160
180
|
readonly 'delegation.ask_unresolvable': typeof readAskUnresolvable;
|
|
@@ -173,6 +193,9 @@ export declare const ENGINE_NOTICE_FACT_READERS: Readonly<{
|
|
|
173
193
|
readonly 'resume.legacy_mode_seed_migrated': typeof readLegacyModeSeedMigrated;
|
|
174
194
|
readonly 'context.tool_turn_repaired': typeof readToolTurnRepaired;
|
|
175
195
|
readonly 'server.model_unreachable': typeof readModelUnreachable;
|
|
196
|
+
readonly 'task.tool_turn_incomplete': typeof readToolTurnIncomplete;
|
|
197
|
+
readonly 'task.user_steer_undrained': typeof readUserInputUndrained;
|
|
198
|
+
readonly 'task.user_followup_undrained': typeof readUserInputUndrained;
|
|
176
199
|
}>;
|
|
177
200
|
type FactReaderTable = typeof ENGINE_NOTICE_FACT_READERS;
|
|
178
201
|
export type EngineNoticeFactsCode = keyof FactReaderTable;
|