@sema-agent/client-core 0.91.0 → 0.92.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 +172 -0
- package/README.md +31 -21
- package/dist/adapt/arms.js +4 -12
- package/dist/adapt/panelTasks.d.ts +0 -2
- package/dist/adapt/panelTasks.js +6 -26
- package/dist/adapt.js +2 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +0 -2
- package/dist/adapter/activeRunSelfHeal.js +5 -27
- package/dist/adapter/downstream/terminalToSdkResult.js +16 -7
- package/dist/adapter/runStream.js +3 -1
- package/dist/askSurvivesStandingAnswer.d.ts +4 -1
- package/dist/askSurvivesStandingAnswer.js +13 -0
- package/dist/autoModeUnavailable.js +3 -2
- package/dist/cloudConfigWireCaps.js +5 -4
- package/dist/compensations.js +5 -5
- package/dist/controlRouter.d.ts +23 -23
- package/dist/controlRouter.js +114 -49
- package/dist/coreValuePorts.d.ts +4 -2
- package/dist/coreValuePorts.js +5 -0
- package/dist/decideFailureNote.js +4 -2
- package/dist/decideReceipt.d.ts +9 -0
- package/dist/decideReceipt.js +62 -1
- package/dist/displayUntrusted.js +2 -1
- package/dist/effectiveFacts.d.ts +14 -4
- package/dist/effectiveFacts.js +45 -5
- package/dist/engineAgentAbsence.js +2 -1
- package/dist/engineCapReader.js +16 -10
- package/dist/engineCapsCache.d.ts +2 -0
- package/dist/engineCapsCache.js +13 -2
- package/dist/engineErrorCodes.d.ts +14 -0
- package/dist/engineErrorCodes.js +37 -0
- package/dist/engineNoticeCodes.d.ts +14 -0
- package/dist/engineNoticeCodes.js +71 -0
- package/dist/executionLaneCapability.js +2 -0
- package/dist/gateOutcome.js +2 -17
- package/dist/gateVocabulary.d.ts +2 -4
- package/dist/gateVocabulary.js +3 -11
- package/dist/generated/engineFactTables.d.ts +16 -1
- package/dist/generated/engineFactTables.js +81 -0
- package/dist/generated/engineNoticeTables.js +3 -0
- package/dist/generated/settingsSchemaTables.d.ts +8 -0
- package/dist/generated/settingsSchemaTables.js +40 -0
- package/dist/hitl/allowRuleShadow.d.ts +21 -0
- package/dist/hitl/allowRuleShadow.js +167 -0
- package/dist/hitl/askClassPair.d.ts +14 -0
- package/dist/hitl/askClassPair.js +42 -0
- package/dist/hitl/askGateWire.js +1 -0
- package/dist/hitl/askSurvivesPosture.d.ts +5 -0
- package/dist/hitl/askSurvivesPosture.js +17 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +21 -0
- package/dist/hitl/automaticAnswerVerdict.js +143 -0
- package/dist/hitl/crashConverged.d.ts +1 -0
- package/dist/hitl/crashConverged.js +1 -1
- package/dist/hitl/frameRouter.d.ts +2 -0
- package/dist/hitl/frameRouter.js +66 -14
- package/dist/hitl/gateLedger.d.ts +6 -0
- package/dist/hitl/gateLedger.js +34 -5
- package/dist/hitl/hitlHostSurface.d.ts +2 -0
- package/dist/hitl/hitlHostSurface.js +7 -0
- package/dist/hitl/livePendingAsk.js +24 -5
- package/dist/hitl/parkResolver.js +3 -1
- package/dist/hitl/persistedRulesWire.d.ts +4 -1
- package/dist/hitl/persistedRulesWire.js +9 -2
- package/dist/hitl/planReviewWire.js +2 -2
- package/dist/hitl/replayedApproval.d.ts +21 -0
- package/dist/hitl/replayedApproval.js +89 -0
- package/dist/hitl/sessionPolicyDeliverable.js +20 -2
- package/dist/hitl/sessionPolicyWire.d.ts +8 -0
- package/dist/hitl/sessionPolicyWire.js +12 -2
- package/dist/hitl/toolApprovalWire.d.ts +6 -1
- package/dist/hitl/toolApprovalWire.js +20 -40
- package/dist/hookMatcherVerdict.js +2 -1
- package/dist/humanTurn.js +3 -4
- package/dist/index.d.ts +15 -5
- package/dist/index.js +12 -3
- package/dist/inheritEnvWire.js +3 -4
- package/dist/mcpLiveness.js +2 -1
- package/dist/memoryVerbsWire.d.ts +1 -1
- package/dist/memoryVerbsWire.js +3 -0
- package/dist/model/catalog.js +2 -1
- package/dist/model/providerPresets.d.ts +3 -1
- package/dist/model/tierVocabulary.d.ts +2 -1
- package/dist/model/tierVocabulary.js +3 -8
- package/dist/peerFrames.js +2 -2
- package/dist/permissionRuleIssue.js +9 -6
- package/dist/permissionsDeclaration.d.ts +7 -1
- package/dist/permissionsDeclaration.js +29 -20
- package/dist/pluginHooksWire.js +2 -11
- package/dist/promptProfileWireCaps.d.ts +2 -1
- package/dist/protocolSegment.d.ts +9 -0
- package/dist/protocolSegment.js +28 -0
- package/dist/request/taskRequest.js +1 -15
- package/dist/ruleCompileVerdict.d.ts +2 -0
- package/dist/ruleCompileVerdict.js +13 -0
- package/dist/ruleRemovalConsequence.d.ts +2 -1
- package/dist/runCancelContext.d.ts +12 -0
- package/dist/runCancelContext.js +83 -1
- package/dist/seam.js +1 -1
- package/dist/seatContract.d.ts +2 -1
- package/dist/sessionMemoryStatus.d.ts +2 -4
- package/dist/sessionSyncFileHistoryCapability.d.ts +18 -0
- package/dist/sessionSyncFileHistoryCapability.js +50 -0
- package/dist/skillToolListsCapability.d.ts +18 -0
- package/dist/skillToolListsCapability.js +50 -0
- package/dist/sqlEngineCapability.js +1 -8
- package/dist/steerPriorityCapability.d.ts +18 -0
- package/dist/steerPriorityCapability.js +80 -0
- package/dist/steerReceipt.d.ts +9 -0
- package/dist/steerReceipt.js +25 -0
- package/dist/subagent/engineSubagentSteer.js +2 -9
- package/dist/supportFloor.js +2 -2
- package/dist/toolResult.d.ts +8 -0
- package/dist/toolResult.js +47 -3
- package/dist/types/engineState.d.ts +2 -12
- package/dist/userInvokedSkillsCapability.d.ts +18 -0
- package/dist/userInvokedSkillsCapability.js +50 -0
- package/dist/wireFailureShape.d.ts +2 -0
- package/dist/wireFailureShape.js +4 -0
- package/dist/workflowsJournalCapability.d.ts +18 -0
- package/dist/workflowsJournalCapability.js +50 -0
- package/dist/writeProtectionCapability.d.ts +2 -4
- package/docs/INTEGRATION-CLIENTS.md +624 -12
- package/package.json +2 -2
package/dist/pluginHooksWire.js
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { displayUntrusted } from './displayUntrusted.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
'PostToolUse',
|
|
5
|
-
'PostToolUseFailure',
|
|
6
|
-
'PostToolBatch',
|
|
7
|
-
'PreCompact',
|
|
8
|
-
'PostCompact',
|
|
9
|
-
'Stop',
|
|
10
|
-
'StopFailure',
|
|
11
|
-
'UserPromptSubmit',
|
|
12
|
-
];
|
|
2
|
+
import { SETTINGS_ENGINE_OWNED_HOOK_EVENTS } from './generated/settingsSchemaTables.js';
|
|
3
|
+
export const ENGINE_FIRED_HOOK_EVENTS = SETTINGS_ENGINE_OWNED_HOOK_EVENTS;
|
|
13
4
|
export const PLUGIN_HOOK_DISPOSITIONS = ['engine', 'shell', 'not_run'];
|
|
14
5
|
export const PLUGIN_HOOK_REASONS = [
|
|
15
6
|
'projected',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TaskRequest } from '@sema-agent/sdk';
|
|
1
2
|
import { type EnvLike } from './hostEnv.js';
|
|
2
|
-
export type PromptProfile = '
|
|
3
|
+
export type PromptProfile = NonNullable<TaskRequest['promptProfile']>;
|
|
3
4
|
export declare function promptProfileFromEnv(env?: EnvLike): PromptProfile | undefined;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { hasCoreValuePort, mintNamespacePrefix, protocolOf } from './coreValuePorts.js';
|
|
2
|
+
export function protocolSegmentOf(name) {
|
|
3
|
+
const ns = protocolOf(name);
|
|
4
|
+
if (ns === undefined)
|
|
5
|
+
return hasCoreValuePort('protocolOf') ? { kind: 'ok' } : { kind: 'unknown' };
|
|
6
|
+
let parsed;
|
|
7
|
+
try {
|
|
8
|
+
parsed = ns.parse(name);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return { kind: 'unknown' };
|
|
12
|
+
}
|
|
13
|
+
const peer = parsed?.peer;
|
|
14
|
+
if (typeof peer !== 'string')
|
|
15
|
+
return { kind: 'ok' };
|
|
16
|
+
if (peer.includes('*'))
|
|
17
|
+
return { kind: 'unminted' };
|
|
18
|
+
let minted;
|
|
19
|
+
try {
|
|
20
|
+
minted = mintNamespacePrefix(ns, peer);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return { kind: 'unknown' };
|
|
24
|
+
}
|
|
25
|
+
if (typeof minted !== 'string')
|
|
26
|
+
return { kind: 'unknown' };
|
|
27
|
+
return minted === `${ns.prefix}${peer}__` ? { kind: 'ok' } : { kind: 'unminted', minted };
|
|
28
|
+
}
|
|
@@ -44,7 +44,7 @@ export const REQUEST_FIELD_MATRIX = [
|
|
|
44
44
|
{ field: 'systemPrompt', lanes: ['interactive', 'print', 'utility'], live: false, why: '整段替换系统提示(sdk `TaskRequest.systemPrompt`;上游字符数超限 400 响亮拒,本层原样透传)。三条车道都有来源:交互面 = CC QueryParams.systemPrompt,无人值守面 = `--system-prompt[-file]` 一类旗,side-channel 面 = 壳整段给出的那一份。与追加位 `appendSystemPrompt` 不是一个位(那一位归 live 兜底层,见 `LIVE_DEFAULT_FIELDS`)', whyUtilityLane: '有座:side-channel 提交的系统提示由壳整段给出 —— 它不是用户会话的续谈,不该继承用户那一份' },
|
|
45
45
|
{ field: 'reasoningEffort', lanes: ['interactive', 'print', 'utility'], live: false, why: '思考档位(sdk `TaskRequest.reasoningEffort` 七词闭集;上游对表外词 400 响亮拒 ⇒ 本层不预铸第二判官)。档位是请求级的位、与车道无关:交互面 = `/effort` 拨盘,无人值守面 = 档位旗。🔴 端交的必须是**档位词**:「思考 token 数」今天没有上游对位(见 `UPSTREAM_ABSENT_REQUEST_INTENTS` 的 `maxThinkingTokens`),别把一个数字折成档位词发出去', whyUtilityLane: '有座:side-channel 该用显式低档(省钱省时);与 model 同一条理由 —— 本车道上这两位都由壳显式给,不跟用户会话的拨盘走' },
|
|
46
46
|
{ field: 'model', lanes: ['interactive', 'print', 'utility'], live: false, why: '模型选择(sdk `TaskRequest.model`;交互面 = `/model` 中途换模型的拨盘,无人值守面 = 模型旗 / 部署缺省那一路,side-channel 面 = 壳显式挑的那一只)。三条车道都有来源、都是提交面。🔴 0.79.0 改口:修前「print 的模型走另一条路」这句理由被用户面实测证伪 —— 无人值守车道传了模型名却整键不上请求体,于是同一个坏名字在交互态被引擎 400 点名、在无人值守态却安静换成部署缺省并在首帧回显一个没生效的名字。一个**选择**类声明被静默丢掉,后果与收紧类声明被静默丢掉同形(端不读回执就以为生效)—— 与 `excludeTools` 补 print 座同律。本层原样透传、不预判模型名(名字的合法性归引擎,本层不铸第二判官)', whyUtilityLane: '有座:side-channel 显式挑便宜的那只模型(不跟用户会话的 `/model` 拨盘走)' },
|
|
47
|
-
{ field: 'images', lanes: ['interactive'], live: false, why: '
|
|
47
|
+
{ field: 'images', lanes: ['interactive', 'print'], live: false, why: '图片输入(sdk `TaskRequest.images`;base64 / url 两形,原样透传)。两条用户车道都是提交面、都有来源:交互面 = 粘贴图与 `@` 图片像素,一次性车道 = 结构化输入里的图片块。张数、单张与合计的座位判定归人类提交装配口 `encodeHumanTurn`(两条车道同一份判定,本表不另判);请求体与图片张数的上限归上游判', whyUtilityLane: '无座:贴图是交互动作,side-channel 的提交体里没有图片块' },
|
|
48
48
|
{ field: 'resumeAt/resumeAtMode/restoreFiles/rewindFilesTo', lanes: ['interactive'], live: false, why: 'E18 `/rewind` 是交互命令;四键同生同灭(CC-145:core 6.0.0 起 both 臂发 restoreFiles;CC-223 起退役键 rewindFiles 不再有座 —— 交它按表外子键响亮拒;resumeAtMode 是 both/conversation 两臂恒带的排他截语义位)', whyUtilityLane: '无座:回退是交互命令,而 side-channel 是一次性的独立会话,没有可回退的历史' },
|
|
49
49
|
{ field: 'clientContext', lanes: ['interactive'], live: false, why: 'IANA 时区 + 可选邮箱 → core 本地化 `# Environment` 的 today;print 同样跑在用户机器上,缺席让引擎误标 (UTC)', gap: true, whyUtilityLane: '无座:本地化 today 的用途在用户会话的环境段,而 side-channel 的系统提示由壳整段给出 —— 这一列我判不准要不要(与本行 `gap` 同一条待办:要补先单独立项)' },
|
|
50
50
|
{ field: 'scratchpadDir', lanes: ['interactive'], live: true, why: '[816]③ per-session 暂存目录;print 也有 session,缺席让 `-p` 的工具写不进 exemptDir', gap: true, whyUtilityLane: '无座:per-session 暂存目录是给**工具**写的,零工具面上没人写' },
|
|
@@ -483,13 +483,6 @@ const refuseBadExcludeAllTools = (v) => {
|
|
|
483
483
|
`收到 ${coarseShape(v)}。这一位是**整只工具面卸载**的收紧声明:本层若把坏值静默删键,这一次运行会挂上声明人以为已经卸掉的全部工具。` +
|
|
484
484
|
'错误文本只报形状,不回显值。');
|
|
485
485
|
};
|
|
486
|
-
const RETIRED_APPROVER_POSTURE_KEY = 'approverPosture';
|
|
487
|
-
const refuseRetiredApproverPosture = () => {
|
|
488
|
-
throw new TypeError('buildTaskRequest: "approverPosture" 是退役键(引擎 core 7.34.0 起在任务规格入口按名拒收;服务端 7.106.0 起提交体带它整条 400 ' +
|
|
489
|
-
'request.body_shape,unknownKeys 点名它)。它只是一句渲给模型看的审批姿态声明,从不授权任何东西 —— 删掉它不改变这一次运行被允许做什么。' +
|
|
490
|
-
'本包在装配前拒:在场即拒,任何值同判(undefined / null = 缺席)。处置:删掉这个键,不要改发别的键来顶替它;' +
|
|
491
|
-
'若确实要引擎侧放行审批,那是另一件事:显式给权限模式 permissionMode(那是一项授权,受部署策略管)。错误文本只报键名,不回显值。');
|
|
492
|
-
};
|
|
493
486
|
const refuseBadFileHistory = (v) => {
|
|
494
487
|
if (v === undefined || v === null)
|
|
495
488
|
return;
|
|
@@ -715,17 +708,12 @@ export function assembleTaskRequest(input, lane) {
|
|
|
715
708
|
};
|
|
716
709
|
const unknownKeys = [];
|
|
717
710
|
const lateOmitted = [];
|
|
718
|
-
let retiredApproverPosture = false;
|
|
719
711
|
for (const key of Object.keys(src)) {
|
|
720
712
|
if (hasOwn(INPUT_KEY_ROUTES, key))
|
|
721
713
|
continue;
|
|
722
714
|
const stray = Reflect.get(src, key);
|
|
723
715
|
if (!present(stray))
|
|
724
716
|
continue;
|
|
725
|
-
if (key === RETIRED_APPROVER_POSTURE_KEY) {
|
|
726
|
-
retiredApproverPosture = true;
|
|
727
|
-
continue;
|
|
728
|
-
}
|
|
729
717
|
const route = routeOfTopLevelKey(key);
|
|
730
718
|
if (route === undefined) {
|
|
731
719
|
unknownKeys.push(key);
|
|
@@ -756,8 +744,6 @@ export function assembleTaskRequest(input, lane) {
|
|
|
756
744
|
retiredRewindFiles = true;
|
|
757
745
|
unknownKeys.push(`rewind.${sub}`);
|
|
758
746
|
}
|
|
759
|
-
if (retiredApproverPosture)
|
|
760
|
-
refuseRetiredApproverPosture();
|
|
761
747
|
if (retiredRewindFiles) {
|
|
762
748
|
throw new TypeError('buildTaskRequest: "rewind.rewindFiles" 是退役键(引擎 core 6.0.0 起退役:「逐轮捕获」那一义被引擎忽略 —— 文件首触追踪恒开,' +
|
|
763
749
|
'无需请求;「回退时一并还原文件」那一义被引擎拒收、改名为 restoreFiles)。本包在装配前拒:在场即拒,true / false 同判。' +
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { validatePermissionRules } from './coreValuePorts.js';
|
|
2
|
+
const RULE_COMPILE_ROOT = '/';
|
|
3
|
+
export function ruleCompileVerdict(rule, behavior) {
|
|
4
|
+
try {
|
|
5
|
+
const issues = validatePermissionRules([{ rule, behavior }], { pathBases: { root: RULE_COMPILE_ROOT } });
|
|
6
|
+
if (!Array.isArray(issues))
|
|
7
|
+
return 'unknown';
|
|
8
|
+
return issues.length === 0 ? 'compiles' : 'refused';
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return 'unknown';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RuleBehavior } from '@sema-agent/sdk';
|
|
2
|
+
export type RuleRemovalBehavior = RuleBehavior | undefined;
|
|
2
3
|
export declare function removalConsequenceLineForBehavior(behavior: RuleRemovalBehavior): string;
|
|
3
4
|
export declare function ruleRemovalBehaviorOf(raw: unknown): RuleRemovalBehavior;
|
|
@@ -15,6 +15,7 @@ import { type RunTerminalRead } from './runTerminal.js';
|
|
|
15
15
|
export type RunAbortCause = {
|
|
16
16
|
kind: 'cancelled';
|
|
17
17
|
context?: RunCancelContextView;
|
|
18
|
+
cause?: AbortCauseReading;
|
|
18
19
|
} | {
|
|
19
20
|
kind: 'engine_error';
|
|
20
21
|
code?: string;
|
|
@@ -28,3 +29,14 @@ export type RunAbortCause = {
|
|
|
28
29
|
};
|
|
29
30
|
export declare const RUN_CANCELLED_CODE: "cancelled";
|
|
30
31
|
export declare function classifyRunAbortCause(record: unknown): RunAbortCause;
|
|
32
|
+
export declare const ABORT_CAUSES: readonly ["client_disconnected", "ask_park_grace_exhausted", "cancel_verb"];
|
|
33
|
+
export type AbortCause = (typeof ABORT_CAUSES)[number];
|
|
34
|
+
export type AbortCauseReading = {
|
|
35
|
+
readonly kind: 'known';
|
|
36
|
+
readonly cause: AbortCause;
|
|
37
|
+
} | {
|
|
38
|
+
readonly kind: 'unrecognized';
|
|
39
|
+
readonly word: string;
|
|
40
|
+
};
|
|
41
|
+
export declare function readAbortCause(frame: unknown): AbortCauseReading | undefined;
|
|
42
|
+
export declare function abortCauseNoteOf(frame: unknown): string | undefined;
|
package/dist/runCancelContext.js
CHANGED
|
@@ -45,7 +45,8 @@ export function classifyRunAbortCause(record) {
|
|
|
45
45
|
if (read !== null && read.kind === 'failed') {
|
|
46
46
|
if (read.code === RUN_CANCELLED_CODE) {
|
|
47
47
|
const cc = readRunCancelContext(record);
|
|
48
|
-
|
|
48
|
+
const cause = readAbortCause(record);
|
|
49
|
+
return { kind: 'cancelled', ...(cc?.kind === 'present' ? { context: cc.context } : {}), ...(cause !== undefined ? { cause } : {}) };
|
|
49
50
|
}
|
|
50
51
|
return { kind: 'engine_error', ...(read.code !== undefined ? { code: read.code } : {}), ...(read.message !== undefined ? { message: read.message } : {}) };
|
|
51
52
|
}
|
|
@@ -55,3 +56,84 @@ export function classifyRunAbortCause(record) {
|
|
|
55
56
|
return { kind: 'run_still_live', status };
|
|
56
57
|
return { kind: 'unknown', ...(read !== null ? { terminal: read.kind } : {}) };
|
|
57
58
|
}
|
|
59
|
+
export const ABORT_CAUSES = Object.freeze(['client_disconnected', 'ask_park_grace_exhausted', 'cancel_verb']);
|
|
60
|
+
function ownDataOf(o, key) {
|
|
61
|
+
const d = Object.getOwnPropertyDescriptor(o, key);
|
|
62
|
+
return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
|
|
63
|
+
}
|
|
64
|
+
function plainRecordOf(v) {
|
|
65
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v) ? v : undefined;
|
|
66
|
+
}
|
|
67
|
+
function cancelledHolderOf(frame) {
|
|
68
|
+
const f = plainRecordOf(frame);
|
|
69
|
+
if (f === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
const type = ownDataOf(f, 'type');
|
|
72
|
+
if (type === 'failed')
|
|
73
|
+
return ownDataOf(f, 'errorCode') === RUN_CANCELLED_CODE ? f : undefined;
|
|
74
|
+
const base = plainRecordOf(type === 'done' ? ownDataOf(f, 'result') : f);
|
|
75
|
+
if (base === undefined)
|
|
76
|
+
return undefined;
|
|
77
|
+
const holder = runResultHolder(base);
|
|
78
|
+
const t = readRunTerminal(holder);
|
|
79
|
+
return t !== null && t.kind === 'failed' && t.code === RUN_CANCELLED_CODE ? holder : undefined;
|
|
80
|
+
}
|
|
81
|
+
function abortCauseIn(holder) {
|
|
82
|
+
const raw = ownDataOf(holder, 'abortCause');
|
|
83
|
+
if (typeof raw !== 'string' || raw.length === 0)
|
|
84
|
+
return undefined;
|
|
85
|
+
return ABORT_CAUSES.includes(raw) ? { kind: 'known', cause: raw } : { kind: 'unrecognized', word: raw };
|
|
86
|
+
}
|
|
87
|
+
export function readAbortCause(frame) {
|
|
88
|
+
try {
|
|
89
|
+
const holder = cancelledHolderOf(frame);
|
|
90
|
+
return holder === undefined ? undefined : abortCauseIn(holder);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const ABORT_CAUSE_SENTENCES = Object.freeze({
|
|
97
|
+
client_disconnected: 'Aborted: the stream connection to the engine dropped, and the engine stopped the run (cause client_disconnected) — not an engine error.',
|
|
98
|
+
ask_park_grace_exhausted: 'Aborted: the connection dropped while a question or approval was pending, and the run could not be parked for later resumption in time ' +
|
|
99
|
+
'(cause ask_park_grace_exhausted) — not an engine error.',
|
|
100
|
+
cancel_verb: 'Cancelled: a cancel request to the engine stopped this run (cause cancel_verb) — not an engine error.',
|
|
101
|
+
});
|
|
102
|
+
const ABORT_CAUSE_UNRECOGNIZED_SENTENCE = 'Aborted by the engine for a reason this client does not recognize — not an engine error.';
|
|
103
|
+
function secondsText(ms) {
|
|
104
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
105
|
+
}
|
|
106
|
+
function cancelContextOf(holder) {
|
|
107
|
+
try {
|
|
108
|
+
const r = readRunCancelContext(holder);
|
|
109
|
+
return r?.kind === 'present' ? r.context : undefined;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function cancelContextTail(ctx) {
|
|
116
|
+
if (ctx === undefined)
|
|
117
|
+
return '';
|
|
118
|
+
const parts = [];
|
|
119
|
+
if (ctx.elapsedMs !== undefined)
|
|
120
|
+
parts.push(`ran ${secondsText(ctx.elapsedMs)}`);
|
|
121
|
+
if (ctx.lastEventAgeMs !== undefined)
|
|
122
|
+
parts.push(`last engine activity ${secondsText(ctx.lastEventAgeMs)} before the stop`);
|
|
123
|
+
return parts.length > 0 ? ` (${parts.join('; ')})` : '';
|
|
124
|
+
}
|
|
125
|
+
export function abortCauseNoteOf(frame) {
|
|
126
|
+
try {
|
|
127
|
+
const holder = cancelledHolderOf(frame);
|
|
128
|
+
if (holder === undefined)
|
|
129
|
+
return undefined;
|
|
130
|
+
const cause = abortCauseIn(holder);
|
|
131
|
+
if (cause === undefined)
|
|
132
|
+
return undefined;
|
|
133
|
+
const sentence = cause.kind === 'known' ? ABORT_CAUSE_SENTENCES[cause.cause] : ABORT_CAUSE_UNRECOGNIZED_SENTENCE;
|
|
134
|
+
return `${sentence}${cancelContextTail(cancelContextOf(holder))}`;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
}
|
package/dist/seam.js
CHANGED
|
@@ -94,7 +94,7 @@ const CHROME_ARM_TABLE = {
|
|
|
94
94
|
},
|
|
95
95
|
tool_progress: {
|
|
96
96
|
required: false,
|
|
97
|
-
duty: 'CC-08(0.71.0
|
|
97
|
+
duty: 'CC-08(0.71.0,一帧两拍):按 `toolCallId` 挂到那张工具卡上;`elapsedSeconds` 缺席不是 0、不等于 tool_end 的 duration;' +
|
|
98
98
|
'`output` 在场 = 命令尾巴窗口(活面板,不是日志;`totalLines`/`totalBytes` 与它同进同退),🔴 它是 UNTRUSTED RAW,可再封顶展示、**绝不回喂**模型;' +
|
|
99
99
|
'子代工具的进度不在这条臂上(三键断闸),fleet 面板另有口。不接 = 看不见进度,不属行为丢失。',
|
|
100
100
|
},
|
package/dist/seatContract.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { LaneProof } from "./seam.js";
|
|
|
4
4
|
import type { QuestionAnswer } from "./liveQuestionStore.js";
|
|
5
5
|
import type { ToolApprovalDelegation } from "./hitl/toolApprovalWire.js";
|
|
6
6
|
import type { ApprovalMandateWord } from "./gateVocabulary.js";
|
|
7
|
+
import type { ModelApiWord } from "./model/providerPresets.js";
|
|
7
8
|
export interface SeatValidationFailure {
|
|
8
9
|
reason: string;
|
|
9
10
|
field?: string;
|
|
@@ -240,7 +241,7 @@ export interface SeatCatalogEntry {
|
|
|
240
241
|
providerId: string;
|
|
241
242
|
providerName: string;
|
|
242
243
|
baseUrl: string;
|
|
243
|
-
api:
|
|
244
|
+
api: ModelApiWord;
|
|
244
245
|
apiKey?: string;
|
|
245
246
|
modelId: string;
|
|
246
247
|
contextWindow: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionMemoryStatus } from '@sema-agent/sdk';
|
|
1
|
+
import type { SessionMemoryStatus, SessionMemoryStatusResponse } from '@sema-agent/sdk';
|
|
2
2
|
export interface MemoryStatusClientLike {
|
|
3
3
|
sessions: {
|
|
4
4
|
memoryStatus(sessionId: string, opts?: {
|
|
@@ -8,9 +8,7 @@ export interface MemoryStatusClientLike {
|
|
|
8
8
|
} & SessionMemoryStatus>;
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
export type MemoryStatusFacts =
|
|
12
|
-
readonly autoConsolidationArmed?: boolean;
|
|
13
|
-
};
|
|
11
|
+
export type MemoryStatusFacts = Omit<SessionMemoryStatusResponse, 'sessionId'>;
|
|
14
12
|
export type MemoryStatusVerdict = {
|
|
15
13
|
readonly kind: 'ok';
|
|
16
14
|
readonly sessionId: string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type SessionSyncFileHistoryReading = {
|
|
2
|
+
kind: 'unobserved';
|
|
3
|
+
} | {
|
|
4
|
+
kind: 'not_reported';
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'absent';
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'present';
|
|
9
|
+
};
|
|
10
|
+
export declare function projectSessionSyncFileHistoryCapability(caps: unknown): SessionSyncFileHistoryReading | undefined;
|
|
11
|
+
export declare function noteEngineCapsForSessionSyncFileHistory(baseUrl: string, caps: unknown, opts?: {
|
|
12
|
+
generation?: number;
|
|
13
|
+
}): void;
|
|
14
|
+
export declare function observedSessionSyncFileHistory(baseUrl?: string | undefined): SessionSyncFileHistoryReading;
|
|
15
|
+
export declare function sessionSyncFileHistoryAvailable(reading: SessionSyncFileHistoryReading): 'yes' | 'no' | 'unknown';
|
|
16
|
+
export declare function sessionSyncFileHistoryDoctorDetail(reading: SessionSyncFileHistoryReading): string;
|
|
17
|
+
export declare function forgetSessionSyncFileHistoryReading(baseUrl: string | undefined): void;
|
|
18
|
+
export declare function __resetSessionSyncFileHistoryReadingsForTests(): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { engineWireTarget } from './engineWireTarget.js';
|
|
2
|
+
import { createEngineCapReader } from './engineCapReader.js';
|
|
3
|
+
export function projectSessionSyncFileHistoryCapability(caps) {
|
|
4
|
+
if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
|
|
5
|
+
return undefined;
|
|
6
|
+
if (!Object.hasOwn(caps, 'sessionSyncFileHistory'))
|
|
7
|
+
return { kind: 'not_reported' };
|
|
8
|
+
const v = caps.sessionSyncFileHistory;
|
|
9
|
+
if (v === undefined)
|
|
10
|
+
return { kind: 'not_reported' };
|
|
11
|
+
if (typeof v !== 'boolean')
|
|
12
|
+
return undefined;
|
|
13
|
+
return v ? { kind: 'present' } : { kind: 'absent' };
|
|
14
|
+
}
|
|
15
|
+
const reader = createEngineCapReader({
|
|
16
|
+
name: 'sessionSyncFileHistory',
|
|
17
|
+
project: projectSessionSyncFileHistoryCapability,
|
|
18
|
+
makeUnobserved: () => ({ kind: 'unobserved' }),
|
|
19
|
+
});
|
|
20
|
+
export function noteEngineCapsForSessionSyncFileHistory(baseUrl, caps, opts) {
|
|
21
|
+
reader.note(baseUrl, caps, opts);
|
|
22
|
+
}
|
|
23
|
+
export function observedSessionSyncFileHistory(baseUrl = engineWireTarget()?.baseUrl) {
|
|
24
|
+
return reader.observed(baseUrl);
|
|
25
|
+
}
|
|
26
|
+
export function sessionSyncFileHistoryAvailable(reading) {
|
|
27
|
+
if (reading.kind === 'present')
|
|
28
|
+
return 'yes';
|
|
29
|
+
if (reading.kind === 'absent')
|
|
30
|
+
return 'no';
|
|
31
|
+
return 'unknown';
|
|
32
|
+
}
|
|
33
|
+
export function sessionSyncFileHistoryDoctorDetail(reading) {
|
|
34
|
+
switch (reading.kind) {
|
|
35
|
+
case 'unobserved':
|
|
36
|
+
return 'session-sync file history not observed — the engine reports it on /v1/capabilities (sessionSyncFileHistory); this process has no usable capabilities reading cached for it (none received, or the last one was unreadable)';
|
|
37
|
+
case 'not_reported':
|
|
38
|
+
return 'session-sync file history not reported by this engine — only newer engines advertise it separately; this does not say whether file history can be synced';
|
|
39
|
+
case 'absent':
|
|
40
|
+
return 'no session-sync file history on this deployment — syncing a session moves the conversation only; edited-file history stays behind';
|
|
41
|
+
case 'present':
|
|
42
|
+
return 'session-sync file history on — syncing a session can also move its edited-file history';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function forgetSessionSyncFileHistoryReading(baseUrl) {
|
|
46
|
+
reader.forget(baseUrl);
|
|
47
|
+
}
|
|
48
|
+
export function __resetSessionSyncFileHistoryReadingsForTests() {
|
|
49
|
+
reader.__resetForTests();
|
|
50
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type SkillToolListsReading = {
|
|
2
|
+
kind: 'unobserved';
|
|
3
|
+
} | {
|
|
4
|
+
kind: 'not_reported';
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'absent';
|
|
7
|
+
} | {
|
|
8
|
+
kind: 'present';
|
|
9
|
+
};
|
|
10
|
+
export declare function projectSkillToolListsCapability(caps: unknown): SkillToolListsReading | undefined;
|
|
11
|
+
export declare function noteEngineCapsForSkillToolLists(baseUrl: string, caps: unknown, opts?: {
|
|
12
|
+
generation?: number;
|
|
13
|
+
}): void;
|
|
14
|
+
export declare function observedSkillToolLists(baseUrl?: string | undefined): SkillToolListsReading;
|
|
15
|
+
export declare function skillToolListsAvailable(reading: SkillToolListsReading): 'yes' | 'no' | 'unknown';
|
|
16
|
+
export declare function skillToolListsDoctorDetail(reading: SkillToolListsReading): string;
|
|
17
|
+
export declare function forgetSkillToolListsReading(baseUrl: string | undefined): void;
|
|
18
|
+
export declare function __resetSkillToolListsReadingsForTests(): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { engineWireTarget } from './engineWireTarget.js';
|
|
2
|
+
import { createEngineCapReader } from './engineCapReader.js';
|
|
3
|
+
export function projectSkillToolListsCapability(caps) {
|
|
4
|
+
if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
|
|
5
|
+
return undefined;
|
|
6
|
+
if (!Object.hasOwn(caps, 'skillToolLists'))
|
|
7
|
+
return { kind: 'not_reported' };
|
|
8
|
+
const v = caps.skillToolLists;
|
|
9
|
+
if (v === undefined)
|
|
10
|
+
return { kind: 'not_reported' };
|
|
11
|
+
if (typeof v !== 'boolean')
|
|
12
|
+
return undefined;
|
|
13
|
+
return v ? { kind: 'present' } : { kind: 'absent' };
|
|
14
|
+
}
|
|
15
|
+
const reader = createEngineCapReader({
|
|
16
|
+
name: 'skillToolLists',
|
|
17
|
+
project: projectSkillToolListsCapability,
|
|
18
|
+
makeUnobserved: () => ({ kind: 'unobserved' }),
|
|
19
|
+
});
|
|
20
|
+
export function noteEngineCapsForSkillToolLists(baseUrl, caps, opts) {
|
|
21
|
+
reader.note(baseUrl, caps, opts);
|
|
22
|
+
}
|
|
23
|
+
export function observedSkillToolLists(baseUrl = engineWireTarget()?.baseUrl) {
|
|
24
|
+
return reader.observed(baseUrl);
|
|
25
|
+
}
|
|
26
|
+
export function skillToolListsAvailable(reading) {
|
|
27
|
+
if (reading.kind === 'present')
|
|
28
|
+
return 'yes';
|
|
29
|
+
if (reading.kind === 'absent' || reading.kind === 'not_reported')
|
|
30
|
+
return 'no';
|
|
31
|
+
return 'unknown';
|
|
32
|
+
}
|
|
33
|
+
export function skillToolListsDoctorDetail(reading) {
|
|
34
|
+
switch (reading.kind) {
|
|
35
|
+
case 'unobserved':
|
|
36
|
+
return 'skill tool lists not observed — the engine reports it on /v1/capabilities (skillToolLists); this process has no usable capabilities reading cached for it (none received, or the last one was unreadable)';
|
|
37
|
+
case 'not_reported':
|
|
38
|
+
return 'skill tool lists not reported by this engine — the engine predates them: tool lists on request skills are not read, so they do not limit any tool';
|
|
39
|
+
case 'absent':
|
|
40
|
+
return 'skill tool lists off on this deployment — tool lists on request skills are not read';
|
|
41
|
+
case 'present':
|
|
42
|
+
return 'skill tool lists on — a request skill’s allowed and disallowed tool lists are read as this run’s rules';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function forgetSkillToolListsReading(baseUrl) {
|
|
46
|
+
reader.forget(baseUrl);
|
|
47
|
+
}
|
|
48
|
+
export function __resetSkillToolListsReadingsForTests() {
|
|
49
|
+
reader.__resetForTests();
|
|
50
|
+
}
|
|
@@ -16,14 +16,7 @@ export function projectSqlEngineCapability(caps) {
|
|
|
16
16
|
return { kind: 'none' };
|
|
17
17
|
return projectSqlEngineView(nested);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
return { kind: 'not_reported' };
|
|
21
|
-
const sql = caps.sql;
|
|
22
|
-
if (sql === null)
|
|
23
|
-
return { kind: 'none' };
|
|
24
|
-
if (sql === undefined)
|
|
25
|
-
return { kind: 'not_reported' };
|
|
26
|
-
return projectSqlEngineView(sql);
|
|
19
|
+
return { kind: 'not_reported' };
|
|
27
20
|
}
|
|
28
21
|
function projectSqlEngineView(sql) {
|
|
29
22
|
if (sql === null || typeof sql !== 'object')
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type SteerPriorityReading = {
|
|
2
|
+
kind: 'unobserved';
|
|
3
|
+
} | {
|
|
4
|
+
kind: 'not_reported';
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'present';
|
|
7
|
+
word: string;
|
|
8
|
+
};
|
|
9
|
+
export type SteerPriorityMode = 'engine' | 'advisory' | 'unknown';
|
|
10
|
+
export declare function projectSteerPriorityCapability(caps: unknown): SteerPriorityReading | undefined;
|
|
11
|
+
export declare function noteEngineCapsForSteerPriority(baseUrl: string, caps: unknown, opts?: {
|
|
12
|
+
generation?: number;
|
|
13
|
+
}): void;
|
|
14
|
+
export declare function observedSteerPriority(baseUrl?: string | undefined): SteerPriorityReading;
|
|
15
|
+
export declare function steerPriorityMode(reading: SteerPriorityReading): SteerPriorityMode;
|
|
16
|
+
export declare function steerPriorityDoctorDetail(reading: SteerPriorityReading): string;
|
|
17
|
+
export declare function forgetSteerPriorityReading(baseUrl: string | undefined): void;
|
|
18
|
+
export declare function __resetSteerPriorityReadingsForTests(): void;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { capForDisplay } from './fleetTaskDesc.js';
|
|
2
|
+
import { engineWireTarget } from './engineWireTarget.js';
|
|
3
|
+
import { createEngineCapReader } from './engineCapReader.js';
|
|
4
|
+
export function projectSteerPriorityCapability(caps) {
|
|
5
|
+
if (caps === null || typeof caps !== 'object' || Array.isArray(caps))
|
|
6
|
+
return undefined;
|
|
7
|
+
if (!Object.hasOwn(caps, 'fleet'))
|
|
8
|
+
return { kind: 'not_reported' };
|
|
9
|
+
const fleet = caps.fleet;
|
|
10
|
+
if (fleet === undefined || fleet === false)
|
|
11
|
+
return { kind: 'not_reported' };
|
|
12
|
+
if (fleet === null || typeof fleet !== 'object' || Array.isArray(fleet))
|
|
13
|
+
return undefined;
|
|
14
|
+
if (!Object.hasOwn(fleet, 'steerPriority'))
|
|
15
|
+
return { kind: 'not_reported' };
|
|
16
|
+
const v = fleet.steerPriority;
|
|
17
|
+
if (v === undefined)
|
|
18
|
+
return { kind: 'not_reported' };
|
|
19
|
+
if (typeof v !== 'string' || v.length === 0)
|
|
20
|
+
return undefined;
|
|
21
|
+
return { kind: 'present', word: v };
|
|
22
|
+
}
|
|
23
|
+
const reader = createEngineCapReader({
|
|
24
|
+
name: 'fleet.steerPriority',
|
|
25
|
+
project: projectSteerPriorityCapability,
|
|
26
|
+
makeUnobserved: () => ({ kind: 'unobserved' }),
|
|
27
|
+
});
|
|
28
|
+
export function noteEngineCapsForSteerPriority(baseUrl, caps, opts) {
|
|
29
|
+
reader.note(baseUrl, caps, opts);
|
|
30
|
+
}
|
|
31
|
+
export function observedSteerPriority(baseUrl = engineWireTarget()?.baseUrl) {
|
|
32
|
+
return reader.observed(baseUrl);
|
|
33
|
+
}
|
|
34
|
+
export function steerPriorityMode(reading) {
|
|
35
|
+
try {
|
|
36
|
+
if (reading === null || typeof reading !== 'object' || Array.isArray(reading))
|
|
37
|
+
return 'unknown';
|
|
38
|
+
if (!Object.hasOwn(reading, 'kind') || reading.kind !== 'present')
|
|
39
|
+
return 'unknown';
|
|
40
|
+
if (!Object.hasOwn(reading, 'word'))
|
|
41
|
+
return 'unknown';
|
|
42
|
+
const word = reading.word;
|
|
43
|
+
return word === 'engine' ? 'engine' : word === 'advisory' ? 'advisory' : 'unknown';
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return 'unknown';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const WORD_DETAIL_MAX = 40;
|
|
50
|
+
export function steerPriorityDoctorDetail(reading) {
|
|
51
|
+
const unobserved = 'steer priority not observed — the engine reports it on /v1/capabilities (fleet.steerPriority); this process has no usable capabilities reading cached for it, so a "now" or "later" steer is not sent';
|
|
52
|
+
let kind;
|
|
53
|
+
let word;
|
|
54
|
+
try {
|
|
55
|
+
if (reading === null || typeof reading !== 'object')
|
|
56
|
+
return unobserved;
|
|
57
|
+
kind = Object.hasOwn(reading, 'kind') ? reading.kind : undefined;
|
|
58
|
+
word = kind === 'present' && Object.hasOwn(reading, 'word') ? reading.word : undefined;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return unobserved;
|
|
62
|
+
}
|
|
63
|
+
if (kind === 'not_reported') {
|
|
64
|
+
return 'steer priority not reported by this engine — it predates the field or has no fleet face, so a "now" or "later" steer is not sent (steers without a priority work as before)';
|
|
65
|
+
}
|
|
66
|
+
if (kind !== 'present' || typeof word !== 'string' || word.length === 0)
|
|
67
|
+
return unobserved;
|
|
68
|
+
if (word === 'engine')
|
|
69
|
+
return 'steer priority applied by the engine — "now" interrupts the running turn, "later" waits until the run would have stopped';
|
|
70
|
+
if (word === 'advisory') {
|
|
71
|
+
return 'steer priority accepted but not applied on this deployment — a "now" or "later" steer is not sent (steers without a priority work as before)';
|
|
72
|
+
}
|
|
73
|
+
return `steer priority reported as "${capForDisplay(word, WORD_DETAIL_MAX)}" — a value this client does not know yet, so whether it is applied is unknown and a "now" or "later" steer is not sent`;
|
|
74
|
+
}
|
|
75
|
+
export function forgetSteerPriorityReading(baseUrl) {
|
|
76
|
+
reader.forget(baseUrl);
|
|
77
|
+
}
|
|
78
|
+
export function __resetSteerPriorityReadingsForTests() {
|
|
79
|
+
reader.__resetForTests();
|
|
80
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SteerPriority } from '@sema-agent/sdk';
|
|
2
|
+
export interface SteerReceiptReading {
|
|
3
|
+
readonly delivery: string | null;
|
|
4
|
+
readonly status: string | null;
|
|
5
|
+
readonly messageId?: string;
|
|
6
|
+
readonly priority?: SteerPriority;
|
|
7
|
+
}
|
|
8
|
+
export declare function ownNonEmptyStringOf(body: unknown, key: string): string | undefined;
|
|
9
|
+
export declare function readSteerReceipt(receipt: unknown): SteerReceiptReading;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function ownNonEmptyStringOf(body, key) {
|
|
2
|
+
try {
|
|
3
|
+
if (typeof body !== 'object' || body === null || !Object.hasOwn(body, key))
|
|
4
|
+
return undefined;
|
|
5
|
+
const v = body[key];
|
|
6
|
+
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function priorityEchoOf(body) {
|
|
13
|
+
const v = ownNonEmptyStringOf(body, 'priority');
|
|
14
|
+
return v === 'now' || v === 'next' || v === 'later' ? v : undefined;
|
|
15
|
+
}
|
|
16
|
+
export function readSteerReceipt(receipt) {
|
|
17
|
+
const messageId = ownNonEmptyStringOf(receipt, 'messageId');
|
|
18
|
+
const priority = priorityEchoOf(receipt);
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
delivery: ownNonEmptyStringOf(receipt, 'delivery') ?? null,
|
|
21
|
+
status: ownNonEmptyStringOf(receipt, 'status') ?? null,
|
|
22
|
+
...(messageId !== undefined ? { messageId } : {}),
|
|
23
|
+
...(priority !== undefined ? { priority } : {}),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -4,19 +4,12 @@ import { engineSessionParamFor } from '../engineSessionParam.js';
|
|
|
4
4
|
import { resolveOwnerContext, resolveOwnerRunId } from './engineSubagentResume.js';
|
|
5
5
|
import { noteBgOwnerAbsence } from './subagentOwnerAbsence.js';
|
|
6
6
|
import { errCodes, steeringRefusedBeforeEngine } from '../controlRouter.js';
|
|
7
|
+
import { ownNonEmptyStringOf } from '../steerReceipt.js';
|
|
7
8
|
function usableSteerClient(client) {
|
|
8
9
|
return clientHasVerbs(client, [['runs', 'steerSubagent']]);
|
|
9
10
|
}
|
|
10
11
|
function steerReceiptMessageId(body) {
|
|
11
|
-
|
|
12
|
-
if (typeof body !== 'object' || body === null || !Object.hasOwn(body, 'messageId'))
|
|
13
|
-
return undefined;
|
|
14
|
-
const v = body.messageId;
|
|
15
|
-
return typeof v === 'string' && v.length > 0 ? v : undefined;
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return undefined;
|
|
19
|
-
}
|
|
12
|
+
return ownNonEmptyStringOf(body, 'messageId');
|
|
20
13
|
}
|
|
21
14
|
export async function steerEngineSubagent(target, text, childTaskId, opts) {
|
|
22
15
|
const named = typeof childTaskId === 'string' && childTaskId !== '' ? childTaskId : undefined;
|
package/dist/supportFloor.js
CHANGED