@sema-agent/client-core 0.98.0 → 0.100.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +376 -0
- package/README.md +61 -35
- package/dist/adapt/arms.js +120 -55
- package/dist/adapt/panelTasks.d.ts +3 -2
- package/dist/adapt/panelTasks.js +34 -11
- package/dist/adapt/textStream.d.ts +1 -1
- package/dist/adapt/textStream.js +51 -28
- package/dist/adapter/activeRunSelfHeal.d.ts +11 -3
- package/dist/adapter/activeRunSelfHeal.js +210 -294
- package/dist/adapter/downstream/eventToSdkMessage.d.ts +25 -6
- package/dist/adapter/downstream/eventToSdkMessage.js +176 -12
- package/dist/adapter/downstream/terminalToSdkResult.js +10 -0
- package/dist/adapter/downstream/wiringManifestView.d.ts +3 -1
- package/dist/adapter/downstream/wiringManifestView.js +1 -0
- package/dist/adapter/runStream.js +82 -40
- package/dist/adapter/types.d.ts +2 -0
- package/dist/adapter/types.js +2 -1
- package/dist/agentSession/engineSessionBackgroundStop.js +16 -8
- package/dist/agentsWireCaps.d.ts +7 -3
- package/dist/agentsWireCaps.js +133 -39
- package/dist/cloudConfigWireCaps.d.ts +10 -1
- package/dist/cloudConfigWireCaps.js +181 -65
- package/dist/compactionStatus.d.ts +34 -0
- package/dist/compactionStatus.js +196 -0
- package/dist/controlRouter.d.ts +4 -2
- package/dist/controlRouter.js +39 -51
- package/dist/coreValuePorts.d.ts +26 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/corruptSessionCopy.d.ts +2 -1
- package/dist/corruptSessionCopy.js +3 -3
- package/dist/decideFailureNote.js +3 -3
- package/dist/declared/supportFloorDeclared.js +1 -1
- package/dist/detachWire.js +3 -2
- package/dist/devicesFace.d.ts +34 -0
- package/dist/devicesFace.js +90 -0
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +153 -5
- package/dist/engineAgentPanelStore.d.ts +14 -4
- package/dist/engineAgentPanelStore.js +14 -0
- package/dist/engineCapReader.d.ts +2 -1
- package/dist/engineCapReader.js +7 -5
- package/dist/engineCapsCache.d.ts +8 -0
- package/dist/engineCapsCache.js +59 -6
- package/dist/engineCapsChange.d.ts +2 -0
- package/dist/engineCapsChange.js +9 -0
- package/dist/engineErrorCodes.d.ts +11 -2
- package/dist/engineErrorCodes.js +11 -12
- package/dist/engineRowRef.js +4 -0
- package/dist/engineSessionMessages.d.ts +1 -0
- package/dist/engineSessionMessages.js +7 -1
- package/dist/engineTargetSeat.d.ts +27 -0
- package/dist/engineTargetSeat.js +199 -0
- package/dist/engineToolDirectory.d.ts +3 -0
- package/dist/engineToolDirectory.js +4 -2
- package/dist/engineWireFor.js +3 -8
- package/dist/env/uiLanguage.d.ts +2 -1
- package/dist/env/uiLanguage.js +3 -2
- package/dist/eventLeg.d.ts +7 -5
- package/dist/eventLeg.js +68 -49
- package/dist/fileHistoryCaptureCapability.d.ts +2 -4
- package/dist/fileHistoryCaptureCapability.js +12 -22
- package/dist/fileHistoryLegNotice.d.ts +2 -1
- package/dist/fileHistoryLegNotice.js +3 -3
- package/dist/frameBinding.d.ts +3 -0
- package/dist/frameBinding.js +12 -0
- package/dist/gateOutcome.js +16 -2
- package/dist/gateVocabulary.d.ts +8 -7
- package/dist/gateVocabulary.js +71 -73
- package/dist/generated/engineFactTables.d.ts +18 -1
- package/dist/generated/engineFactTables.js +56 -0
- package/dist/generated/engineNoticeTables.js +12 -3
- package/dist/generated/settingsSchemaFns.d.ts +18 -0
- package/dist/generated/settingsSchemaFns.js +70 -0
- package/dist/generated/settingsSchemaHooksClassifier.d.ts +2 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +254 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -0
- package/dist/generated/settingsSchemaMcpRequestEntry.js +162 -0
- package/dist/generated/settingsSchemaTables.d.ts +2 -0
- package/dist/generated/settingsSchemaTables.js +9 -0
- package/dist/generated/settingsSchemaTypes.d.ts +133 -0
- package/dist/generated/settingsSchemaTypes.js +1 -0
- package/dist/hitl/allowRuleShadow.d.ts +2 -1
- package/dist/hitl/allowRuleShadow.js +18 -15
- package/dist/hitl/approvalCardReasons.d.ts +3 -2
- package/dist/hitl/approvalCardReasons.js +29 -30
- package/dist/hitl/approvalHolds.d.ts +17 -0
- package/dist/hitl/approvalHolds.js +114 -29
- package/dist/hitl/askClassPair.d.ts +2 -2
- package/dist/hitl/askClassPair.js +16 -0
- package/dist/hitl/askGateWire.js +2 -1
- package/dist/hitl/askSettlementLine.d.ts +14 -4
- package/dist/hitl/askSettlementLine.js +67 -47
- package/dist/hitl/attributionLadder.d.ts +23 -0
- package/dist/hitl/attributionLadder.js +67 -0
- package/dist/hitl/automaticAnswerVerdict.d.ts +2 -1
- package/dist/hitl/automaticAnswerVerdict.js +8 -8
- package/dist/hitl/crashConvergedNotice.d.ts +5 -4
- package/dist/hitl/crashConvergedNotice.js +28 -41
- package/dist/hitl/decisionLedger.d.ts +55 -0
- package/dist/hitl/decisionLedger.js +156 -0
- package/dist/hitl/decisionRefusal.d.ts +1 -0
- package/dist/hitl/decisionRefusal.js +1 -1
- package/dist/hitl/decisionSend.d.ts +113 -0
- package/dist/hitl/decisionSend.js +579 -0
- package/dist/hitl/frameRouter.js +7 -8
- package/dist/hitl/hitlBridge.d.ts +1 -0
- package/dist/hitl/hitlBridge.js +21 -9
- package/dist/hitl/persistedRulesWire.d.ts +6 -5
- package/dist/hitl/persistedRulesWire.js +55 -73
- package/dist/hitl/planReviewWire.d.ts +5 -0
- package/dist/hitl/planReviewWire.js +53 -76
- package/dist/hitl/sessionPolicyDeliverable.d.ts +2 -0
- package/dist/hitl/sessionPolicyDeliverable.js +49 -9
- package/dist/hitl/sessionPolicyWire.d.ts +2 -1
- package/dist/hitl/sessionPolicyWire.js +23 -24
- package/dist/hitl/suspendedReopen.d.ts +2 -1
- package/dist/hitl/suspendedReopen.js +7 -10
- package/dist/hitl/toolApprovalWire.d.ts +17 -5
- package/dist/hitl/toolApprovalWire.js +120 -147
- package/dist/hooksWireCaps.js +145 -56
- package/dist/host.d.ts +21 -0
- package/dist/hostTurnSettings.d.ts +110 -0
- package/dist/hostTurnSettings.js +692 -0
- package/dist/humanTurn.d.ts +15 -1
- package/dist/humanTurn.js +100 -12
- package/dist/humanTurnRead.d.ts +2 -0
- package/dist/humanTurnRead.js +22 -1
- package/dist/i18n/messages.en.d.ts +713 -0
- package/dist/i18n/messages.en.js +713 -0
- package/dist/i18n/messages.zh.js +854 -1
- package/dist/index.d.ts +45 -13
- package/dist/index.js +27 -9
- package/dist/inheritEnvCapability.d.ts +4 -2
- package/dist/inheritEnvCapability.js +12 -5
- package/dist/inheritEnvWire.d.ts +3 -2
- package/dist/inheritEnvWire.js +14 -16
- package/dist/injectionLaneNotice.d.ts +5 -0
- package/dist/injectionLaneNotice.js +46 -0
- package/dist/interactiveHalt.js +17 -6
- package/dist/liveModelCatalog.d.ts +2 -1
- package/dist/liveModelCatalog.js +14 -8
- package/dist/mcpPanel.d.ts +10 -1
- package/dist/mcpPanel.js +42 -13
- package/dist/mcpProbeCapability.d.ts +2 -1
- package/dist/mcpProbeCapability.js +7 -11
- package/dist/mcpProbeWire.d.ts +3 -1
- package/dist/mcpProbeWire.js +5 -0
- package/dist/mcpReconnect.js +2 -2
- package/dist/mcpToolToggles.d.ts +6 -0
- package/dist/mcpToolToggles.js +46 -0
- package/dist/mcpWireCaps.d.ts +43 -3
- package/dist/mcpWireCaps.js +194 -59
- package/dist/mcpWireTransport.d.ts +4 -0
- package/dist/mcpWireTransport.js +18 -0
- package/dist/memoryEntriesWire.js +5 -10
- package/dist/model/onboardJudgement.d.ts +93 -0
- package/dist/model/onboardJudgement.js +415 -0
- package/dist/model/tierVocabulary.d.ts +2 -0
- package/dist/model/tierVocabulary.js +17 -5
- package/dist/modelCapabilityProbe.d.ts +65 -0
- package/dist/modelCapabilityProbe.js +601 -0
- package/dist/modelIdentityResolvability.d.ts +5 -0
- package/dist/modelIdentityResolvability.js +49 -22
- package/dist/ownKey.d.ts +33 -0
- package/dist/ownKey.js +109 -0
- package/dist/panelReduce.d.ts +11 -1
- package/dist/panelReduce.js +95 -16
- package/dist/panelStateHolder.d.ts +1 -0
- package/dist/panelStateHolder.js +10 -1
- package/dist/permissionRuleIssue.d.ts +2 -1
- package/dist/permissionRuleIssue.js +23 -20
- package/dist/permissionRulesWriteCapability.d.ts +2 -1
- package/dist/permissionRulesWriteCapability.js +8 -6
- package/dist/pluginHooksWire.d.ts +46 -3
- package/dist/pluginHooksWire.js +220 -12
- package/dist/prepareRefusal.d.ts +8 -0
- package/dist/prepareRefusal.js +72 -0
- package/dist/printModelStatus.d.ts +63 -0
- package/dist/printModelStatus.js +155 -0
- package/dist/request/taskRequest.d.ts +16 -10
- package/dist/request/taskRequest.js +195 -58
- package/dist/resumeRefusalCopy.d.ts +14 -9
- package/dist/resumeRefusalCopy.js +89 -144
- package/dist/retryStatus.d.ts +55 -0
- package/dist/retryStatus.js +155 -19
- package/dist/ruleRefusalSentence.d.ts +4 -0
- package/dist/ruleRefusalSentence.js +58 -0
- package/dist/sandboxWire.d.ts +2 -1
- package/dist/sandboxWire.js +55 -21
- package/dist/scenarioRefusal.d.ts +10 -0
- package/dist/scenarioRefusal.js +111 -0
- package/dist/seam.d.ts +48 -9
- package/dist/seam.js +54 -5
- package/dist/seatContract.d.ts +272 -14
- package/dist/seatContract.js +711 -23
- package/dist/selfOrchestrationDenial.js +7 -19
- package/dist/sessionIdSegment.d.ts +6 -0
- package/dist/sessionIdSegment.js +24 -0
- package/dist/sessionMemoryStatus.js +6 -11
- package/dist/sessionPolicyCapability.d.ts +2 -1
- package/dist/sessionPolicyCapability.js +8 -6
- package/dist/settingsCredentialKeyPaths.d.ts +8 -0
- package/dist/settingsCredentialKeyPaths.js +219 -0
- package/dist/settingsHooksSalvage.d.ts +44 -0
- package/dist/settingsHooksSalvage.js +211 -0
- package/dist/skillToolListsCapability.d.ts +2 -1
- package/dist/skillToolListsCapability.js +8 -6
- package/dist/skillsWireCaps.d.ts +0 -3
- package/dist/skillsWireCaps.js +1 -2
- package/dist/sseIdleTriage.js +3 -2
- package/dist/subagent/engineSubagentResume.js +15 -9
- package/dist/subagentContentStore.d.ts +4 -0
- package/dist/subagentContentStore.js +157 -27
- package/dist/toolHistoryMismatch.js +3 -2
- package/dist/toolRoster.d.ts +3 -2
- package/dist/toolRoster.js +21 -20
- package/dist/toolsFlagNames.d.ts +8 -0
- package/dist/toolsFlagNames.js +110 -0
- package/dist/turnFailurePresentation.d.ts +12 -1
- package/dist/turnFailurePresentation.js +220 -15
- package/dist/usageAnalytics.js +6 -11
- package/dist/userAttachmentEnvelope.d.ts +1 -0
- package/dist/userAttachmentEnvelope.js +37 -7
- package/dist/userAttachmentSeat.d.ts +21 -0
- package/dist/userAttachmentSeat.js +75 -0
- package/dist/userInvokedSkillsCapability.d.ts +11 -1
- package/dist/userInvokedSkillsCapability.js +31 -7
- package/dist/wireErrorTriage.d.ts +7 -0
- package/dist/wireErrorTriage.js +23 -1
- package/dist/wireFailureShape.js +2 -1
- package/dist/wireRefusalCopy.d.ts +62 -16
- package/dist/wireRefusalCopy.js +307 -148
- package/dist/workflowsJournalCapability.d.ts +2 -1
- package/dist/workflowsJournalCapability.js +8 -6
- package/docs/INTEGRATION-CLIENTS.md +951 -42
- package/package.json +5 -5
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { abortableSleep } from '../abortableSleep.js';
|
|
2
|
+
import { EN_MESSAGES } from '../i18n/messages.en.js';
|
|
3
|
+
import { msg, renderMessage } from '../i18n/translate.js';
|
|
2
4
|
import { corruptStoredRowContent, corruptStoredRowWhere, effectiveWireErrorCode } from '../wireErrorTriage.js';
|
|
3
5
|
import { readThrownStatusSlot } from '../wireFailureShape.js';
|
|
4
6
|
import { steerBodyOf, UNOBSERVED_STEER_PRIORITY } from '../controlRouter.js';
|
|
@@ -42,6 +44,7 @@ export const PLAN_REVIEW_STATES = Object.freeze(['needs_review']);
|
|
|
42
44
|
export const ASK_PARK_STATES = Object.freeze(['suspended']);
|
|
43
45
|
export const RUNNING_STATES = Object.freeze(['running']);
|
|
44
46
|
export const CLAIM_HELD_STATES = SDK_RUN_LIVE_STATUSES;
|
|
47
|
+
export const PLAN_REVIEW_REOPEN_REFUSALS = Object.freeze(['invalid_call', 'no_delivery_path', 'not_presented', 'gate_record_gone', 'internal_error']);
|
|
45
48
|
export function selfHealSubmissionDisposition(outcome) {
|
|
46
49
|
switch (outcome.kind) {
|
|
47
50
|
case 'decision-pending':
|
|
@@ -788,7 +791,22 @@ async function runningChoiceArm(taskId, status, busy, statusFromWire, runs, deps
|
|
|
788
791
|
return { kind: 'running-steered', taskId, delivery, status: receiptStatus, reopened: null };
|
|
789
792
|
}
|
|
790
793
|
catch (e) {
|
|
791
|
-
|
|
794
|
+
const delivery = atMostOnceFailureClass(e);
|
|
795
|
+
const errorCode = failureWireCode(e);
|
|
796
|
+
let runStatus;
|
|
797
|
+
if (delivery === 'rejected' && errorCode === STEER_NOT_RUNNING_CODE && typeof runs.get === 'function' && !probeCallerAborted()) {
|
|
798
|
+
const probe = await probeRunStatusOnce(taskId, runs, runs.get, deps);
|
|
799
|
+
if (probe.status !== null)
|
|
800
|
+
runStatus = probe.status;
|
|
801
|
+
}
|
|
802
|
+
return {
|
|
803
|
+
kind: 'running-steer-failed',
|
|
804
|
+
taskId,
|
|
805
|
+
detail: describeFailure(e),
|
|
806
|
+
delivery,
|
|
807
|
+
...(errorCode !== undefined ? { errorCode } : {}),
|
|
808
|
+
...(runStatus !== undefined ? { runStatus } : {}),
|
|
809
|
+
};
|
|
792
810
|
}
|
|
793
811
|
}
|
|
794
812
|
if (choice === 'cancel' && canCancel && runs?.cancel !== undefined && runs.get !== undefined) {
|
|
@@ -832,38 +850,62 @@ async function routeFreshNonRunning(fresh, taskId, busy, runs, deps) {
|
|
|
832
850
|
return { kind: 'running-settled', taskId, status: fresh };
|
|
833
851
|
return { kind: 'not-parked', taskId, status: fresh };
|
|
834
852
|
}
|
|
835
|
-
export const INTERACTIVE_WAY_OUT = '
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
853
|
+
export const INTERACTIVE_WAY_OUT = EN_MESSAGES['session.selfHeal.wayOut.interactive'];
|
|
854
|
+
const say = (lang, key, params) => renderMessage(msg(key, params), lang);
|
|
855
|
+
function gateKindPhrase(kind, lang) {
|
|
856
|
+
return kind ? say(lang, 'session.selfHeal.gate.kind', { kind }) : say(lang, 'session.selfHeal.gate.generic');
|
|
857
|
+
}
|
|
858
|
+
function endRunClause(copy, taskId, lang) {
|
|
859
|
+
let host;
|
|
860
|
+
try {
|
|
861
|
+
host = copy?.endRun;
|
|
862
|
+
}
|
|
863
|
+
catch {
|
|
864
|
+
host = undefined;
|
|
865
|
+
}
|
|
866
|
+
const phrase = typeof host === 'string' ? host.trim().replace(/[\s.;。;!!??]+$/u, '') : '';
|
|
867
|
+
if (/[\p{L}\p{N}]/u.test(phrase))
|
|
868
|
+
return phrase;
|
|
869
|
+
return say(lang, 'session.selfHeal.endRun.engine', { cancelPath: `POST /v1/runs/${taskId ? taskId : '<id>'}/cancel` });
|
|
840
870
|
}
|
|
841
|
-
function
|
|
871
|
+
function wakeSessionClause(copy, lang) {
|
|
872
|
+
let host;
|
|
873
|
+
try {
|
|
874
|
+
host = copy?.wakeSession;
|
|
875
|
+
}
|
|
876
|
+
catch {
|
|
877
|
+
host = undefined;
|
|
878
|
+
}
|
|
879
|
+
if (host === null)
|
|
880
|
+
return '';
|
|
881
|
+
if (typeof host === 'string' && host.trim().length > 0)
|
|
882
|
+
return say(lang, 'session.selfHeal.wakeOn.host', { where: host.trim() });
|
|
883
|
+
return say(lang, 'session.selfHeal.wakeOn.engine');
|
|
884
|
+
}
|
|
885
|
+
const STEER_NOT_RUNNING_CODE = 'steering.not_running';
|
|
886
|
+
function decidePathClause(signal, lang) {
|
|
842
887
|
const decidePath = signal?.pendingGate?.decidePath;
|
|
843
888
|
if (!decidePath)
|
|
844
889
|
return '';
|
|
845
|
-
return (
|
|
846
|
-
` decided at POST ${decidePath} — deciding it releases the session.`);
|
|
890
|
+
return say(lang, 'session.selfHeal.decidePathClause', { gate: gateKindPhrase(signal?.pendingGate?.kind, lang), decidePath });
|
|
847
891
|
}
|
|
848
|
-
function governanceOriginClause(signal) {
|
|
849
|
-
return signal?.pendingGate?.governanceForced === true
|
|
850
|
-
? ' That gate is enforced by this deployment\'s governance policy, not by a permission rule you set.'
|
|
851
|
-
: '';
|
|
892
|
+
function governanceOriginClause(signal, lang) {
|
|
893
|
+
return signal?.pendingGate?.governanceForced === true ? say(lang, 'session.selfHeal.governanceOrigin') : '';
|
|
852
894
|
}
|
|
853
|
-
function lastActivityClause(signal) {
|
|
895
|
+
function lastActivityClause(signal, lang) {
|
|
854
896
|
const ms = signal?.msSinceLastActivity;
|
|
855
897
|
if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0)
|
|
856
898
|
return '';
|
|
857
899
|
const human = ms < 120_000 ? `${String(Math.max(1, Math.round(ms / 1000)))}s` : `${String(Math.round(ms / 60_000))}m`;
|
|
858
|
-
return
|
|
900
|
+
return say(lang, 'session.selfHeal.lastActivity', { ago: human });
|
|
859
901
|
}
|
|
860
|
-
export function activeRunSelfHealRow(outcome, signal, copy, origin, follow) {
|
|
902
|
+
export function activeRunSelfHealRow(outcome, signal, copy, origin, follow, lang) {
|
|
861
903
|
const override = copy?.rowFor?.(outcome, signal);
|
|
862
904
|
if (typeof override === 'string')
|
|
863
905
|
return override;
|
|
864
906
|
const following = follow?.following === true && steerFollowIntent(outcome)?.kind === 'tail';
|
|
865
907
|
if (origin === 'injected')
|
|
866
|
-
return injectedSubmissionRow(outcome, following);
|
|
908
|
+
return injectedSubmissionRow(outcome, following, lang);
|
|
867
909
|
const engineDecide = copy?.engineDecidePath !== false;
|
|
868
910
|
const keep = (outcome.kind === 'plan-review-reopen-failed' || outcome.kind === 'ask-reopen-failed') &&
|
|
869
911
|
outcome.decisionInFlight !== true &&
|
|
@@ -871,101 +913,77 @@ export function activeRunSelfHealRow(outcome, signal, copy, origin, follow) {
|
|
|
871
913
|
(outcome.kind !== 'plan-review-reopen-failed' || outcome.dismissedByUser !== true)
|
|
872
914
|
? keepSessionWayOutOf(copy)
|
|
873
915
|
: null;
|
|
874
|
-
const base = activeRunSelfHealBaseRow(outcome, copy?.wayOut ??
|
|
875
|
-
const viaEngine = engineDecide ? decidePathClause(signal) : '';
|
|
916
|
+
const base = activeRunSelfHealBaseRow(outcome, copy?.wayOut ?? say(lang, 'session.selfHeal.wayOut.interactive'), following, keep, engineDecide, lang, copy);
|
|
917
|
+
const viaEngine = engineDecide ? decidePathClause(signal, lang) : '';
|
|
876
918
|
switch (outcome.kind) {
|
|
877
919
|
case 'not-parked':
|
|
878
|
-
return base + lastActivityClause(signal) + (outcome.pendingGateKind !== undefined ? viaEngine + governanceOriginClause(signal) : '');
|
|
920
|
+
return base + lastActivityClause(signal, lang) + (outcome.pendingGateKind !== undefined ? viaEngine + governanceOriginClause(signal, lang) : '');
|
|
879
921
|
case 'state-unknown':
|
|
880
|
-
return base + viaEngine + governanceOriginClause(signal);
|
|
922
|
+
return base + viaEngine + governanceOriginClause(signal, lang);
|
|
881
923
|
default:
|
|
882
|
-
return base + governanceOriginClause(signal);
|
|
924
|
+
return base + governanceOriginClause(signal, lang);
|
|
883
925
|
}
|
|
884
926
|
}
|
|
885
|
-
|
|
886
|
-
const
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
const id = 'taskId' in outcome && outcome.taskId ? ` (id ${outcome.taskId})` : '';
|
|
891
|
-
if (outcome.kind === 'running-attach') {
|
|
892
|
-
return `${lead} was not delivered: you chose to watch the reply already in progress${id} instead, and sema is replaying that reply here, so the part already shown above will appear again below. sema did not retry, so the model has not seen it.`;
|
|
893
|
-
}
|
|
927
|
+
function injectedSubmissionRow(outcome, following = false, lang) {
|
|
928
|
+
const lead = msg('session.selfHeal.injected.lead');
|
|
929
|
+
const id = 'taskId' in outcome && outcome.taskId ? msg('session.selfHeal.injected.id', { id: outcome.taskId }) : '';
|
|
930
|
+
if (outcome.kind === 'running-attach')
|
|
931
|
+
return say(lang, 'session.selfHeal.injected.attach', { lead, id });
|
|
894
932
|
if (outcome.kind === 'running-steer-failed') {
|
|
895
933
|
return outcome.delivery === 'unknown'
|
|
896
|
-
?
|
|
897
|
-
|
|
898
|
-
`is not safe; watch that reply for what it does next.`
|
|
899
|
-
: `${lead} was not delivered: passing it to the reply already in progress${id} was refused (${outcome.detail}). ` +
|
|
900
|
-
`sema did not retry, so the model has not seen it.`;
|
|
934
|
+
? say(lang, 'session.selfHeal.injected.steerUnknown', { lead, id, detail: outcome.detail })
|
|
935
|
+
: say(lang, 'session.selfHeal.injected.steerRejected', { lead, id, detail: outcome.detail });
|
|
901
936
|
}
|
|
902
937
|
if ((outcome.kind === 'ask-reopen-failed' || outcome.kind === 'plan-review-reopen-failed') && outcome.decisionInFlight === true) {
|
|
903
|
-
return (
|
|
904
|
-
`it is waiting on is still on its way. sema did not retry, so the model has not seen it.`);
|
|
938
|
+
return say(lang, 'session.selfHeal.injected.decisionInFlight', { lead, id });
|
|
905
939
|
}
|
|
906
940
|
if (outcome.kind === 'plan-review-reopen-failed' && outcome.dismissedByUser === true) {
|
|
907
|
-
return (
|
|
908
|
-
`you closed that approval card — ${USER_CLOSED_CARD_NOT_PUT_BACK}. Send a message when you want the card back; ` +
|
|
909
|
-
`sema did not retry, so the model has not seen it.`);
|
|
941
|
+
return say(lang, 'session.selfHeal.injected.dismissedPlan', { lead, id, closed: msg('session.selfHeal.userClosedCardNotPutBack') });
|
|
910
942
|
}
|
|
911
943
|
if (outcome.kind === 'running-steered' && outcome.delivery === 'queued') {
|
|
912
|
-
const queuedOn =
|
|
944
|
+
const queuedOn = msg('session.selfHeal.injected.queuedOn', { lead, id });
|
|
913
945
|
const reopened = reopenedOfOutcome(outcome);
|
|
914
|
-
if (reopened !== null && reopenDelivered(reopened))
|
|
915
|
-
return
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
`back, and the message is picked up once that decision is made.`);
|
|
923
|
-
}
|
|
924
|
-
const noView = reopenRefusedForNoPresentationSurface(reopened) ? ` (${NO_CARD_VIEW_ATTACHED})` : '';
|
|
925
|
-
return `${queuedOn} sema could not show here${noView}; the message is picked up only once that decision is made.`;
|
|
946
|
+
if (reopened !== null && reopenDelivered(reopened))
|
|
947
|
+
return say(lang, 'session.selfHeal.injected.queuedShown', { queuedOn });
|
|
948
|
+
if (reopenRefusedForDecisionInFlight(reopened))
|
|
949
|
+
return say(lang, 'session.selfHeal.injected.queuedInFlight', { queuedOn });
|
|
950
|
+
if (reopenRefusedForUserDismissal(reopened))
|
|
951
|
+
return say(lang, 'session.selfHeal.injected.queuedDismissed', { queuedOn });
|
|
952
|
+
const noView = reopenRefusedForNoPresentationSurface(reopened) ? msg('session.selfHeal.noCardView.inParens') : '';
|
|
953
|
+
return say(lang, 'session.selfHeal.injected.queuedCannotShow', { queuedOn, noView });
|
|
926
954
|
}
|
|
927
955
|
if (outcome.kind === 'running-steered' && outcome.delivery === 'parked_for_wake') {
|
|
928
|
-
return (
|
|
929
|
-
`instead of starting a new reply, and sema did not retry it.`);
|
|
956
|
+
return say(lang, 'session.selfHeal.injected.parkedForWake', { lead, id });
|
|
930
957
|
}
|
|
931
958
|
if (outcome.kind === 'running-steered' && outcome.delivery !== 'applied') {
|
|
932
|
-
const unknown =
|
|
933
|
-
`so sema cannot tell whether that reply will pick it up`;
|
|
959
|
+
const unknown = msg('session.selfHeal.injected.unknownDelivery', { lead, id });
|
|
934
960
|
return following
|
|
935
|
-
?
|
|
936
|
-
|
|
937
|
-
: `${unknown} — watch that reply before deciding whether anything needs to be sent again.`;
|
|
961
|
+
? say(lang, 'session.selfHeal.injected.unknownDeliveryFollowing', { unknown })
|
|
962
|
+
: say(lang, 'session.selfHeal.injected.unknownDeliveryWatch', { unknown });
|
|
938
963
|
}
|
|
939
964
|
switch (selfHealSubmissionDisposition(outcome)) {
|
|
940
965
|
case 'held-for-decision':
|
|
941
|
-
return (
|
|
942
|
-
`sema kept the message queued and will send it after you answer the open card.`);
|
|
966
|
+
return say(lang, 'session.selfHeal.injected.heldForDecision', { lead, id });
|
|
943
967
|
case 'resending':
|
|
944
968
|
return 'releaseConfirmedByEngine' in outcome && outcome.releaseConfirmedByEngine === true
|
|
945
|
-
?
|
|
946
|
-
|
|
947
|
-
: `${lead} was held back because this session was busy with an earlier reply${id}; that reply is now reported ` +
|
|
948
|
-
`as finished, so sema is sending the message now — nothing for you to do (if the session has not quite ` +
|
|
949
|
-
`freed up yet, it may be held back once more).`;
|
|
969
|
+
? say(lang, 'session.selfHeal.injected.resendingConfirmed', { lead, id })
|
|
970
|
+
: say(lang, 'session.selfHeal.injected.resendingInferred', { lead, id });
|
|
950
971
|
case 'handed-off':
|
|
951
972
|
return following
|
|
952
|
-
?
|
|
953
|
-
|
|
954
|
-
: `${lead} was passed to the reply already in progress${id} instead of starting a new one — ` +
|
|
955
|
-
`watch that reply for what it does with it.`;
|
|
973
|
+
? say(lang, 'session.selfHeal.injected.handedOffFollowing', { lead, id })
|
|
974
|
+
: say(lang, 'session.selfHeal.injected.handedOffWatch', { lead, id });
|
|
956
975
|
case 'not-delivered': {
|
|
957
976
|
const noView = (outcome.kind === 'ask-reopen-failed' || outcome.kind === 'plan-review-reopen-failed') && outcome.noPresentationSurface === true
|
|
958
|
-
?
|
|
977
|
+
? msg('session.selfHeal.noCardView.inParens')
|
|
959
978
|
: '';
|
|
960
|
-
return (
|
|
961
|
-
`you could answer to free it${noView}. sema did not retry, so the model has not seen it.`);
|
|
979
|
+
return say(lang, 'session.selfHeal.injected.notDelivered', { lead, id, noView });
|
|
962
980
|
}
|
|
963
981
|
}
|
|
964
982
|
}
|
|
965
|
-
function decisionInFlightRow(parkedOn) {
|
|
966
|
-
return (
|
|
967
|
-
|
|
968
|
-
|
|
983
|
+
function decisionInFlightRow(parkedOn, taskId, lang) {
|
|
984
|
+
return say(lang, 'session.selfHeal.decisionInFlight', {
|
|
985
|
+
parkedOn: msg(parkedOn === 'ask' ? 'session.selfHeal.parkedOn.ask' : 'session.selfHeal.parkedOn.plan', { taskId }),
|
|
986
|
+
});
|
|
969
987
|
}
|
|
970
988
|
function keepSessionWayOutOf(copy) {
|
|
971
989
|
if (typeof copy?.keepSessionWayOut !== 'function')
|
|
@@ -979,287 +997,185 @@ function keepSessionWayOutOf(copy) {
|
|
|
979
997
|
return null;
|
|
980
998
|
}
|
|
981
999
|
}
|
|
982
|
-
function activeRunSelfHealBaseRow(outcome, wayOut, following = false, keepSessionWayOut = null, engineDecide = true) {
|
|
1000
|
+
function activeRunSelfHealBaseRow(outcome, wayOut, following = false, keepSessionWayOut = null, engineDecide = true, lang, copy) {
|
|
983
1001
|
switch (outcome.kind) {
|
|
984
1002
|
case 'decision-pending':
|
|
985
|
-
return (
|
|
986
|
-
`is waiting on a decision you have not made yet, and there is a decision card open for it. ` +
|
|
987
|
-
`sema did NOT cancel it — answering that card is what releases the session, and cancelling ` +
|
|
988
|
-
`would decide it for you. Your message was NOT sent; answer the open card and send it again.`);
|
|
1003
|
+
return say(lang, 'session.selfHeal.row.decisionPending', { handle: outcome.taskId ? msg('session.selfHeal.handle.run', { taskId: outcome.taskId }) : '' });
|
|
989
1004
|
case 'ask-reopened':
|
|
990
|
-
if (outcome.firstSight)
|
|
991
|
-
return (
|
|
992
|
-
|
|
993
|
-
`message again. (sema did NOT cancel the run: cancelling would have decided it for you.)`);
|
|
994
|
-
}
|
|
995
|
-
return (`The previous turn is parked waiting for your decision (run ${outcome.taskId}), which is why ` +
|
|
996
|
-
`nothing new could start — that card was closed without being answered, so sema reopened it. ` +
|
|
997
|
-
`Answer it and send your message again. (sema did NOT cancel the run: cancelling would have ` +
|
|
998
|
-
`decided it for you.)`);
|
|
1005
|
+
if (outcome.firstSight)
|
|
1006
|
+
return say(lang, 'session.selfHeal.row.askReopened.firstSight', { taskId: outcome.taskId });
|
|
1007
|
+
return say(lang, 'session.selfHeal.row.askReopened.reseen', { taskId: outcome.taskId });
|
|
999
1008
|
case 'plan-review-reopened':
|
|
1000
|
-
if (outcome.firstSight)
|
|
1001
|
-
return (
|
|
1002
|
-
|
|
1003
|
-
`your message again. (sema did NOT cancel the run: cancelling would have thrown the plan away ` +
|
|
1004
|
-
`on your behalf.)`);
|
|
1005
|
-
}
|
|
1006
|
-
return (`The previous turn is parked waiting for you to review its plan (run ${outcome.taskId}), which is ` +
|
|
1007
|
-
`why nothing new could start — that approval card was closed without being answered, so sema ` +
|
|
1008
|
-
`reopened it. Answer it and send your message again. (sema did NOT cancel the run: cancelling ` +
|
|
1009
|
-
`would have thrown the plan away on your behalf.)`);
|
|
1009
|
+
if (outcome.firstSight)
|
|
1010
|
+
return say(lang, 'session.selfHeal.row.planReviewReopened.firstSight', { taskId: outcome.taskId });
|
|
1011
|
+
return say(lang, 'session.selfHeal.row.planReviewReopened.reseen', { taskId: outcome.taskId });
|
|
1010
1012
|
case 'ask-decided-without-card':
|
|
1011
|
-
if (outcome.releaseConfirmedByEngine === true)
|
|
1012
|
-
return (
|
|
1013
|
-
|
|
1014
|
-
`sema is re-sending your message.`);
|
|
1015
|
-
}
|
|
1016
|
-
return (`The previous turn was parked on an approval that your permission rules decided on their own (no card was ` +
|
|
1017
|
-
`needed); run ${outcome.taskId} resumed and has since finished — sema is re-sending your message; if that ` +
|
|
1018
|
-
`run has not fully let go of the session yet, you may have to send it once more.`);
|
|
1013
|
+
if (outcome.releaseConfirmedByEngine === true)
|
|
1014
|
+
return say(lang, 'session.selfHeal.row.askDecided.confirmed', { taskId: outcome.taskId });
|
|
1015
|
+
return say(lang, 'session.selfHeal.row.askDecided.inferred', { taskId: outcome.taskId });
|
|
1019
1016
|
case 'ask-decided-release-unknown':
|
|
1020
|
-
return (
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1017
|
+
return say(lang, 'session.selfHeal.row.askDecided.releaseUnknown', {
|
|
1018
|
+
taskId: outcome.taskId,
|
|
1019
|
+
status: outcome.lastStatus ? msg('session.selfHeal.lastEngineStatus', { status: outcome.lastStatus }) : '',
|
|
1020
|
+
});
|
|
1024
1021
|
case 'ask-reopen-failed': {
|
|
1025
1022
|
if (outcome.decisionInFlight === true)
|
|
1026
|
-
return decisionInFlightRow(
|
|
1027
|
-
const viaEngine = engineDecide && outcome.decidePath
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
`not reopen that card here${noView}. It did NOT cancel the run — that would have decided it for you. ` +
|
|
1033
|
-
(keepSessionWayOut !== null
|
|
1034
|
-
? `Your message was NOT sent. To keep this conversation, ${keepSessionWayOut}: the card comes back when the session resumes, if it is still waiting. Or ${wayOut} if you no longer want it.${viaEngine}`
|
|
1035
|
-
: `Your message was NOT sent; ${wayOut} if you no longer want it.${viaEngine}`));
|
|
1023
|
+
return decisionInFlightRow('ask', outcome.taskId, lang);
|
|
1024
|
+
const viaEngine = engineDecide && outcome.decidePath ? msg('session.selfHeal.viaEngine', { decidePath: outcome.decidePath }) : '';
|
|
1025
|
+
const noView = outcome.noPresentationSurface === true ? msg('session.selfHeal.noCardView.afterColon') : '';
|
|
1026
|
+
return keepSessionWayOut !== null
|
|
1027
|
+
? say(lang, 'session.selfHeal.row.askReopenFailed.withKeep', { taskId: outcome.taskId, noView, keep: keepSessionWayOut, wayOut, viaEngine })
|
|
1028
|
+
: say(lang, 'session.selfHeal.row.askReopenFailed.noKeep', { taskId: outcome.taskId, noView, wayOut, viaEngine });
|
|
1036
1029
|
}
|
|
1037
1030
|
case 'plan-review-reopen-failed': {
|
|
1038
1031
|
if (outcome.decisionInFlight === true)
|
|
1039
|
-
return decisionInFlightRow(
|
|
1032
|
+
return decisionInFlightRow('plan', outcome.taskId, lang);
|
|
1040
1033
|
if (outcome.dismissedByUser === true) {
|
|
1041
|
-
return (
|
|
1042
|
-
`${USER_CLOSED_CARD_NOT_PUT_BACK}. It did NOT cancel the run — that would have discarded the plan for you. ` +
|
|
1043
|
-
`Your message was NOT sent; send it again to bring the card back.`);
|
|
1034
|
+
return say(lang, 'session.selfHeal.row.planReopenFailed.dismissed', { taskId: outcome.taskId, closed: msg('session.selfHeal.userClosedCardNotPutBack') });
|
|
1044
1035
|
}
|
|
1045
|
-
const viaEngine = engineDecide && outcome.decidePath
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
`reopen that approval card${noView}. It did NOT cancel the run — that would have discarded the plan for ` +
|
|
1051
|
-
(keepSessionWayOut !== null
|
|
1052
|
-
? `you. Your message was NOT sent. To keep this conversation, ${keepSessionWayOut}: the card comes back when the session resumes, if it is still waiting. Or ${wayOut} if you no longer want that plan.${viaEngine}`
|
|
1053
|
-
: `you. Your message was NOT sent; ${wayOut} if you no longer want that plan.${viaEngine}`));
|
|
1036
|
+
const viaEngine = engineDecide && outcome.decidePath ? msg('session.selfHeal.viaEngine', { decidePath: outcome.decidePath }) : '';
|
|
1037
|
+
const noView = outcome.noPresentationSurface === true ? msg('session.selfHeal.noCardView.afterColon') : '';
|
|
1038
|
+
return keepSessionWayOut !== null
|
|
1039
|
+
? say(lang, 'session.selfHeal.row.planReopenFailed.withKeep', { taskId: outcome.taskId, noView, keep: keepSessionWayOut, wayOut, viaEngine })
|
|
1040
|
+
: say(lang, 'session.selfHeal.row.planReopenFailed.noKeep', { taskId: outcome.taskId, noView, wayOut, viaEngine });
|
|
1054
1041
|
}
|
|
1055
1042
|
case 'running-steered': {
|
|
1056
|
-
const
|
|
1057
|
-
const textOnly =
|
|
1043
|
+
const taskId = outcome.taskId;
|
|
1044
|
+
const textOnly = msg('session.selfHeal.row.steered.textOnly');
|
|
1058
1045
|
if (outcome.delivery === 'applied') {
|
|
1059
|
-
return (
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
(following
|
|
1063
|
-
|
|
1064
|
-
: `watch that run for what it does with it.`));
|
|
1046
|
+
return say(lang, 'session.selfHeal.row.steered.applied', {
|
|
1047
|
+
taskId,
|
|
1048
|
+
textOnly,
|
|
1049
|
+
tail: msg(following ? 'session.selfHeal.row.steered.tail.following' : 'session.selfHeal.row.steered.tail.watch'),
|
|
1050
|
+
});
|
|
1065
1051
|
}
|
|
1066
1052
|
if (outcome.delivery === 'queued') {
|
|
1067
|
-
const parked = outcome.status ?
|
|
1053
|
+
const parked = outcome.status ? msg('session.selfHeal.row.steered.parked.withStatus', { status: outcome.status }) : msg('session.selfHeal.row.steered.parked.plain');
|
|
1068
1054
|
const reopened = reopenedOfOutcome(outcome);
|
|
1069
1055
|
const next = reopened !== null && reopenDelivered(reopened)
|
|
1070
|
-
?
|
|
1056
|
+
? msg('session.selfHeal.row.steered.next.shown')
|
|
1071
1057
|
: reopenRefusedForDecisionInFlight(reopened)
|
|
1072
|
-
?
|
|
1073
|
-
`that run moves on once the engine applies it.`
|
|
1058
|
+
? msg('session.selfHeal.row.steered.next.inFlight')
|
|
1074
1059
|
: reopenRefusedForUserDismissal(reopened)
|
|
1075
|
-
?
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
return (`${handle} is not actually working right now: the engine reports it ${parked} on a decision it needs ` +
|
|
1082
|
-
`from you, so it queued your message on that park instead of running it. ${next} ${textOnly} ` +
|
|
1083
|
-
`Nothing was cancelled, and your message did NOT start a new turn.`);
|
|
1060
|
+
? msg('session.selfHeal.row.steered.next.dismissed')
|
|
1061
|
+
: msg('session.selfHeal.row.steered.next.cannotShow', {
|
|
1062
|
+
noView: reopenRefusedForNoPresentationSurface(reopened) ? msg('session.selfHeal.noCardView.inParens') : '',
|
|
1063
|
+
wayOut,
|
|
1064
|
+
});
|
|
1065
|
+
return say(lang, 'session.selfHeal.row.steered.queued', { taskId, parked, next, textOnly });
|
|
1084
1066
|
}
|
|
1085
1067
|
if (outcome.delivery === 'parked_for_wake') {
|
|
1086
|
-
return (
|
|
1087
|
-
`running it — a parked message is delivered only if this session is woken on the engine ` +
|
|
1088
|
-
`(POST /v1/sessions/:id/wake), which sema does not do here. That run is no longer holding this ` +
|
|
1089
|
-
`session: send your message again to run it as a new turn — but note that the parked copy is NOT ` +
|
|
1090
|
-
`discarded, so if anything ever wakes this session on the engine that instruction would run a ` +
|
|
1091
|
-
`second time. ${textOnly} Nothing was cancelled.`);
|
|
1068
|
+
return say(lang, 'session.selfHeal.row.steered.parkedForWake', { taskId, textOnly, wakeOn: wakeSessionClause(copy, lang) });
|
|
1092
1069
|
}
|
|
1093
|
-
return (
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1070
|
+
return say(lang, 'session.selfHeal.row.steered.unknown', {
|
|
1071
|
+
taskId,
|
|
1072
|
+
reported: outcome.status ? msg('session.selfHeal.row.steered.reported', { status: outcome.status }) : '',
|
|
1073
|
+
textOnly,
|
|
1074
|
+
tail: msg(following ? 'session.selfHeal.row.steered.unknownTail.following' : 'session.selfHeal.row.steered.unknownTail.watch'),
|
|
1075
|
+
});
|
|
1099
1076
|
}
|
|
1100
1077
|
case 'running-steer-failed':
|
|
1101
|
-
if (outcome.delivery === 'rejected') {
|
|
1102
|
-
return (
|
|
1103
|
-
`sema did NOT retry it (a steer is not safe to send twice) and it did NOT cancel that run. ` +
|
|
1104
|
-
`Your message was NOT sent; send it again if you still want it.`);
|
|
1078
|
+
if (outcome.delivery === 'rejected' && outcome.errorCode === STEER_NOT_RUNNING_CODE && outcome.runStatus !== undefined && isSdkRunTerminal(outcome.runStatus)) {
|
|
1079
|
+
return say(lang, 'session.selfHeal.row.steerFailed.runEnded', { taskId: outcome.taskId, status: outcome.runStatus });
|
|
1105
1080
|
}
|
|
1106
|
-
return
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
`before sending it again.`);
|
|
1081
|
+
return outcome.delivery === 'rejected'
|
|
1082
|
+
? say(lang, 'session.selfHeal.row.steerFailed.rejected', { taskId: outcome.taskId, detail: outcome.detail })
|
|
1083
|
+
: say(lang, 'session.selfHeal.row.steerFailed.unknown', { taskId: outcome.taskId, detail: outcome.detail });
|
|
1110
1084
|
case 'running-attach':
|
|
1111
|
-
return (
|
|
1085
|
+
return say(lang, 'session.selfHeal.row.attach', { disclosure: resumeAttachReplayDisclosure(outcome.taskId) });
|
|
1112
1086
|
case 'running-cancelled':
|
|
1113
1087
|
return outcome.releaseConfirmedByEngine === true
|
|
1114
|
-
?
|
|
1115
|
-
|
|
1116
|
-
: `You chose to cancel run ${outcome.taskId}. The engine now reports that run as finished, so sema is ` +
|
|
1117
|
-
`sending your message now; if that run has not fully let go of the session yet, you may have to send ` +
|
|
1118
|
-
`it once more.`;
|
|
1088
|
+
? say(lang, 'session.selfHeal.row.cancelled.confirmed', { taskId: outcome.taskId })
|
|
1089
|
+
: say(lang, 'session.selfHeal.row.cancelled.reported', { taskId: outcome.taskId });
|
|
1119
1090
|
case 'running-cancel-timeout': {
|
|
1120
1091
|
const waited = `${String(Math.max(1, Math.round(outcome.waitedMs / 1000)))}s`;
|
|
1121
|
-
if (outcome.aborted)
|
|
1122
|
-
return (
|
|
1123
|
-
`confirming (${waited} in). Cancelling is asynchronous, so that run may still be winding down and ` +
|
|
1124
|
-
`may still hold this session. Your message was NOT sent; send it again in a moment, or ${wayOut}.`);
|
|
1125
|
-
}
|
|
1092
|
+
if (outcome.aborted)
|
|
1093
|
+
return say(lang, 'session.selfHeal.row.cancelTimeout.aborted', { taskId: outcome.taskId, waited, wayOut });
|
|
1126
1094
|
if (!outcome.confirmedHeld) {
|
|
1127
|
-
return (
|
|
1128
|
-
`within ${waited}, so it cannot confirm whether the session was released. Your message was NOT sent; ` +
|
|
1129
|
-
`send it again in a moment (if that run really is gone it will just run), or ${wayOut}.`);
|
|
1095
|
+
return say(lang, 'session.selfHeal.row.cancelTimeout.unread', { taskId: outcome.taskId, waited, wayOut });
|
|
1130
1096
|
}
|
|
1131
|
-
return (
|
|
1132
|
-
`${waited} later — cancelling is asynchronous and it may still be winding down. Your message was NOT ` +
|
|
1133
|
-
`sent; send it again in a moment, or ${wayOut}.`);
|
|
1097
|
+
return say(lang, 'session.selfHeal.row.cancelTimeout.held', { taskId: outcome.taskId, waited, wayOut });
|
|
1134
1098
|
}
|
|
1135
1099
|
case 'running-cancel-failed':
|
|
1136
1100
|
if (outcome.delivery === 'unknown') {
|
|
1137
|
-
return (
|
|
1138
|
-
`(${outcome.detail}), and it could not read that run back as released either. That run may or may ` +
|
|
1139
|
-
`not still be holding this session. Your message was NOT sent; send it again in a moment, or ${wayOut}.`);
|
|
1101
|
+
return say(lang, 'session.selfHeal.row.cancelFailed.unknown', { taskId: outcome.taskId, detail: outcome.detail, wayOut });
|
|
1140
1102
|
}
|
|
1141
|
-
return (
|
|
1142
|
-
`nothing was cancelled and sema cannot tell whether that run is still holding this session. Your message ` +
|
|
1143
|
-
`was NOT sent; send it again to find out, or ${wayOut}.`);
|
|
1103
|
+
return say(lang, 'session.selfHeal.row.cancelFailed.rejected', { taskId: outcome.taskId, detail: outcome.detail, wayOut });
|
|
1144
1104
|
case 'ask-run-not-found':
|
|
1145
|
-
return (
|
|
1146
|
-
`was waiting on is no longer on the engine, and asking the engine about that run directly comes back ` +
|
|
1147
|
-
`not-found — a lookup that cannot separate a run that is really gone from one this session is simply ` +
|
|
1148
|
-
`not allowed to read. Either way sema has nothing it can act on here, so it did NOT cancel anything. ` +
|
|
1149
|
-
`Your message was NOT sent; send it again (if the session really is free it will just run), or ${wayOut}.`);
|
|
1105
|
+
return say(lang, 'session.selfHeal.row.askRunNotFound', { taskId: outcome.taskId, wayOut });
|
|
1150
1106
|
case 'ask-run-settled':
|
|
1151
|
-
return (
|
|
1152
|
-
`(status ${outcome.status}) — there is nothing left to answer and nothing to cancel, so sema did NOT cancel anything. ` +
|
|
1153
|
-
`Your message was NOT sent; send it again (once that run has let go of the session it will just run), or ${wayOut}.`);
|
|
1107
|
+
return say(lang, 'session.selfHeal.row.askRunSettled', { taskId: outcome.taskId, status: outcome.status, wayOut });
|
|
1154
1108
|
case 'stale-park-cancelled':
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
`holding this session, so sema is sending your message again now.`);
|
|
1159
|
-
}
|
|
1160
|
-
return (`Run ${outcome.taskId} was parked on an approval that no longer exists on the engine, so there was ` +
|
|
1161
|
-
`nothing left for you to answer. You chose to cancel that run: the engine now reports it as finished, ` +
|
|
1162
|
-
`so it will not resume — whatever that turn had left to do is not coming back. sema is sending your ` +
|
|
1163
|
-
`message again now; if that run has not fully let go of the session yet, you may have to send it once ` +
|
|
1164
|
-
`more.`);
|
|
1109
|
+
return outcome.releaseConfirmedByEngine === true
|
|
1110
|
+
? say(lang, 'session.selfHeal.row.stale.cancelled.confirmed', { taskId: outcome.taskId })
|
|
1111
|
+
: say(lang, 'session.selfHeal.row.stale.cancelled.reported', { taskId: outcome.taskId });
|
|
1165
1112
|
case 'stale-park-cancel-timeout': {
|
|
1166
1113
|
const waited = `${String(Math.max(1, Math.round(outcome.waitedMs / 1000)))}s`;
|
|
1167
|
-
if (outcome.aborted)
|
|
1168
|
-
return (
|
|
1169
|
-
`exists there) and you interrupted while it was still confirming (${waited} in). Cancelling is ` +
|
|
1170
|
-
`asynchronous, so that run may still be winding down and may still hold this session. Your message ` +
|
|
1171
|
-
`was NOT sent; send it again in a moment, or ${wayOut}.`);
|
|
1172
|
-
}
|
|
1114
|
+
if (outcome.aborted)
|
|
1115
|
+
return say(lang, 'session.selfHeal.row.stale.cancelTimeout.aborted', { taskId: outcome.taskId, waited, wayOut });
|
|
1173
1116
|
if (!outcome.confirmedHeld) {
|
|
1174
|
-
return (
|
|
1175
|
-
`there) but could not read that run's state back within ${waited}, so it cannot confirm whether the ` +
|
|
1176
|
-
`session was released. Your message was NOT sent; send it again in a moment (if that run really is ` +
|
|
1177
|
-
`gone it will just run), or ${wayOut}.`);
|
|
1117
|
+
return say(lang, 'session.selfHeal.row.stale.cancelTimeout.unread', { taskId: outcome.taskId, waited, wayOut });
|
|
1178
1118
|
}
|
|
1179
|
-
return (
|
|
1180
|
-
`there), but that run still held this session ${waited} later — cancelling is asynchronous and it may ` +
|
|
1181
|
-
`still be winding down. Your message was NOT sent; send it again in a moment, or ${wayOut}.`);
|
|
1119
|
+
return say(lang, 'session.selfHeal.row.stale.cancelTimeout.held', { taskId: outcome.taskId, waited, wayOut });
|
|
1182
1120
|
}
|
|
1183
1121
|
case 'stale-park-cancel-failed':
|
|
1184
1122
|
if (outcome.delivery === 'unknown') {
|
|
1185
|
-
return (
|
|
1186
|
-
`engine) but could not confirm what happened to it (${outcome.detail}), and it could not read that ` +
|
|
1187
|
-
`run back as released either. That run may or may not still be holding this session. Your message ` +
|
|
1188
|
-
`was NOT sent; send it again in a moment, or ${wayOut}.`);
|
|
1123
|
+
return say(lang, 'session.selfHeal.row.stale.cancelFailed.unknown', { taskId: outcome.taskId, detail: outcome.detail, wayOut });
|
|
1189
1124
|
}
|
|
1190
|
-
return (
|
|
1191
|
-
`so nothing was cancelled and sema cannot tell whether that run is still holding this session. Your ` +
|
|
1192
|
-
`message was NOT sent; send it again to find out, or ${wayOut}.`);
|
|
1125
|
+
return say(lang, 'session.selfHeal.row.cancelFailed.rejected', { taskId: outcome.taskId, detail: outcome.detail, wayOut });
|
|
1193
1126
|
case 'stale-park-wait':
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
`is not asking again. Your message was NOT sent; cancel that run on the engine ` +
|
|
1198
|
-
`(POST /v1/runs/${outcome.taskId}/cancel — that ends it for good), or ${wayOut}.`);
|
|
1199
|
-
}
|
|
1200
|
-
return (`Run ${outcome.taskId} is still parked (status ${outcome.status}) on an approval that no longer exists ` +
|
|
1201
|
-
`on the engine, so there is no card left to answer and that run will not settle on its own. sema did ` +
|
|
1202
|
-
`NOT cancel it — you chose to leave it alone. Your message was NOT sent; cancel that run on the engine ` +
|
|
1203
|
-
`(POST /v1/runs/${outcome.taskId}/cancel — that ends it for good), or ${wayOut}.`);
|
|
1127
|
+
return outcome.alreadyOffered === true
|
|
1128
|
+
? say(lang, 'session.selfHeal.row.stale.wait.offered', { taskId: outcome.taskId, status: outcome.status, wayOut, endRun: endRunClause(copy, outcome.taskId, lang) })
|
|
1129
|
+
: say(lang, 'session.selfHeal.row.stale.wait.first', { taskId: outcome.taskId, status: outcome.status, wayOut, endRun: endRunClause(copy, outcome.taskId, lang) });
|
|
1204
1130
|
case 'running-not-found':
|
|
1205
|
-
return (
|
|
1206
|
-
`longer recognizes that run when asked directly — that claim looks stale (the run most likely no ` +
|
|
1207
|
-
`longer exists). sema did not offer to steer or cancel it: there is nothing left to act on. ` +
|
|
1208
|
-
`Your message was NOT sent; send it again (if the session really is free it will just run), or ${wayOut}.`);
|
|
1131
|
+
return say(lang, 'session.selfHeal.row.runNotFound', { taskId: outcome.taskId, wayOut });
|
|
1209
1132
|
case 'running-settled':
|
|
1210
|
-
return (
|
|
1211
|
-
`reported it as holding this session — that claim looks stale or mid-release. sema did not offer ` +
|
|
1212
|
-
`to steer or cancel it: the run is over. Your message was NOT sent; send it again (once the claim ` +
|
|
1213
|
-
`clears it will just run), or ${wayOut}.`);
|
|
1133
|
+
return say(lang, 'session.selfHeal.row.runSettled', { taskId: outcome.taskId, status: outcome.status, wayOut });
|
|
1214
1134
|
case 'not-parked':
|
|
1215
1135
|
if (outcome.alreadyOffered === true) {
|
|
1216
|
-
return (
|
|
1217
|
-
`asked what to do with it and you chose to leave it alone, so it is not asking again. ` +
|
|
1218
|
-
`Your message was NOT sent; wait for that run, cancel it on the engine ` +
|
|
1219
|
-
`(POST /v1/runs/${outcome.taskId}/cancel), or ${wayOut}.`);
|
|
1136
|
+
return say(lang, 'session.selfHeal.row.notParked.offered', { taskId: outcome.taskId, status: outcome.status, wayOut, endRun: endRunClause(copy, outcome.taskId, lang) });
|
|
1220
1137
|
}
|
|
1221
|
-
const parkedOn = outcome.pendingGateKind !== undefined
|
|
1138
|
+
const parkedOn = outcome.pendingGateKind !== undefined
|
|
1139
|
+
? gateKindPhrase(outcome.pendingGateKind, lang)
|
|
1140
|
+
: isSdkRunParked(outcome.status)
|
|
1141
|
+
? gateKindPhrase(null, lang)
|
|
1142
|
+
: undefined;
|
|
1222
1143
|
if (parkedOn !== undefined) {
|
|
1223
|
-
return (
|
|
1224
|
-
`waiting on ${parkedOn} — it will not finish on its own. sema did ` +
|
|
1225
|
-
`NOT cancel it, because cancelling would decide that item for you. Your message was NOT sent; ` +
|
|
1226
|
-
`${wayOut} if you no longer want it.`);
|
|
1144
|
+
return say(lang, 'session.selfHeal.row.notParked.parkedOn', { taskId: outcome.taskId, status: outcome.status, parkedOn, wayOut });
|
|
1227
1145
|
}
|
|
1228
|
-
return (
|
|
1229
|
-
`most likely a turn you sent to the background. sema did NOT cancel it, because that would ` +
|
|
1230
|
-
`throw away work you asked for. Wait for it to finish, or ${wayOut}.`);
|
|
1146
|
+
return say(lang, 'session.selfHeal.row.notParked.inFlight', { taskId: outcome.taskId, status: outcome.status, wayOut });
|
|
1231
1147
|
case 'state-unknown':
|
|
1232
|
-
return (
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1148
|
+
return say(lang, 'session.selfHeal.row.stateUnknown', {
|
|
1149
|
+
handle: outcome.taskId ? msg('session.selfHeal.handle.run', { taskId: outcome.taskId }) : '',
|
|
1150
|
+
detail: outcome.detail,
|
|
1151
|
+
wayOut,
|
|
1152
|
+
});
|
|
1236
1153
|
}
|
|
1237
1154
|
}
|
|
1238
|
-
export function activeRunBusyHeadlessRow(signal, copy) {
|
|
1155
|
+
export function activeRunBusyHeadlessRow(signal, copy, lang) {
|
|
1239
1156
|
const override = copy?.headlessRowFor?.(signal);
|
|
1240
1157
|
if (typeof override === 'string')
|
|
1241
1158
|
return override;
|
|
1242
1159
|
const activeTaskId = signal.activeTaskId;
|
|
1243
|
-
const handle = activeTaskId ?
|
|
1244
|
-
const
|
|
1160
|
+
const handle = activeTaskId ? msg('session.selfHeal.handle.run', { taskId: activeTaskId }) : '';
|
|
1161
|
+
const endRun = endRunClause(copy, activeTaskId, lang);
|
|
1245
1162
|
const status = signal.activeTaskStatus;
|
|
1246
1163
|
const decidePath = signal.pendingGate?.decidePath ?? null;
|
|
1247
|
-
const
|
|
1164
|
+
const hostFresh = copy?.freshSession ?? undefined;
|
|
1165
|
+
const freshSession = hostFresh ?? say(lang, 'session.selfHeal.freshSession.default');
|
|
1248
1166
|
if (decidePath) {
|
|
1249
|
-
return (
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
const startOver = `${
|
|
1262
|
-
return (
|
|
1263
|
-
`NOT sent. Nothing here clears on its own. ${startOver}, or ` +
|
|
1264
|
-
`release the run on the engine: ${cancelPath}`);
|
|
1167
|
+
return say(lang, 'session.selfHeal.headless.decide', {
|
|
1168
|
+
handle,
|
|
1169
|
+
status: status ? msg('session.selfHeal.headless.status', { status }) : '',
|
|
1170
|
+
gate: gateKindPhrase(signal.pendingGate?.kind, lang),
|
|
1171
|
+
decidePath,
|
|
1172
|
+
endRun,
|
|
1173
|
+
freshSession,
|
|
1174
|
+
governance: governanceOriginClause(signal, lang),
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
if (status)
|
|
1178
|
+
return say(lang, 'session.selfHeal.headless.statusOnly', { handle, status, endRun, freshSession });
|
|
1179
|
+
const startOver = hostFresh !== undefined ? `${hostFresh.charAt(0).toUpperCase()}${hostFresh.slice(1)}` : say(lang, 'session.selfHeal.freshSession.defaultCapitalized');
|
|
1180
|
+
return say(lang, 'session.selfHeal.headless.neverReleased', { handle, startOver, endRun });
|
|
1265
1181
|
}
|