@sema-agent/client-core 0.101.0 → 0.102.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +12 -7
  3. package/dist/adapt/toolCards.d.ts +2 -1
  4. package/dist/adapt/toolCards.js +20 -6
  5. package/dist/adapt.d.ts +1 -1
  6. package/dist/adapt.js +1 -1
  7. package/dist/adapter/downstream/eventToSdkMessage.js +6 -68
  8. package/dist/adapter/downstream/wiringManifestView.d.ts +1 -0
  9. package/dist/adapter/downstream/wiringManifestView.js +138 -0
  10. package/dist/compensations.js +1 -1
  11. package/dist/displayUntrusted.d.ts +8 -4
  12. package/dist/displayUntrusted.js +769 -96
  13. package/dist/engineRowRef.js +1 -0
  14. package/dist/fleet/fleetProjection.js +1 -1
  15. package/dist/i18n/messages.en.d.ts +38 -0
  16. package/dist/i18n/messages.en.js +38 -0
  17. package/dist/i18n/messages.zh.js +40 -0
  18. package/dist/index.d.ts +8 -0
  19. package/dist/index.js +5 -0
  20. package/dist/interactiveHalt.d.ts +3 -1
  21. package/dist/interactiveHalt.js +2 -0
  22. package/dist/interactiveInterrupt.d.ts +2 -0
  23. package/dist/interactiveInterrupt.js +15 -0
  24. package/dist/modsFace.d.ts +8 -0
  25. package/dist/modsFace.js +59 -0
  26. package/dist/ownKey.d.ts +1 -0
  27. package/dist/ownKey.js +15 -0
  28. package/dist/printToolResultFrame.js +1 -1
  29. package/dist/request/printNotification.js +1 -1
  30. package/dist/request/taskRequest.d.ts +21 -0
  31. package/dist/request/taskRequest.js +123 -7
  32. package/dist/seam.js +1 -1
  33. package/dist/seatContract.d.ts +22 -6
  34. package/dist/seatContract.js +35 -6
  35. package/dist/sessionBackground.d.ts +165 -0
  36. package/dist/sessionBackground.js +781 -0
  37. package/dist/sessionBackgroundHandoff.d.ts +54 -0
  38. package/dist/sessionBackgroundHandoff.js +321 -0
  39. package/dist/sessionMap.js +4 -1
  40. package/dist/settingsCredentialKeyPaths.js +2 -17
  41. package/dist/thinkingLatch.d.ts +69 -0
  42. package/dist/thinkingLatch.js +255 -0
  43. package/dist/thinkingLatchWords.d.ts +7 -0
  44. package/dist/thinkingLatchWords.js +4 -0
  45. package/dist/toolResult.js +2 -24
  46. package/docs/INTEGRATION-CLIENTS.md +309 -10
  47. package/package.json +1 -1
  48. package/dist/argvFlagValue.d.ts +0 -8
  49. package/dist/argvFlagValue.js +0 -37
@@ -100,6 +100,7 @@ export const TRANSCRIPT_ROW_SIDECAR_KEYS = Object.freeze([
100
100
  '_sema_row_kind',
101
101
  '_sema_coded_detail',
102
102
  '_sema_task_notification',
103
+ '_sema_answered_by',
103
104
  ]);
104
105
  export function parkHeldCallIdOf(carrier) {
105
106
  return readFrameStringKey(carrier, 'toolCallId');
@@ -328,7 +328,7 @@ export const FLEET_TASK_ROW_KEYS_NOT_PROJECTED = {
328
328
  kind: 'by-design',
329
329
  owner: 'client-core 规范重构轮',
330
330
  reason: 'SDK 3.0.0 新键([2070]① 让位半场:前台 delegation 复合 id 行带 "run-leg" 标)。**渲染视图**(FleetTaskView)不投 —— 渲染面没有按车道分支的需求,' +
331
- '#95 纪律:没人读的键不盲投。🆕 0.96.0 CC-643 起它有了消费者,但住在另一张读面:在飞 bg 读面行(EngineActiveBgTask)投了它,' +
331
+ '纪律:没人读的键不盲投。🆕 0.96.0 CC-643 起它有了消费者,但住在另一张读面:在飞 bg 读面行(EngineActiveBgTask)投了它,' +
332
332
  '「这一行是不是后台子代」的单一判定口 isBackgroundSubagentRow 读它(见 fleet/bgSubagentRow.ts);视图不投的理由不变,不是第二份真源。',
333
333
  },
334
334
  agentType: {
@@ -1010,6 +1010,44 @@ declare const EN: {
1010
1010
  'config.hooks.plan.reason.compactionLocalFallback': string;
1011
1011
  'session.hooks.compactTransition.disclosure.engineOutcomeUnknown': string;
1012
1012
  'session.hooks.compactTransition.disclosure.neitherRan': string;
1013
+ 'session.background.handedOff': string;
1014
+ 'session.background.refusal.noRun': string;
1015
+ 'session.background.refusal.streamEnded': string;
1016
+ 'session.background.refusal.notStarted': string;
1017
+ 'session.background.refusal.alreadyHandedOff': string;
1018
+ 'session.background.refusal.finished': string;
1019
+ 'session.background.refusal.stopping': string;
1020
+ 'session.background.refusal.engineReplaced': string;
1021
+ 'session.background.refusal.declined': string;
1022
+ 'session.background.refusal.envOff': string;
1023
+ 'session.background.refusal.notReattachable': string;
1024
+ 'session.background.refusal.unconfirmed': string;
1025
+ 'session.background.refusal.durableOff': string;
1026
+ 'session.background.refusal.awaitingUser': string;
1027
+ 'session.background.unknown': string;
1028
+ 'session.background.hostNotNotified': string;
1029
+ 'session.background.settled.completed': string;
1030
+ 'session.background.settled.failed': string;
1031
+ 'session.background.settled.cancelled': string;
1032
+ 'session.background.settled.parked': string;
1033
+ 'session.background.settled.observationStopped': string;
1034
+ 'session.background.busy': string;
1035
+ 'session.thinking.state.on': string;
1036
+ 'session.thinking.state.off': string;
1037
+ 'session.thinking.state.unset': string;
1038
+ 'session.thinking.offWithUltracodeOnBody': string;
1039
+ 'session.thinking.modelCannotThink': string;
1040
+ 'session.thinking.storeUnreadable': string;
1041
+ 'session.thinking.notSaved': string;
1042
+ 'config.mods.card.mounted': string;
1043
+ 'config.mods.card.refused': string;
1044
+ 'config.mods.card.none': string;
1045
+ 'config.mods.card.counts': string;
1046
+ 'config.mods.card.countsWithRefused': string;
1047
+ 'config.mods.loader.failed': string;
1048
+ 'config.mods.loader.failedNoReason': string;
1049
+ 'config.mods.refusal.by': string;
1050
+ 'config.mods.rewrite.resultInPlace': string;
1013
1051
  };
1014
1052
  export declare const EN_MESSAGES: Readonly<typeof EN>;
1015
1053
  export type MessageKey = keyof typeof EN;
@@ -1010,5 +1010,43 @@ const EN = {
1010
1010
  'config.hooks.plan.reason.compactionLocalFallback': 'this compaction is summarized on this client because the engine session is unavailable, so the engine will not run it and this client runs it itself',
1011
1011
  'session.hooks.compactTransition.disclosure.engineOutcomeUnknown': 'The compaction request had already been sent to the engine when the summary fell back to this client, so whether the engine ran the compaction hooks cannot be told here, and this client did not run them again.',
1012
1012
  'session.hooks.compactTransition.disclosure.neitherRan': 'The compaction hooks did not run this time: the engine did not compact here and this client could not start its own summary. If the engine still compacts later it will run them then.',
1013
+ 'session.background.handedOff': "Moved to the background. You'll be told when it finishes.",
1014
+ 'session.background.refusal.noRun': "There's no answer running from this screen that can be moved to the background.",
1015
+ 'session.background.refusal.streamEnded': "This answer is no longer on its original live connection, so it can't be moved to the background from here.",
1016
+ 'session.background.refusal.notStarted': "The engine hasn't started streaming this answer yet. Try again in a moment.",
1017
+ 'session.background.refusal.alreadyHandedOff': 'This answer is already in the background.',
1018
+ 'session.background.refusal.finished': 'This answer has already finished.',
1019
+ 'session.background.refusal.stopping': "This answer is being stopped, so it can't move to the background.",
1020
+ 'session.background.refusal.engineReplaced': "The engine running this answer has stopped or been replaced; it can't be moved.",
1021
+ 'session.background.refusal.declined': "This answer can't move to the background: this engine doesn't keep answers running after you leave. It will finish here.",
1022
+ 'session.background.refusal.envOff': 'Background hand-off is turned off (SEMA_HEADLESS_DETACH). This answer will finish here.',
1023
+ 'session.background.refusal.notReattachable': "This answer can't move to the background: this window can't reconnect to an answer running elsewhere.",
1024
+ 'session.background.refusal.unconfirmed': "This answer can't move to the background: the engine hasn't confirmed it can keep answers running on its own.",
1025
+ 'session.background.refusal.durableOff': "This answer can't move to the background: the engine said it can't keep this answer running after you leave.",
1026
+ 'session.background.refusal.awaitingUser': "Answer the open question first — an answer that is waiting for you can't move to the background.",
1027
+ 'session.background.unknown': "Couldn't confirm this answer can safely move to the background, so it stays here.",
1028
+ 'session.background.hostNotNotified': "Moved to the background, but this screen didn't update cleanly.",
1029
+ 'session.background.settled.completed': 'The background answer finished.',
1030
+ 'session.background.settled.failed': 'The background answer stopped with an error ({code}).',
1031
+ 'session.background.settled.cancelled': 'The background answer was cancelled.',
1032
+ 'session.background.settled.parked': 'The background answer is waiting for approval; open it to continue.',
1033
+ 'session.background.settled.observationStopped': 'Lost track of the background answer. It may still be running — check the task list.',
1034
+ 'session.background.busy': "This conversation's answer is still running in the background. Wait for it to finish, or start a new conversation.",
1035
+ 'session.thinking.state.on': 'Thinking on',
1036
+ 'session.thinking.state.off': 'Thinking off',
1037
+ 'session.thinking.state.unset': 'Thinking not set: the effort setting decides, or the engine default when there is none',
1038
+ 'session.thinking.offWithUltracodeOnBody': 'This message carries both Ultracode and thinking off; the engine decides which one applies.',
1039
+ 'session.thinking.modelCannotThink': 'Thinking is on, but the model {model} does not use extended thinking, so this setting has no effect on it.',
1040
+ 'session.thinking.storeUnreadable': 'The thinking setting could not be read, so it is treated as not set: no thinking override is applied and the effort setting decides.',
1041
+ 'session.thinking.notSaved': 'The thinking setting was not saved, so it may not have changed.',
1042
+ 'config.mods.card.mounted': '{name} is loaded',
1043
+ 'config.mods.card.refused': '{name} was not loaded: {refusedBy} refused it — {reason}',
1044
+ 'config.mods.card.none': 'No mods registered on this leg',
1045
+ 'config.mods.card.counts': '{n} mounted',
1046
+ 'config.mods.card.countsWithRefused': '{n} mounted, {m} refused',
1047
+ 'config.mods.loader.failed': '{name} could not be loaded: {reason}',
1048
+ 'config.mods.loader.failedNoReason': '{name} could not be loaded',
1049
+ 'config.mods.refusal.by': 'Refused by {by}',
1050
+ 'config.mods.rewrite.resultInPlace': 'Answered by {by} in place of the tool',
1013
1051
  };
1014
1052
  export const EN_MESSAGES = Object.freeze(EN);
@@ -1010,9 +1010,49 @@ const ZH = {
1010
1010
  'config.hooks.plan.reason.compactionLocalFallback': '这一次压缩的摘要因引擎会话不可用而在本客户端本地生成,引擎不会替它运行这只 hook,所以由本客户端自己运行',
1011
1011
  'session.hooks.compactTransition.disclosure.engineOutcomeUnknown': '摘要改走本客户端时,压缩请求已经发给了引擎,所以引擎有没有运行压缩 hook 这里判不了,本客户端也没有再运行一遍。',
1012
1012
  'session.hooks.compactTransition.disclosure.neitherRan': '这一次压缩 hook 没有运行:引擎没有在这里压缩,本客户端的本地摘要也没能启动。引擎之后若仍会压缩,到时会运行它们。',
1013
+ 'session.background.handedOff': '已转到后台,结束时会告诉你。',
1014
+ 'session.background.refusal.noRun': '这块屏上没有可以转后台的、正在跑的回答。',
1015
+ 'session.background.refusal.streamEnded': '这条回答已不在最初的实时连接上,不能从这里转后台。',
1016
+ 'session.background.refusal.notStarted': '引擎还没开始输出这条回答,稍后再试。',
1017
+ 'session.background.refusal.alreadyHandedOff': '这条回答已经在后台了。',
1018
+ 'session.background.refusal.finished': '这条回答已经结束了。',
1019
+ 'session.background.refusal.stopping': '这条回答正在被停止,不能转后台。',
1020
+ 'session.background.refusal.engineReplaced': '跑这条回答的引擎已停止或被替换,无法转后台。',
1021
+ 'session.background.refusal.declined': '无法转后台:这台引擎不会在你离开后继续跑回答。它会在这里跑完。',
1022
+ 'session.background.refusal.envOff': '送后台已被关闭(SEMA_HEADLESS_DETACH)。这条回答会在这里跑完。',
1023
+ 'session.background.refusal.notReattachable': '无法转后台:这个窗口接不回在别处跑的回答。',
1024
+ 'session.background.refusal.unconfirmed': '无法转后台:引擎还没确认它能独立跑完回答。',
1025
+ 'session.background.refusal.durableOff': '无法转后台:引擎表示你离开后它没法继续跑这条回答。',
1026
+ 'session.background.refusal.awaitingUser': '先回答屏上的问题 —— 正在等你回答的回答不能转后台。',
1027
+ 'session.background.unknown': '没法确认这条回答能安全转后台,所以它留在这里。',
1028
+ 'session.background.hostNotNotified': '已转到后台,但这块屏没能正常收尾。',
1029
+ 'session.background.settled.completed': '后台回答已完成。',
1030
+ 'session.background.settled.failed': '后台回答出错停止({code})。',
1031
+ 'session.background.settled.cancelled': '后台回答已取消。',
1032
+ 'session.background.settled.parked': '后台回答停在等批准上,打开它继续。',
1033
+ 'session.background.settled.observationStopped': '看不到后台回答了。它可能还在跑 —— 去任务列表看。',
1034
+ 'session.background.busy': '这个对话的回答还在后台跑。等它结束,或开个新对话。',
1035
+ 'session.thinking.state.on': '思考已开启',
1036
+ 'session.thinking.state.off': '思考已关闭',
1037
+ 'session.thinking.state.unset': '思考未设置:由思考档位决定,没有档位时交给引擎默认',
1038
+ 'session.thinking.offWithUltracodeOnBody': '这条消息同时带了 Ultracode 与关闭思考,以哪个为准由引擎决定。',
1039
+ 'session.thinking.modelCannotThink': '思考已开启,但模型 {model} 不使用扩展思考,这一设置对它不起作用。',
1040
+ 'session.thinking.storeUnreadable': '读不出思考设置,按未设处理:不加开关的限制,由思考档位决定。',
1041
+ 'session.thinking.notSaved': '思考设置没有存上,可能没有改变。',
1042
+ 'config.mods.card.mounted': '{name} 已装载',
1043
+ 'config.mods.card.refused': '{name} 没有装载:{refusedBy} 拒绝了它 —— {reason}',
1044
+ 'config.mods.card.none': '本腿没有注册的 mod',
1045
+ 'config.mods.card.counts': '{n} 已装载',
1046
+ 'config.mods.card.countsWithRefused': '{n} 已装载,{m} 被拒',
1047
+ 'config.mods.loader.failed': '{name} 装载失败:{reason}',
1048
+ 'config.mods.loader.failedNoReason': '{name} 装载失败',
1049
+ 'config.mods.refusal.by': '被 {by} 拒绝',
1050
+ 'config.mods.rewrite.resultInPlace': '由 {by} 代替工具作答',
1013
1051
  };
1014
1052
  export const ZH_MESSAGES = Object.freeze(ZH);
1015
1053
  export const TERM_SLOTS = Object.freeze({
1054
+ 'session.background.refusal.envOff': ['SEMA_HEADLESS_DETACH'],
1055
+ 'session.thinking.offWithUltracodeOnBody': ['Ultracode'],
1016
1056
  'config.mcp.toolAxesInvalid': ['toolAxes'],
1017
1057
  'config.mcp.toolFacesInvalid': ['toolFaces'],
1018
1058
  'config.mcp.cloudToolAxesInvalid': ['toolAxes'],
package/dist/index.d.ts CHANGED
@@ -161,6 +161,8 @@ export * from './effortWire.js';
161
161
  export * from './adapter/types.js';
162
162
  export * from './adapter/downstream/turnUsageToModelUsage.js';
163
163
  export * from './adapter/downstream/eventToSdkMessage.js';
164
+ export { MOD_LOADER_VERBS, readModRegistrationRefusedNotice, modCardSentence, modLoaderFailureSentence, type ModLoaderVerb } from './modsFace.js';
165
+ export { modRowsOf } from './adapter/downstream/wiringManifestView.js';
164
166
  export type { WiringManifestView, WiringManifestSections, WiringManifestFleetView } from './adapter/downstream/wiringManifestView.js';
165
167
  export { wiringFleetDoctorDetail } from './wiringFleetDoctor.js';
166
168
  export * from './adapter/downstream/terminalToSdkResult.js';
@@ -352,6 +354,10 @@ export * from './hitl/askSettlementLine.js';
352
354
  export * from './interactiveHalt.js';
353
355
  export { fireInteractiveInterrupt } from './interactiveInterrupt.js';
354
356
  export type { InteractiveInterruptRuns, InteractiveInterruptOptions } from './interactiveInterrupt.js';
357
+ export { readSessionBackgroundable, projectSessionBackgroundable, interactiveEngineWire, retireInteractiveEngineWire, interactiveDetachPosture, streamInteractiveRun, backgroundHandoffEligibility, backgroundHandoffSentence, interactiveStopFacts, } from './sessionBackground.js';
358
+ export type { SessionBackgroundableReading, InteractiveEngineLane, InteractiveEngineWireInit, InteractiveEngineWire, InteractiveOpeningInput, InteractiveDetachPostureReason, InteractiveDetachPosture, InteractiveStreamOptions, BackgroundHandoffVerdict, BackgroundHandoffRefusal, BackgroundHandoffUnknown, InteractiveStopFacts, } from './sessionBackground.js';
359
+ export { BACKGROUND_HANDOFF_ABORT_REASON, handoffInteractiveRun, handedOffRunsOf, forgetHandedOffRun } from './sessionBackgroundHandoff.js';
360
+ export type { BackgroundHandoffRequest, BackgroundHandoffOutcome, BackgroundRun, BackgroundRunSettlement, HandedOffRunRow, HandedOffRunsReading, } from './sessionBackgroundHandoff.js';
355
361
  export { listDevices, readSessionBinding, rebindSession, reconcileRebindOutcome, rebindProvesRequestNotApplied } from './deviceRebind.js';
356
362
  export { issueEnrollToken, enrollDevice, revokeDevice, deviceIdentityMismatchOf, deviceIdentityMismatchLine, deviceRegistrationOutcomeLine } from './deviceRebind.js';
357
363
  export type { DeviceSummary, DeviceListResult, DeviceBinding, DeviceSessionBinding, DeviceRebindRequest, DeviceRevokeRequest, DeviceRebindResult, DeviceEnrollToken, DeviceEnrollRequest, DeviceEnrollResult, DeviceRevokeResult, } from '@sema-agent/sdk';
@@ -363,6 +369,8 @@ export * from './request/printNotification.js';
363
369
  export * from './seatContract.js';
364
370
  export { mcpToolTogglesToExcludeTools } from './mcpToolToggles.js';
365
371
  export type { McpToolToggleKey, McpMountedServers } from './mcpToolToggles.js';
372
+ export { readThinkingLatch, writeThinkingLatch, thinkingLatchView, thinkingLatchSentence, thinkingLatchRowWordOf, readSeatThinkingLatch } from './thinkingLatch.js';
373
+ export type { ThinkingLatchState, ThinkingLatchEvent, ThinkingLatchRowWord, ThinkingLatchStorePort, ThinkingLatchReading, ThinkingLatchWriteOutcome, ThinkingLatchView, ThinkingLatchCarrier, ThinkingLatchSentenceSubject, } from './thinkingLatch.js';
366
374
  export { devicesFaceOf, devicesWritesAllowed, devicesFaceDetail } from './devicesFace.js';
367
375
  export type { DevicesFace, DevicesFaceInput, DevicesFaceUnavailableWhy } from './devicesFace.js';
368
376
  export { cloudLoginFailureOf, cloudLoginFailureText, engineTargetRefusalText, seatMcpReadingOf, watchEngineTarget } from './engineTargetSeat.js';
package/dist/index.js CHANGED
@@ -139,6 +139,8 @@ export * from './effortWire.js';
139
139
  export * from './adapter/types.js';
140
140
  export * from './adapter/downstream/turnUsageToModelUsage.js';
141
141
  export * from './adapter/downstream/eventToSdkMessage.js';
142
+ export { MOD_LOADER_VERBS, readModRegistrationRefusedNotice, modCardSentence, modLoaderFailureSentence } from './modsFace.js';
143
+ export { modRowsOf } from './adapter/downstream/wiringManifestView.js';
142
144
  export { wiringFleetDoctorDetail } from './wiringFleetDoctor.js';
143
145
  export * from './adapter/downstream/terminalToSdkResult.js';
144
146
  export { resultErrorCodeOf, resultSelectedModelOf, resultSalvagedResultOf, resultParkFailedReasonOf } from './resultFrameKeys.js';
@@ -288,6 +290,8 @@ export { approvalCompleteCauseOf } from './hitl/approvalEndingCause.js';
288
290
  export * from './hitl/askSettlementLine.js';
289
291
  export * from './interactiveHalt.js';
290
292
  export { fireInteractiveInterrupt } from './interactiveInterrupt.js';
293
+ export { readSessionBackgroundable, projectSessionBackgroundable, interactiveEngineWire, retireInteractiveEngineWire, interactiveDetachPosture, streamInteractiveRun, backgroundHandoffEligibility, backgroundHandoffSentence, interactiveStopFacts, } from './sessionBackground.js';
294
+ export { BACKGROUND_HANDOFF_ABORT_REASON, handoffInteractiveRun, handedOffRunsOf, forgetHandedOffRun } from './sessionBackgroundHandoff.js';
291
295
  export { listDevices, readSessionBinding, rebindSession, reconcileRebindOutcome, rebindProvesRequestNotApplied } from './deviceRebind.js';
292
296
  export { issueEnrollToken, enrollDevice, revokeDevice, deviceIdentityMismatchOf, deviceIdentityMismatchLine, deviceRegistrationOutcomeLine } from './deviceRebind.js';
293
297
  export { resolveEngineEnvSourcing, engineEnvView } from './engineEnvSourcing.js';
@@ -295,6 +299,7 @@ export * from './compensations.js';
295
299
  export * from './request/printNotification.js';
296
300
  export * from './seatContract.js';
297
301
  export { mcpToolTogglesToExcludeTools } from './mcpToolToggles.js';
302
+ export { readThinkingLatch, writeThinkingLatch, thinkingLatchView, thinkingLatchSentence, thinkingLatchRowWordOf, readSeatThinkingLatch } from './thinkingLatch.js';
298
303
  export { devicesFaceOf, devicesWritesAllowed, devicesFaceDetail } from './devicesFace.js';
299
304
  export { cloudLoginFailureOf, cloudLoginFailureText, engineTargetRefusalText, seatMcpReadingOf, watchEngineTarget } from './engineTargetSeat.js';
300
305
  export { KEY_SLOT_PREFIX, keyEnvNameForEntry, onboardBaseUrlProblem, onboardRefusalText, onboardWritePlan, onboardWriteVerdict, poolEntryNameOf, probeModelEndpoint, } from './model/onboardJudgement.js';
@@ -11,13 +11,15 @@ export type InteractiveHaltInterruptOutcome = {
11
11
  } | {
12
12
  kind: 'transport';
13
13
  detail?: string | undefined;
14
+ } | {
15
+ kind: 'withheld';
14
16
  };
15
17
  export interface InteractiveHaltInput {
16
18
  readonly parked?: boolean | undefined;
17
19
  readonly detachArmed?: boolean | undefined;
18
20
  readonly interruptOutcome?: InteractiveHaltInterruptOutcome | undefined;
19
21
  }
20
- export type InteractiveHaltReason = 'first-shot' | 'halted' | 'engine-says-run-level' | 'no-verdict-on-parked-card' | 'no-verdict-detach-armed' | 'no-verdict-not-parked' | 'refused-no-escalation' | 'unknown-outcome';
22
+ export type InteractiveHaltReason = 'first-shot' | 'halted' | 'engine-says-run-level' | 'no-verdict-on-parked-card' | 'no-verdict-detach-armed' | 'no-verdict-not-parked' | 'refused-no-escalation' | 'unknown-outcome' | 'handed-off';
21
23
  export interface InteractiveHaltPlan {
22
24
  readonly action: 'interrupt' | 'escalate-cancel' | 'none';
23
25
  readonly reason: InteractiveHaltReason;
@@ -32,6 +32,8 @@ export function planInteractiveHalt(input) {
32
32
  ? { action: 'escalate-cancel', reason: 'engine-says-run-level' }
33
33
  : { action: 'none', reason: 'refused-no-escalation' };
34
34
  }
35
+ if (kind === 'withheld')
36
+ return { action: 'none', reason: 'handed-off' };
35
37
  if (kind === 'transport' || kind === 'unarmed') {
36
38
  if (input.parked === true)
37
39
  return { action: 'escalate-cancel', reason: 'no-verdict-on-parked-card' };
@@ -1,8 +1,10 @@
1
1
  import type { AgentClient } from '@sema-agent/sdk';
2
2
  import type { InteractiveHaltInterruptOutcome } from './interactiveHalt.js';
3
+ import { type InteractiveEngineWire } from './sessionBackground.js';
3
4
  export type InteractiveInterruptRuns = Pick<AgentClient['runs'], 'interrupt'>;
4
5
  export interface InteractiveInterruptOptions {
5
6
  readonly sessionId?: string | undefined;
6
7
  readonly signal?: AbortSignal | undefined;
8
+ readonly wire?: InteractiveEngineWire | undefined;
7
9
  }
8
10
  export declare function fireInteractiveInterrupt(runs: InteractiveInterruptRuns | null | undefined, taskId: string, opts?: InteractiveInterruptOptions): Promise<InteractiveHaltInterruptOutcome>;
@@ -1,5 +1,6 @@
1
1
  import { atMostOnceVerdictOf } from './atMostOnce.js';
2
2
  import { readOwnDataValue } from './ownKey.js';
3
+ import { noteInteractiveStopRequested, ownSlotOf } from './sessionBackground.js';
3
4
  function guardedSlot(e, key) {
4
5
  if (e === null || (typeof e !== 'object' && typeof e !== 'function'))
5
6
  return undefined;
@@ -33,6 +34,20 @@ function turnCutOf(receipt) {
33
34
  }
34
35
  }
35
36
  export async function fireInteractiveInterrupt(runs, taskId, opts = {}) {
37
+ if (opts !== null && typeof opts === 'object') {
38
+ const ws = ownSlotOf(opts, 'wire');
39
+ if (ws.state === 'unreadable')
40
+ return { kind: 'withheld' };
41
+ if (ws.state === 'data') {
42
+ const wire = ws.value;
43
+ if (wire !== null) {
44
+ if (typeof wire !== 'object')
45
+ return { kind: 'withheld' };
46
+ if (noteInteractiveStopRequested(wire, taskId) === 'withheld')
47
+ return { kind: 'withheld' };
48
+ }
49
+ }
50
+ }
36
51
  const verb = guardedSlot(runs, 'interrupt');
37
52
  if (typeof verb !== 'function')
38
53
  return { kind: 'unarmed' };
@@ -0,0 +1,8 @@
1
+ import type { WiringManifestModRefusedView } from './adapter/downstream/eventToSdkMessage.js';
2
+ import type { EngineNoticeChromeEvent } from './seam.js';
3
+ import type { UiLanguage } from './env/uiLanguage.js';
4
+ export declare const MOD_LOADER_VERBS: readonly ["list", "load", "unload", "status"];
5
+ export type ModLoaderVerb = (typeof MOD_LOADER_VERBS)[number];
6
+ export declare function readModRegistrationRefusedNotice(ev: EngineNoticeChromeEvent): WiringManifestModRefusedView | undefined;
7
+ export declare function modCardSentence(input: object | null | undefined, lang?: UiLanguage): string | undefined;
8
+ export declare function modLoaderFailureSentence(name: string, error: unknown, lang?: UiLanguage): string;
@@ -0,0 +1,59 @@
1
+ import { modRowsOf } from './adapter/downstream/wiringManifestView.js';
2
+ import { msg, renderMessage } from './i18n/translate.js';
3
+ import { displayUntrusted } from './displayUntrusted.js';
4
+ import { WIRE_FAILURE_UNRENDERABLE_TEXT, wireFailureTextsOf } from './wireFailureShape.js';
5
+ import { gateOutcomeOf, isDeniedGate } from './gateOutcome.js';
6
+ import { guardedRead, readOwnDataNonEmptyString, readOwnDataValue, toolResultBlockOf } from './ownKey.js';
7
+ const isCardRecordObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
8
+ export const MOD_LOADER_VERBS = Object.freeze(['list', 'load', 'unload', 'status']);
9
+ const modRowOf = (r) => modRowsOf([r])?.[0];
10
+ const MODS_REGISTRATION_REFUSED_NOTICE_CODE = 'mods.registration_refused';
11
+ export function readModRegistrationRefusedNotice(ev) {
12
+ try {
13
+ if (!isCardRecordObject(ev))
14
+ return undefined;
15
+ if (readOwnDataValue(ev, 'code') !== MODS_REGISTRATION_REFUSED_NOTICE_CODE)
16
+ return undefined;
17
+ const row = modRowOf(readOwnDataValue(ev, 'detail'));
18
+ return row !== undefined && 'refusedBy' in row ? row : undefined;
19
+ }
20
+ catch {
21
+ return undefined;
22
+ }
23
+ }
24
+ const MOD_NAME_SHOWN_MAX = 64;
25
+ const MOD_REASON_SHOWN_MAX = 160;
26
+ const shownName = (s) => displayUntrusted(s, { blanks: true, max: MOD_NAME_SHOWN_MAX });
27
+ const shownReason = (s) => displayUntrusted(s, { max: MOD_REASON_SHOWN_MAX });
28
+ export function modCardSentence(input, lang) {
29
+ try {
30
+ if (!isCardRecordObject(input))
31
+ return undefined;
32
+ if (toolResultBlockOf(input) !== undefined) {
33
+ const by = readOwnDataNonEmptyString(input, '_sema_answered_by');
34
+ if (by === undefined)
35
+ return undefined;
36
+ const gate = gateOutcomeOf({ gate: readOwnDataValue(input, '_sema_gate') });
37
+ return isDeniedGate(gate)
38
+ ? renderMessage(msg('config.mods.refusal.by', { by: shownName(by) }), lang)
39
+ : renderMessage(msg('config.mods.rewrite.resultInPlace', { by: shownName(by) }), lang);
40
+ }
41
+ const row = modRowOf(input);
42
+ if (row === undefined)
43
+ return undefined;
44
+ if ('refusedBy' in row) {
45
+ return renderMessage(msg('config.mods.card.refused', { name: shownName(row.name), refusedBy: shownName(row.refusedBy), reason: shownReason(row.reason) }), lang);
46
+ }
47
+ return renderMessage(msg('config.mods.card.mounted', { name: shownName(row.name) }), lang);
48
+ }
49
+ catch {
50
+ return undefined;
51
+ }
52
+ }
53
+ export function modLoaderFailureSentence(name, error, lang) {
54
+ const shown = guardedRead(() => (typeof name === 'string' ? shownName(name) : undefined)) ?? '';
55
+ const { reason } = wireFailureTextsOf(error);
56
+ if (reason === WIRE_FAILURE_UNRENDERABLE_TEXT)
57
+ return renderMessage(msg('config.mods.loader.failedNoReason', { name: shown }), lang);
58
+ return renderMessage(msg('config.mods.loader.failed', { name: shown, reason: shownReason(reason) }), lang);
59
+ }
package/dist/ownKey.d.ts CHANGED
@@ -6,6 +6,7 @@ export declare function readOwnDataFiniteNumber(v: object | null | undefined, ke
6
6
  export declare function readOwnDataValue<T>(v: object | null | undefined, key: string): T | undefined;
7
7
  export declare function carriesAnswerText(text: string): boolean;
8
8
  export declare function appendOwnElement<T>(list: T[], value: T): void;
9
+ export declare function toolResultBlockOf(record: object): object | undefined;
9
10
  export declare function guardedRead<T>(read: () => T | undefined): T | undefined;
10
11
  export declare function ownDataField(v: object, key: string): unknown;
11
12
  export declare function ownSendableField(v: object, key: string): unknown;
package/dist/ownKey.js CHANGED
@@ -40,6 +40,21 @@ export function carriesAnswerText(text) {
40
40
  export function appendOwnElement(list, value) {
41
41
  Object.defineProperty(list, list.length, { value, writable: true, enumerable: true, configurable: true });
42
42
  }
43
+ export function toolResultBlockOf(record) {
44
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
45
+ const message = ownDataField(record, 'message');
46
+ if (!isRecord(message))
47
+ return undefined;
48
+ const content = ownDataField(message, 'content');
49
+ if (!Array.isArray(content))
50
+ return undefined;
51
+ for (let i = 0; i < content.length; i++) {
52
+ const block = ownDataField(content, String(i));
53
+ if (isRecord(block) && ownDataField(block, 'type') === 'tool_result')
54
+ return block;
55
+ }
56
+ return undefined;
57
+ }
43
58
  export function guardedRead(read) {
44
59
  try {
45
60
  return read();
@@ -41,7 +41,7 @@ export function toolEndResultToUserFrame(arm) {
41
41
  parent_tool_use_id: parent,
42
42
  ...(isCcToolDenialKind(arm._sema_denial_kind) ? { _sema_denial_kind: arm._sema_denial_kind } : {}),
43
43
  ...(gateView !== undefined ? { _sema_gate: gateView } : {}),
44
- ...toolResultRowFlagParts(arm),
44
+ ...toolResultRowFlagParts(arm, gateView),
45
45
  ...(Object.hasOwn(envelope, 'tool_use_result') ? { tool_use_result: envelope.tool_use_result } : {}),
46
46
  ...(Object.hasOwn(envelope, '_sema_degraded') ? { _sema_degraded: envelope._sema_degraded } : {}),
47
47
  uuid: rowIdentity.uuid,
@@ -16,7 +16,7 @@ export const PRINT_NOTIFICATION_FIELD_MATRIX = [
16
16
  { field: '_sema_partial', from: 'partial', cc: false, why: 'server 1.258:被终止子代的残果(消费方须渲成不完整,不得当完整结果)' },
17
17
  { field: '_sema_exit_code', from: 'exitCode', cc: false, why: '后台 bash 退出码(137=OOM 这类归因只在这一位上)' },
18
18
  { field: '_sema_diagnostics', from: 'diagnostics', cc: false, why: '引擎侧诊断串(UNTRUSTED,service 已 redact)' },
19
- { field: '_sema_result', from: 'result', cc: false, why: '完成结果正文(#49 C1:帧带 result 必入 XML,print 出口同理不得独漏)' },
19
+ { field: '_sema_result', from: 'result', cc: false, why: '完成结果正文(帧带 result 必入 XML,print 出口同理不得独漏)' },
20
20
  { field: '_sema_lines', from: 'lines', cc: false, why: '尾部输出行(UNTRUSTED);交互面折进 <output-lines>' },
21
21
  { field: '_sema_recent_steps', from: 'recentSteps', cc: false, why: '结构化残局步骤 {tool,target,outcome}[] —— **原样透传**,不降级成交互面那份显示串(SDK 消费方要结构)' },
22
22
  { field: '_sema_edited_files', from: 'editedFiles', cc: false, why: '结构化改档清单 {path,edits}[];同上原样透传' },
@@ -1,4 +1,5 @@
1
1
  import type { TaskRequest, UserAttachment } from '@sema-agent/sdk';
2
+ import { type ThinkingLatchState } from '../thinkingLatchWords.js';
2
3
  import { type ApprovalFrameFamiliesReading, type ApprovalFrameFamiliesWithheld } from '../approvalFrameFamilies.js';
3
4
  import { type OutputStyleSeatReading } from '../outputStyleSeatCapability.js';
4
5
  import { type ApprovalReachWord } from '../approvalReachWire.js';
@@ -66,6 +67,8 @@ export interface TaskRequestInput {
66
67
  repo?: string;
67
68
  hostSettings: HostTurnSettings;
68
69
  approvalFrameFamiliesReading?: ApprovalFrameFamiliesReading;
70
+ thinkingLatch?: 'on' | 'off';
71
+ reasoningFloor?: string;
69
72
  settings?: {
70
73
  ultracode?: boolean;
71
74
  };
@@ -84,6 +87,23 @@ export interface TaskRequestAssembly {
84
87
  readonly omitted: readonly TaskRequestOmission[];
85
88
  readonly host: HostTurnSettings;
86
89
  readonly approvalFrameFamiliesWithheld?: ApprovalFrameFamiliesWithheld;
90
+ readonly thinking: ThinkingTurnProjection;
91
+ }
92
+ export interface ThinkingTurnInput {
93
+ readonly submission: RequestLane | SubmissionIdentity;
94
+ readonly live: boolean;
95
+ readonly latch?: 'on' | 'off';
96
+ readonly strength?: unknown;
97
+ readonly floor?: string;
98
+ readonly ultracode?: boolean;
99
+ }
100
+ export interface ThinkingTurnProjection {
101
+ readonly word?: unknown;
102
+ readonly verdict: 'utility_lane' | 'off' | 'strength';
103
+ readonly latch: ThinkingLatchState;
104
+ readonly ultracodeStamped: boolean;
105
+ readonly floorApplied?: true;
106
+ readonly strengthOverruled?: unknown;
87
107
  }
88
108
  export type TaskRequestSeatReading = {
89
109
  readonly seat: 'seated';
@@ -136,6 +156,7 @@ export type MaxCostUsdParse = {
136
156
  export declare function parseMaxCostUsd(text: unknown): MaxCostUsdParse;
137
157
  export declare function assembleTaskRequest(input: TaskRequestInput, laneOrIdentity: RequestLane | SubmissionIdentity): TaskRequestAssembly;
138
158
  export declare function buildTaskRequest(input: TaskRequestInput, laneOrIdentity: RequestLane | SubmissionIdentity): TaskRequestLike;
159
+ export declare function thinkingTurnProjection(input: ThinkingTurnInput): ThinkingTurnProjection;
139
160
  export interface LiveDefaultsInput {
140
161
  cwd?: string;
141
162
  additionalDirectories?: readonly string[];