@sema-agent/client-core 0.110.0 → 0.111.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 +169 -0
- package/README.md +50 -18
- package/dist/abortableSleep.d.ts +7 -0
- package/dist/abortableSleep.js +37 -0
- package/dist/adapt/arms.js +25 -4
- package/dist/adapt/toolCards.d.ts +3 -1
- package/dist/adapt/toolCards.js +4 -2
- package/dist/adapter/activeRunSelfHeal.d.ts +39 -0
- package/dist/adapter/activeRunSelfHeal.js +171 -3
- package/dist/adapter/downstream/eventToSdkMessage.js +10 -10
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +2 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +11 -0
- package/dist/adapter/runStream.d.ts +5 -0
- package/dist/adapter/runStream.js +15 -3
- package/dist/attachmentRoute.d.ts +20 -0
- package/dist/attachmentRoute.js +39 -0
- package/dist/attachmentsWireCaps.js +1 -1
- package/dist/builtinOutputStyles.d.ts +12 -0
- package/dist/builtinOutputStyles.js +147 -0
- package/dist/compactionStatus.d.ts +9 -0
- package/dist/compactionStatus.js +29 -5
- package/dist/controlRouter.js +2 -1
- package/dist/coreValuePorts.d.ts +39 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +6 -0
- package/dist/engineHealthFacts.d.ts +11 -0
- package/dist/engineHealthFacts.js +21 -0
- package/dist/engineHealthProbeVerdict.d.ts +23 -0
- package/dist/engineHealthProbeVerdict.js +115 -0
- package/dist/engineNoticeCodes.js +5 -7
- package/dist/engineRepoint.d.ts +12 -5
- package/dist/engineRepoint.js +44 -19
- package/dist/engineRowRef.d.ts +3 -0
- package/dist/engineRowRef.js +11 -1
- package/dist/engineSwapCrossing.d.ts +57 -0
- package/dist/engineSwapCrossing.js +297 -0
- package/dist/engineUnavailable.d.ts +44 -0
- package/dist/engineUnavailable.js +492 -0
- package/dist/eventLeg.js +3 -3
- package/dist/generated/sdkFactTables.d.ts +1 -1
- package/dist/generated/sdkFactTables.js +1 -0
- package/dist/generated/settingsSchemaTables.d.ts +4 -0
- package/dist/generated/settingsSchemaTables.js +1 -0
- package/dist/hitl/approvalDelivery.d.ts +1 -0
- package/dist/hitl/approvalDelivery.js +1 -1
- package/dist/hitl/approvalResolution.d.ts +1 -1
- package/dist/hitl/approvalResolution.js +2 -1
- package/dist/hitl/askGateWire.js +5 -6
- package/dist/hitl/decisionRefusal.d.ts +2 -0
- package/dist/hitl/decisionRefusal.js +7 -8
- package/dist/hitl/decisionRefusalCarrier.d.ts +3 -0
- package/dist/hitl/decisionRefusalCarrier.js +348 -0
- package/dist/hitl/decisionSend.d.ts +7 -0
- package/dist/hitl/decisionSend.js +34 -12
- package/dist/hitl/editedApprovalAcceptance.js +1 -1
- package/dist/hitl/elicitationRefusal.d.ts +4 -0
- package/dist/hitl/elicitationRefusal.js +23 -0
- package/dist/hitl/frameRouter.d.ts +2 -2
- package/dist/hitl/frameRouter.js +8 -15
- package/dist/hitl/gateIdentity.d.ts +5 -0
- package/dist/hitl/gateIdentity.js +23 -0
- package/dist/hitl/hitlBridge.d.ts +6 -0
- package/dist/hitl/hitlBridge.js +10 -4
- package/dist/hitl/hitlHostSurface.d.ts +2 -1
- package/dist/hitl/hitlHostSurface.js +7 -2
- package/dist/hitl/localAllowRedemption.d.ts +67 -0
- package/dist/hitl/localAllowRedemption.js +256 -0
- package/dist/hitl/parkResolver.js +7 -4
- package/dist/hitl/persistedRulesWire.d.ts +16 -0
- package/dist/hitl/persistedRulesWire.js +70 -0
- package/dist/hitl/planReviewWire.d.ts +3 -0
- package/dist/hitl/planReviewWire.js +23 -6
- package/dist/hitl/policyDenyCause.d.ts +1 -1
- package/dist/hitl/policyDenyCause.js +1 -1
- package/dist/hitl/resumeRunningCard.d.ts +1 -0
- package/dist/hitl/resumeRunningCard.js +1 -0
- package/dist/hitl/screenCardCarriers.d.ts +15 -0
- package/dist/hitl/screenCardCarriers.js +41 -0
- package/dist/hitl/screenDecisionCards.d.ts +98 -0
- package/dist/hitl/screenDecisionCards.js +362 -0
- package/dist/hitl/standingRows.d.ts +3 -1
- package/dist/hitl/standingRows.js +18 -0
- package/dist/hitl/toolApprovalWire.d.ts +30 -8
- package/dist/hitl/toolApprovalWire.js +264 -121
- package/dist/hooksWireCaps.js +3 -3
- package/dist/hostSettingNoticeArm.d.ts +3 -0
- package/dist/hostSettingNoticeArm.js +12 -0
- package/dist/hostTurnSettings.d.ts +3 -0
- package/dist/hostTurnSettings.js +38 -5
- package/dist/humanTurnRead.js +11 -1
- package/dist/i18n/messages.en.d.ts +129 -0
- package/dist/i18n/messages.en.js +135 -7
- package/dist/i18n/messages.zh.js +142 -6
- package/dist/i18n/translate.d.ts +3 -0
- package/dist/i18n/translate.js +78 -10
- package/dist/i18n/zh.d.ts +1 -0
- package/dist/i18n/zh.js +1 -0
- package/dist/index.d.ts +43 -17
- package/dist/index.js +30 -12
- package/dist/interactiveHalt.js +2 -1
- package/dist/interactiveInterrupt.js +20 -2
- package/dist/liveModelCatalog.js +2 -2
- package/dist/localEngineSeatReading.d.ts +2 -2
- package/dist/localEngineSeatReading.js +5 -3
- package/dist/localEngineSpawn.d.ts +0 -7
- package/dist/localEngineSpawn.js +0 -92
- package/dist/localEngineStep.d.ts +2 -2
- package/dist/localEngineStep.js +2 -0
- package/dist/mcpReconnect.js +3 -3
- package/dist/mcpWireCaps.js +1 -1
- package/dist/model/engineModelWords.d.ts +3 -0
- package/dist/model/engineModelWords.js +13 -0
- package/dist/model/subagentModelWord.d.ts +21 -2
- package/dist/model/subagentModelWord.js +100 -29
- package/dist/modelCapabilityProbe.js +3 -40
- package/dist/notifications.d.ts +19 -0
- package/dist/notifications.js +114 -12
- package/dist/ownKey.d.ts +6 -0
- package/dist/ownKey.js +31 -0
- package/dist/pendingUserRow.d.ts +4 -0
- package/dist/pendingUserRow.js +16 -0
- package/dist/permissionsDeclaration.d.ts +1 -0
- package/dist/permissionsDeclaration.js +11 -1
- package/dist/planReviewCardFacts.d.ts +3 -0
- package/dist/planReviewCardFacts.js +52 -2
- package/dist/pluginHooksWire.d.ts +9 -1
- package/dist/pluginHooksWire.js +40 -6
- package/dist/printToolResultFrame.js +4 -2
- package/dist/promptBlockedCopy.js +11 -6
- package/dist/promptSuggestionBatch.d.ts +7 -0
- package/dist/promptSuggestionBatch.js +9 -0
- package/dist/promptSuggestionsTail.d.ts +39 -0
- package/dist/promptSuggestionsTail.js +116 -0
- package/dist/request/taskRequest.js +10 -6
- package/dist/requestCoordinate.d.ts +1 -0
- package/dist/requestCoordinate.js +13 -0
- package/dist/rewindArchiveReading.js +4 -4
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +1 -0
- package/dist/runPermissionModeSwitch.js +2 -2
- package/dist/scenarioRefusal.js +11 -13
- package/dist/scenarioSkills.js +11 -6
- package/dist/seam.d.ts +16 -2
- package/dist/seam.js +10 -0
- package/dist/seatContract.d.ts +109 -9
- package/dist/seatContract.js +218 -15
- package/dist/sessionCostReading.d.ts +70 -0
- package/dist/sessionCostReading.js +150 -0
- package/dist/sessionHooksRoster.d.ts +4 -0
- package/dist/sessionHooksRoster.js +158 -0
- package/dist/sessionMemoryStatus.js +2 -2
- package/dist/sessionReadRedaction.d.ts +7 -0
- package/dist/sessionReadRedaction.js +26 -0
- package/dist/sessionSyncFileHistory.js +8 -9
- package/dist/settingsHooksSalvage.js +2 -1
- package/dist/sseIdleTriage.js +2 -1
- package/dist/storeDurabilityWord.d.ts +15 -0
- package/dist/storeDurabilityWord.js +18 -0
- package/dist/storePostureCapability.d.ts +7 -3
- package/dist/storePostureCapability.js +69 -39
- package/dist/subagent/engineSubagentResume.js +2 -2
- package/dist/subagent/engineSubagentTail.js +2 -1
- package/dist/subagentContentStore.d.ts +11 -0
- package/dist/subagentContentStore.js +28 -2
- package/dist/toolResult.d.ts +1 -0
- package/dist/toolResult.js +2 -0
- package/dist/userAttachmentEnvelope.d.ts +2 -1
- package/dist/userAttachmentEnvelope.js +10 -0
- package/dist/wireErrorTriage.js +2 -1
- package/dist/wireFailureShape.d.ts +4 -0
- package/dist/wireFailureShape.js +141 -19
- package/dist/wireRefusalCopy.d.ts +6 -5
- package/dist/wireRefusalCopy.js +49 -92
- package/docs/INTEGRATION-CLIENTS.md +2118 -17
- package/package.json +6 -2
package/dist/notifications.js
CHANGED
|
@@ -5,8 +5,9 @@ import { panelEndFact } from './panelReduce.js';
|
|
|
5
5
|
import { isCoreTaskNotificationTerminal, isCoreTaskNotificationTerminalNotSuccess, isCoreWorkflowRunParkedEnd, isCoreWorkflowRunTerminal } from './terminalStatuses.js';
|
|
6
6
|
import { cycleSeqValue } from './cycleOrder.js';
|
|
7
7
|
import { CORE_ENGINE_AUTHORITY_ENVELOPE_TAGS } from './generated/engineFactTables.js';
|
|
8
|
-
import { guardedRead, ownSnapshot, ownSnapshotRecord, ownSnapshotTyped, readOwnDataValue, workflowCompletionExtrasOf } from './ownKey.js';
|
|
9
|
-
import {
|
|
8
|
+
import { guardedRead, ownSnapshot, ownSnapshotRecord, ownSnapshotTyped, readOwnDataNonEmptyString, readOwnDataValue, resupplyTruncatedFactsOf, resupplyTruncatedOf, workflowCompletionExtrasOf } from './ownKey.js';
|
|
9
|
+
import { msg, renderMessage } from './i18n/translate.js';
|
|
10
|
+
import { displayUntrustedCapped } from './displayUntrusted.js';
|
|
10
11
|
function escapeXml(v) {
|
|
11
12
|
return v.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
12
13
|
}
|
|
@@ -213,6 +214,7 @@ export function normalizeTaskNotification(raw) {
|
|
|
213
214
|
? n.lines.filter((l) => typeof l === 'string')
|
|
214
215
|
: [];
|
|
215
216
|
const recentSteps = deriveNotificationResidualLines(n);
|
|
217
|
+
const failureReason = failureReasonOf(status, n.error);
|
|
216
218
|
return {
|
|
217
219
|
taskId,
|
|
218
220
|
status,
|
|
@@ -230,6 +232,7 @@ export function normalizeTaskNotification(raw) {
|
|
|
230
232
|
? { diagnostics: n.diagnostics }
|
|
231
233
|
: {}),
|
|
232
234
|
...(typeof n.result === 'string' && n.result.length > 0 ? { result: n.result } : {}),
|
|
235
|
+
...(failureReason !== undefined ? { error: failureReason } : {}),
|
|
233
236
|
...(typeof n.stoppedBy === 'string' && n.stoppedBy.length > 0 ? { stoppedBy: n.stoppedBy } : {}),
|
|
234
237
|
...(n.partial === true ? { partial: true } : {}),
|
|
235
238
|
...(typeof n.exitCode === 'number' ? { exitCode: n.exitCode } : {}),
|
|
@@ -422,6 +425,7 @@ export function enqueuePlanReviewOutcome(value, meta) {
|
|
|
422
425
|
queuePortMisses++;
|
|
423
426
|
return false;
|
|
424
427
|
}
|
|
428
|
+
const questionId = meta === undefined ? undefined : guardedRead(() => readOwnDataNonEmptyString(meta, 'questionId'));
|
|
425
429
|
p.enqueueMetaPrompt({
|
|
426
430
|
value,
|
|
427
431
|
mode: 'prompt',
|
|
@@ -436,12 +440,34 @@ export function enqueuePlanReviewOutcome(value, meta) {
|
|
|
436
440
|
decision: meta.decision,
|
|
437
441
|
effect: meta.effect,
|
|
438
442
|
...(meta.effect === 'still_parked' && meta.cause === 'stored_form_unsupported' ? { cause: meta.cause } : {}),
|
|
443
|
+
...(questionId !== undefined ? { questionId } : {}),
|
|
439
444
|
}),
|
|
440
445
|
}
|
|
441
446
|
: {}),
|
|
442
447
|
});
|
|
443
448
|
return true;
|
|
444
449
|
}
|
|
450
|
+
export function resupplyTruncatedSentence(facts, lang) {
|
|
451
|
+
try {
|
|
452
|
+
const f = resupplyTruncatedFactsOf(facts);
|
|
453
|
+
if (f === undefined)
|
|
454
|
+
return undefined;
|
|
455
|
+
const count = f.droppedKeys.length;
|
|
456
|
+
return renderMessage(msg(count === 1 ? 'notice.resupply.truncated.one' : 'notice.resupply.truncated.other', count === 1 ? { bytes: f.bytes } : { bytes: f.bytes, count }), lang);
|
|
457
|
+
}
|
|
458
|
+
catch {
|
|
459
|
+
return undefined;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
export function resupplyTruncatedArmBody(carrier, source, taskId) {
|
|
463
|
+
const facts = resupplyTruncatedOf(carrier);
|
|
464
|
+
if (facts === undefined)
|
|
465
|
+
return undefined;
|
|
466
|
+
const text = resupplyTruncatedSentence(facts);
|
|
467
|
+
if (text === undefined)
|
|
468
|
+
return undefined;
|
|
469
|
+
return { source, taskId, bytes: facts.bytes, droppedKeys: facts.droppedKeys, text };
|
|
470
|
+
}
|
|
445
471
|
export function dropQueuedNotificationsForRun(taskId) {
|
|
446
472
|
const needle = `<${TASK_ID_TAG}>${escapeXml(taskId)}</${TASK_ID_TAG}>`;
|
|
447
473
|
const p = port();
|
|
@@ -494,20 +520,25 @@ export function workflowRunTerminalReadingOf(body) {
|
|
|
494
520
|
if (isCoreWorkflowRunParkedEnd(status, guardedRead(() => readOwnDataValue(snap, 'errorCode'))))
|
|
495
521
|
return Object.freeze({ state: 'awaiting approval' });
|
|
496
522
|
const result = guardedRead(() => readOwnDataValue(snap, 'result'));
|
|
497
|
-
const
|
|
498
|
-
const
|
|
523
|
+
const shownError = failureReasonOf(status, guardedRead(() => readOwnDataValue(snap, 'error')));
|
|
524
|
+
const resultFull = guardedRead(() => readOwnDataValue(snap, 'resultFull'));
|
|
499
525
|
return Object.freeze({
|
|
500
526
|
state: status,
|
|
501
527
|
...(typeof result === 'string' && result.length > 0 ? { result } : {}),
|
|
502
|
-
...(shownError
|
|
528
|
+
...(shownError !== undefined ? { error: shownError } : {}),
|
|
503
529
|
pointer: 'absent',
|
|
530
|
+
...(typeof resultFull === 'string' && resultFull.length > 0 ? { truncated: true } : {}),
|
|
504
531
|
});
|
|
505
532
|
}
|
|
506
533
|
const WORKFLOW_RUN_ERROR_MAX = 200;
|
|
507
534
|
function shownRunError(raw) {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
535
|
+
return displayUntrustedCapped(raw, WORKFLOW_RUN_ERROR_MAX, { foldLines: false, escapeBackslashes: 'auto' });
|
|
536
|
+
}
|
|
537
|
+
function failureReasonOf(status, raw) {
|
|
538
|
+
if (status !== 'failed' || typeof raw !== 'string' || raw.length === 0)
|
|
539
|
+
return undefined;
|
|
540
|
+
const shown = shownRunError(raw);
|
|
541
|
+
return shown.length > 0 ? shown : undefined;
|
|
511
542
|
}
|
|
512
543
|
function workflowPollDecisionOf(delivered, reading) {
|
|
513
544
|
if (delivered)
|
|
@@ -518,7 +549,13 @@ function workflowPollDecisionOf(delivered, reading) {
|
|
|
518
549
|
return { act: 'wait', why: 'awaiting approval' };
|
|
519
550
|
if (reading.state === 'unknown')
|
|
520
551
|
return { act: 'wait', why: 'unknown' };
|
|
521
|
-
return {
|
|
552
|
+
return {
|
|
553
|
+
act: 'emit',
|
|
554
|
+
status: reading.state,
|
|
555
|
+
...(reading.result !== undefined ? { result: reading.result } : {}),
|
|
556
|
+
...(reading.error !== undefined ? { error: reading.error } : {}),
|
|
557
|
+
...(reading.truncated === true ? { truncated: true } : {}),
|
|
558
|
+
};
|
|
522
559
|
}
|
|
523
560
|
function workflowPollCompletionSummary(status, error) {
|
|
524
561
|
const head = `workflow ${status} (read from its run record; no handle to the full record is available)`;
|
|
@@ -826,7 +863,7 @@ async function tickWatchInner(now) {
|
|
|
826
863
|
if (outstandingRuns.delete(runId))
|
|
827
864
|
notifyOutstanding();
|
|
828
865
|
if (decision.act === 'emit') {
|
|
829
|
-
enqueueWorkflowCompletion({ runId, status: decision.status, summary: workflowPollCompletionSummary(decision.status, decision.error) }, { ...(decision.result !== undefined ? { result: decision.result } : {}), ...(decision.error !== undefined ? { error: decision.error } : {}) });
|
|
866
|
+
enqueueWorkflowCompletion({ runId, status: decision.status, summary: workflowPollCompletionSummary(decision.status, decision.error) }, { ...(decision.result !== undefined ? { result: decision.result } : {}), ...(decision.error !== undefined ? { error: decision.error } : {}) }, { truncated: decision.truncated === true });
|
|
830
867
|
}
|
|
831
868
|
}
|
|
832
869
|
catch {
|
|
@@ -890,9 +927,17 @@ export function enqueueEngineWorkflowNotification(raw) {
|
|
|
890
927
|
traceNotif('workflow-notification dropped:payload-unreadable');
|
|
891
928
|
return;
|
|
892
929
|
}
|
|
893
|
-
|
|
930
|
+
const extras = workflowCompletionExtrasOf(c);
|
|
931
|
+
if (notifiedRunIds.has(c.runId)) {
|
|
932
|
+
const supplement = takeWorkflowPointerSupplement(c.runId, c.status, extras.diagnostics, extras.completionId);
|
|
933
|
+
if (supplement !== undefined) {
|
|
934
|
+
port()?.enqueuePendingNotification(taskNotificationQueueCommand(supplement));
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
enqueueWorkflowCompletion(c, completionIdOnly(extras));
|
|
894
939
|
}
|
|
895
|
-
function enqueueWorkflowCompletion(c, body) {
|
|
940
|
+
function enqueueWorkflowCompletion(c, body, poll) {
|
|
896
941
|
if (notifiedRunIds.has(c.runId)) {
|
|
897
942
|
workflowDedupDropped++;
|
|
898
943
|
traceNotif(`workflow notification suppressed (run already notified) runId=${c.runId} status=${c.status}`);
|
|
@@ -900,11 +945,68 @@ function enqueueWorkflowCompletion(c, body) {
|
|
|
900
945
|
}
|
|
901
946
|
markRunNotified(c.runId);
|
|
902
947
|
cardEnqueuedRunIds.add(c.runId);
|
|
948
|
+
if (poll !== undefined)
|
|
949
|
+
notePointerOwed(c.runId, poll.truncated);
|
|
903
950
|
port()?.enqueuePendingNotification(taskNotificationQueueCommand({ taskId: c.runId, taskType: 'workflow', status: c.status, summary: c.summary, ...body }));
|
|
904
951
|
}
|
|
952
|
+
const pointerOwedRuns = new Map();
|
|
953
|
+
const POINTER_OWED_MAX = 512;
|
|
954
|
+
function notePointerOwed(runId, truncated) {
|
|
955
|
+
pointerOwedRuns.delete(runId);
|
|
956
|
+
pointerOwedRuns.set(runId, { truncated });
|
|
957
|
+
while (pointerOwedRuns.size > POINTER_OWED_MAX) {
|
|
958
|
+
const oldest = pointerOwedRuns.keys().next();
|
|
959
|
+
if (oldest.done === true)
|
|
960
|
+
break;
|
|
961
|
+
pointerOwedRuns.delete(oldest.value);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
const WORKFLOW_RECORD_REF_SENTENCE = /Full record \(the result and every agent's row\): read it with ReadToolResult \(ref "([A-Za-z0-9_.~-]{1,518})"\) before assuming an empty or unexpected result\./g;
|
|
965
|
+
export function workflowRecordRefOf(diagnostics) {
|
|
966
|
+
if (typeof diagnostics !== 'string' || diagnostics.length === 0)
|
|
967
|
+
return undefined;
|
|
968
|
+
try {
|
|
969
|
+
let ref;
|
|
970
|
+
for (const m of diagnostics.matchAll(WORKFLOW_RECORD_REF_SENTENCE))
|
|
971
|
+
ref = m[1];
|
|
972
|
+
return ref;
|
|
973
|
+
}
|
|
974
|
+
catch {
|
|
975
|
+
return undefined;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
function workflowPointerSupplementSummary(ref, truncated) {
|
|
979
|
+
const head = `Full record of this workflow run (the result and every agent's row): read it with ReadToolResult (ref "${ref}")`;
|
|
980
|
+
return truncated ? `${head} — the result delivered earlier was cut short; the full text is in this record.` : `${head}.`;
|
|
981
|
+
}
|
|
982
|
+
export function takeWorkflowPointerSupplement(runId, status, diagnostics, completionId) {
|
|
983
|
+
try {
|
|
984
|
+
const owed = pointerOwedRuns.get(runId);
|
|
985
|
+
if (owed === undefined)
|
|
986
|
+
return undefined;
|
|
987
|
+
const ref = workflowRecordRefOf(diagnostics);
|
|
988
|
+
if (ref === undefined)
|
|
989
|
+
return undefined;
|
|
990
|
+
pointerOwedRuns.delete(runId);
|
|
991
|
+
return freezeTaskNotificationFields({
|
|
992
|
+
taskId: runId,
|
|
993
|
+
taskType: 'workflow',
|
|
994
|
+
status,
|
|
995
|
+
summary: workflowPointerSupplementSummary(ref, owed.truncated),
|
|
996
|
+
...(completionId !== undefined ? { completionId } : {}),
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
catch {
|
|
1000
|
+
return undefined;
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
export function settleWorkflowPointerOwed(runId) {
|
|
1004
|
+
pointerOwedRuns.delete(runId);
|
|
1005
|
+
}
|
|
905
1006
|
export function _resetEngineTaskNotificationForTest() {
|
|
906
1007
|
notifiedRunIds.clear();
|
|
907
1008
|
notifiedBgCycleHigh.clear();
|
|
1009
|
+
pointerOwedRuns.clear();
|
|
908
1010
|
cardEnqueuedRunIds.clear();
|
|
909
1011
|
outstandingRuns.clear();
|
|
910
1012
|
outstandingBgTasks.clear();
|
package/dist/ownKey.d.ts
CHANGED
|
@@ -79,3 +79,9 @@ export declare function workflowCompletionExtrasOf(c: object): {
|
|
|
79
79
|
completionId?: string;
|
|
80
80
|
diagnostics?: string;
|
|
81
81
|
};
|
|
82
|
+
export interface ResupplyTruncatedFacts {
|
|
83
|
+
readonly bytes: number;
|
|
84
|
+
readonly droppedKeys: readonly string[];
|
|
85
|
+
}
|
|
86
|
+
export declare function resupplyTruncatedFactsOf(slot: {} | null | undefined): ResupplyTruncatedFacts | undefined;
|
|
87
|
+
export declare function resupplyTruncatedOf(carrier: object | null | undefined): ResupplyTruncatedFacts | undefined;
|
package/dist/ownKey.js
CHANGED
|
@@ -453,3 +453,34 @@ export function workflowCompletionExtrasOf(c) {
|
|
|
453
453
|
...(diagnostics !== undefined ? { diagnostics } : {}),
|
|
454
454
|
};
|
|
455
455
|
}
|
|
456
|
+
const DROPPED_KEYS_MAX = 256;
|
|
457
|
+
const DROPPED_KEY_NAME_MAX = 128;
|
|
458
|
+
export function resupplyTruncatedFactsOf(slot) {
|
|
459
|
+
try {
|
|
460
|
+
if (typeof slot !== 'object' || slot === null || Array.isArray(slot))
|
|
461
|
+
return undefined;
|
|
462
|
+
const bytes = guardedRead(() => readOwnDataValue(slot, 'bytes'));
|
|
463
|
+
if (typeof bytes !== 'number' || !Number.isSafeInteger(bytes) || bytes <= 0)
|
|
464
|
+
return undefined;
|
|
465
|
+
const keys = guardedRead(() => readOwnDataValue(slot, 'droppedKeys'));
|
|
466
|
+
if (!Array.isArray(keys))
|
|
467
|
+
return undefined;
|
|
468
|
+
const length = guardedRead(() => keys.length);
|
|
469
|
+
if (typeof length !== 'number' || length < 1 || length > DROPPED_KEYS_MAX)
|
|
470
|
+
return undefined;
|
|
471
|
+
const names = [];
|
|
472
|
+
for (let i = 0; i < length; i++) {
|
|
473
|
+
const name = guardedRead(() => readOwnDataValue(keys, String(i)));
|
|
474
|
+
if (typeof name !== 'string' || name.length === 0 || name.length > DROPPED_KEY_NAME_MAX)
|
|
475
|
+
return undefined;
|
|
476
|
+
appendOwnElement(names, name);
|
|
477
|
+
}
|
|
478
|
+
return Object.freeze({ bytes, droppedKeys: Object.freeze(names) });
|
|
479
|
+
}
|
|
480
|
+
catch {
|
|
481
|
+
return undefined;
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
export function resupplyTruncatedOf(carrier) {
|
|
485
|
+
return resupplyTruncatedFactsOf(guardedRead(() => readOwnDataValue(carrier, 'payloadTruncated')));
|
|
486
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const PENDING_USER_ROW_ID_PREFIX = "pending-";
|
|
2
|
+
export declare function pendingUserRowIdOf(uuid: string): string | undefined;
|
|
3
|
+
export declare function pendingUserRowUuidOf(id: string | null | undefined): string | undefined;
|
|
4
|
+
export declare function isPendingUserRowId(id: string | null | undefined): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const PENDING_USER_ROW_ID_PREFIX = 'pending-';
|
|
2
|
+
const UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
3
|
+
export function pendingUserRowIdOf(uuid) {
|
|
4
|
+
if (typeof uuid !== 'string' || !UUID_V4.test(uuid))
|
|
5
|
+
return undefined;
|
|
6
|
+
return PENDING_USER_ROW_ID_PREFIX + uuid;
|
|
7
|
+
}
|
|
8
|
+
export function pendingUserRowUuidOf(id) {
|
|
9
|
+
if (typeof id !== 'string' || !id.startsWith(PENDING_USER_ROW_ID_PREFIX))
|
|
10
|
+
return undefined;
|
|
11
|
+
const uuid = id.slice(PENDING_USER_ROW_ID_PREFIX.length);
|
|
12
|
+
return pendingUserRowIdOf(uuid) === id ? uuid : undefined;
|
|
13
|
+
}
|
|
14
|
+
export function isPendingUserRowId(id) {
|
|
15
|
+
return pendingUserRowUuidOf(id) !== undefined;
|
|
16
|
+
}
|
|
@@ -115,6 +115,7 @@ export declare function assembledRuleRows(input: PermissionsDeclarationInput, ca
|
|
|
115
115
|
export interface PermissionsAllowKeptFacts {
|
|
116
116
|
readonly problemCount?: number;
|
|
117
117
|
readonly managedPolicyPending?: true;
|
|
118
|
+
readonly managedPolicyFetch?: 'in_progress' | 'failed' | 'unknown';
|
|
118
119
|
readonly where?: string;
|
|
119
120
|
}
|
|
120
121
|
export declare function permissionsAllowKeptNotice(report: Pick<PermissionsDeclarationReport, 'kept'>, settingsRead: 'clean' | 'partial' | 'unreadable', facts?: PermissionsAllowKeptFacts): string | undefined;
|
|
@@ -543,11 +543,21 @@ export function permissionsAllowKeptNotice(report, settingsRead, facts) {
|
|
|
543
543
|
const rawCount = readFact('problemCount');
|
|
544
544
|
const rawWhere = readFact('where');
|
|
545
545
|
const managedPending = readFact('managedPolicyPending') === true;
|
|
546
|
+
const rawFetch = readFact('managedPolicyFetch');
|
|
547
|
+
const fetchState = rawFetch === 'in_progress' || rawFetch === 'failed' ? rawFetch : 'unknown';
|
|
546
548
|
const count = typeof rawCount === 'number' && Number.isInteger(rawCount) && rawCount >= 1 ? rawCount : undefined;
|
|
547
549
|
const where = typeof rawWhere === 'string' && rawWhere.length >= 1 && rawWhere.length <= 200 && !/\p{Cc}/u.test(rawWhere) ? rawWhere : undefined;
|
|
548
550
|
const head = `${String(held)} permissions.allow rule${held === 1 ? ' was' : 's were'} not sent to the engine for this run because `;
|
|
549
551
|
if (settingsRead === 'partial' && managedPending && count === 1) {
|
|
550
|
-
|
|
552
|
+
if (fetchState === 'in_progress') {
|
|
553
|
+
return (`${head}the managed policy for your account has not been received yet (sema keeps fetching it; allow rules apply once it arrives). ` +
|
|
554
|
+
'Run again once it has been received (deny and ask rules, and rules given with --allowedTools, are still sent).');
|
|
555
|
+
}
|
|
556
|
+
if (fetchState === 'failed') {
|
|
557
|
+
return (`${head}the managed policy for your account has not been received yet (this run will not fetch again; the next run retries). ` +
|
|
558
|
+
'Run again to retry fetching it (deny and ask rules, and rules given with --allowedTools, are still sent).');
|
|
559
|
+
}
|
|
560
|
+
return (`${head}the managed policy for your account has not been received yet. ` +
|
|
551
561
|
'Run again once it has been received (deny and ask rules, and rules given with --allowedTools, are still sent).');
|
|
552
562
|
}
|
|
553
563
|
const why = settingsRead === 'partial'
|
|
@@ -16,6 +16,7 @@ export interface PlanReviewCardFacts {
|
|
|
16
16
|
readonly taskId: string;
|
|
17
17
|
readonly checkpointId?: string;
|
|
18
18
|
readonly body: PlanReviewBody;
|
|
19
|
+
readonly evidenceRevision?: number;
|
|
19
20
|
}
|
|
20
21
|
export declare function planReviewBodyOf(text: string): Exclude<PlanReviewBody, {
|
|
21
22
|
kind: 'unknown';
|
|
@@ -91,10 +92,12 @@ export interface PlanBodyClaimLeg {
|
|
|
91
92
|
}>;
|
|
92
93
|
overflow: boolean;
|
|
93
94
|
unreadable: boolean;
|
|
95
|
+
readonly seen: Set<string>;
|
|
94
96
|
}
|
|
95
97
|
export declare function openPlanBodyClaimLeg(): PlanBodyClaimLeg;
|
|
96
98
|
export declare function stepPlanBodyClaim(leg: PlanBodyClaimLeg, frame: object, subFlow: boolean): void;
|
|
97
99
|
export declare function planReviewParkFacts(leg: PlanBodyClaimLeg, result: {} | null | undefined): PlanReviewCardFacts | undefined;
|
|
100
|
+
export declare function planReviewClaimStep(leg: PlanBodyClaimLeg, frame: object, subFlow: boolean, seq: string | undefined): PlanReviewCardFacts | undefined;
|
|
98
101
|
export interface PlanReviewFactsTaken {
|
|
99
102
|
readonly sessionKey: string;
|
|
100
103
|
readonly taskId: string;
|
|
@@ -3,6 +3,7 @@ import { readRunTerminal, runTerminalGateKind } from './runTerminal.js';
|
|
|
3
3
|
import { SDK_PLAN_REVIEW_GATE_KINDS } from './generated/sdkFactTables.js';
|
|
4
4
|
import { CORE_PRESENT_PLAN_TOOL_NAME } from './generated/engineFactTables.js';
|
|
5
5
|
import { DEFAULT_SESSION_KEY } from './sessionSlot.js';
|
|
6
|
+
import { doneResultView } from './replayBody.js';
|
|
6
7
|
const PLAN_BODY_MAX_LENGTH = 200_000;
|
|
7
8
|
const PLAN_BODY_UNKNOWN_CAUSES = Object.freeze([
|
|
8
9
|
'not_observed', 'gate_unidentified', 'gate_moved', 'unreadable', 'ambiguous_call', 'malformed_frame', 'conflicting_claims', 'not_presented', 'not_carried',
|
|
@@ -29,6 +30,13 @@ export function mintPlanReviewCardFacts(taskId, checkpointId, body) {
|
|
|
29
30
|
const b = checkpointId === undefined ? unknownBody('gate_unidentified') : body;
|
|
30
31
|
return Object.freeze({ taskId, ...(checkpointId !== undefined ? { checkpointId } : {}), body: Object.isFrozen(b) ? b : Object.freeze({ ...b }) });
|
|
31
32
|
}
|
|
33
|
+
let evidenceRevisionSeq = 0;
|
|
34
|
+
function withEvidenceRevision(facts, evidenceRevision) {
|
|
35
|
+
return Object.freeze({ taskId: facts.taskId, ...(facts.checkpointId !== undefined ? { checkpointId: facts.checkpointId } : {}), body: facts.body, evidenceRevision });
|
|
36
|
+
}
|
|
37
|
+
function isEvidenceRevision(v) {
|
|
38
|
+
return typeof v === 'number' && Number.isSafeInteger(v) && v > 0;
|
|
39
|
+
}
|
|
32
40
|
export function unknownBody(cause) {
|
|
33
41
|
return Object.freeze({ kind: 'unknown', cause });
|
|
34
42
|
}
|
|
@@ -59,7 +67,11 @@ export function planReviewCardFactsFrom(v) {
|
|
|
59
67
|
const checkpointId = ck.present ? ck.value : undefined;
|
|
60
68
|
if (checkpointId === undefined && !(body.kind === 'unknown' && body.cause === 'gate_unidentified'))
|
|
61
69
|
return undefined;
|
|
62
|
-
|
|
70
|
+
const eg = ownData(v, 'evidenceRevision');
|
|
71
|
+
if (eg.present && !isEvidenceRevision(eg.value))
|
|
72
|
+
return undefined;
|
|
73
|
+
const minted = mintPlanReviewCardFacts(taskId, checkpointId, body);
|
|
74
|
+
return eg.present ? withEvidenceRevision(minted, eg.value) : minted;
|
|
63
75
|
}
|
|
64
76
|
catch {
|
|
65
77
|
return undefined;
|
|
@@ -167,6 +179,10 @@ export function commitPlanReviewFacts(ticket, facts, claim, highWater) {
|
|
|
167
179
|
if (prev !== undefined && prev.checkpointId === checkpointId && (isConflict(prev.facts) || !samePlanClaim(prev.claim, claim))) {
|
|
168
180
|
out = mintPlanReviewCardFacts(facts.taskId, checkpointId, unknownBody('conflicting_claims'));
|
|
169
181
|
}
|
|
182
|
+
const reused = prev !== undefined && prev.checkpointId === checkpointId && prev.facts.evidenceRevision !== undefined && samePlanReviewCardFacts(prev.facts, out)
|
|
183
|
+
? prev.facts.evidenceRevision
|
|
184
|
+
: undefined;
|
|
185
|
+
out = withEvidenceRevision(out, reused ?? ++evidenceRevisionSeq);
|
|
170
186
|
rec.gate = { checkpointId, facts: out, claim, generation: ticket.generation, ...(highWater !== undefined ? { highWater } : {}) };
|
|
171
187
|
return out;
|
|
172
188
|
}
|
|
@@ -338,7 +354,7 @@ function foldMarker(rec, frame) {
|
|
|
338
354
|
}
|
|
339
355
|
const LEG_BUFFER_MAX = 256;
|
|
340
356
|
export function openPlanBodyClaimLeg() {
|
|
341
|
-
return { buffer: [], overflow: false, unreadable: false };
|
|
357
|
+
return { buffer: [], overflow: false, unreadable: false, seen: new Set() };
|
|
342
358
|
}
|
|
343
359
|
function bindLeg(leg, taskId) {
|
|
344
360
|
const rec = recordFor(DEFAULT_SESSION_KEY, taskId);
|
|
@@ -425,6 +441,40 @@ export function planReviewParkFacts(leg, result) {
|
|
|
425
441
|
return taskId === undefined ? undefined : mintPlanReviewCardFacts(taskId, checkpointId, unknownBody('unreadable'));
|
|
426
442
|
}
|
|
427
443
|
}
|
|
444
|
+
export function planReviewClaimStep(leg, frame, subFlow, seq) {
|
|
445
|
+
if (claimSeqDedupe(leg, frame, seq) === 'duplicate')
|
|
446
|
+
return undefined;
|
|
447
|
+
stepPlanBodyClaim(leg, frame, subFlow);
|
|
448
|
+
let result;
|
|
449
|
+
try {
|
|
450
|
+
if (frame.type !== 'done')
|
|
451
|
+
return undefined;
|
|
452
|
+
result = frame.result;
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
return undefined;
|
|
456
|
+
}
|
|
457
|
+
return planReviewParkFacts(leg, doneResultView(result).body);
|
|
458
|
+
}
|
|
459
|
+
function claimSeqDedupe(leg, frame, seq) {
|
|
460
|
+
try {
|
|
461
|
+
if (seq !== undefined && classOf(frame) !== 'other') {
|
|
462
|
+
if (leg.seen.has(seq))
|
|
463
|
+
return 'duplicate';
|
|
464
|
+
leg.seen.add(seq);
|
|
465
|
+
while (leg.seen.size > SETTLED_CALLS_MAX) {
|
|
466
|
+
const oldest = leg.seen.values().next();
|
|
467
|
+
if (oldest.done === true)
|
|
468
|
+
break;
|
|
469
|
+
leg.seen.delete(oldest.value);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return 'fresh';
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
return 'class_unreadable';
|
|
476
|
+
}
|
|
477
|
+
}
|
|
428
478
|
function legRecord(leg, taskId) {
|
|
429
479
|
return leg.taskId === undefined || leg.taskId === taskId ? bindLeg(leg, taskId) : recordFor(DEFAULT_SESSION_KEY, taskId);
|
|
430
480
|
}
|
|
@@ -12,8 +12,10 @@ export declare const PLUGIN_HOOK_REASONS: readonly ["projected", "shell_event",
|
|
|
12
12
|
export type PluginHookReason = (typeof PLUGIN_HOOK_REASONS)[number];
|
|
13
13
|
export declare const PLUGIN_HOOK_EXCLUSION_REASONS: readonly ["workspace_untrusted", "governance_unreadable", "policy_disable_all", "startup_mode", "managed_plugins_only", "prompt_not_user_authored"];
|
|
14
14
|
export type PluginHookExclusionReason = (typeof PLUGIN_HOOK_EXCLUSION_REASONS)[number];
|
|
15
|
-
export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported", "key_not_read", "source_not_authored", "workspace_untrusted", "governance_unreadable", "policy_disable_all"];
|
|
15
|
+
export declare const SETTINGS_HOOK_DROP_REASONS: readonly ["exec_form_unsupported", "mcp_tool_unsupported", "key_not_read", "source_not_authored", "workspace_untrusted", "governance_unreadable", "policy_disable_all", "no_executor"];
|
|
16
16
|
export type SettingsHookDropReason = (typeof SETTINGS_HOOK_DROP_REASONS)[number];
|
|
17
|
+
export type HookEntryTypeWord = 'command' | 'prompt' | 'agent' | 'http' | 'mcp_tool';
|
|
18
|
+
export declare const HOOK_ENTRY_TYPE_WORDS: readonly ["command", "prompt", "agent", "http", "mcp_tool"];
|
|
17
19
|
export type HookSettingsSource = 'policySettings' | 'userSettings' | 'projectSettings' | 'localSettings' | 'flagSettings';
|
|
18
20
|
export interface PluginHookKey {
|
|
19
21
|
readonly pluginId: string;
|
|
@@ -34,6 +36,7 @@ export interface SettingsHookDrop {
|
|
|
34
36
|
readonly event: string;
|
|
35
37
|
readonly groupIndex: number;
|
|
36
38
|
readonly hookIndex: number;
|
|
39
|
+
readonly type?: HookEntryTypeWord;
|
|
37
40
|
readonly reason: SettingsHookDropReason;
|
|
38
41
|
readonly notRun: boolean;
|
|
39
42
|
readonly unreadKeys?: readonly (readonly (string | number)[])[];
|
|
@@ -43,6 +46,7 @@ export interface SettingsHookVerdict {
|
|
|
43
46
|
readonly event: string;
|
|
44
47
|
readonly groupIndex: number;
|
|
45
48
|
readonly hookIndex: number;
|
|
49
|
+
readonly type?: HookEntryTypeWord;
|
|
46
50
|
readonly disposition: PluginHookDisposition;
|
|
47
51
|
readonly reason: PluginHookReason;
|
|
48
52
|
}
|
|
@@ -51,6 +55,7 @@ export interface SettingsHookExclusion {
|
|
|
51
55
|
readonly event: string;
|
|
52
56
|
readonly groupIndex: number;
|
|
53
57
|
readonly hookIndex: number;
|
|
58
|
+
readonly type?: HookEntryTypeWord;
|
|
54
59
|
readonly reason: PluginHookExclusionReason;
|
|
55
60
|
}
|
|
56
61
|
export interface SettingsHooksSalvageRow {
|
|
@@ -169,6 +174,9 @@ export declare function decideSessionHooks(input: SessionHookDecisionInput): {
|
|
|
169
174
|
readonly unreadable: number;
|
|
170
175
|
};
|
|
171
176
|
export declare function filterSettingsHookGroups(source: HookSettingsSource, event: string, groups: readonly WireHookGroup[], execFormCapable: boolean, shellRunsType: (type: string | undefined) => boolean, judge: SettingsHookJudge, readerNotRead: readonly string[], mask?: HooksSalvageMask): SettingsHookFilterResult;
|
|
177
|
+
export declare function hookEntryTypeWordOf(entry: {} | null | undefined): {
|
|
178
|
+
readonly type?: HookEntryTypeWord;
|
|
179
|
+
};
|
|
172
180
|
export interface SettingsHookFilterResult {
|
|
173
181
|
readonly groups: WireHookGroup[];
|
|
174
182
|
readonly drops: SettingsHookDrop[];
|
package/dist/pluginHooksWire.js
CHANGED
|
@@ -3,6 +3,7 @@ import { appendOwnElement, readOwnDataValue } from './ownKey.js';
|
|
|
3
3
|
import { inSlotReadOf } from './wireFailureShape.js';
|
|
4
4
|
import { msg, renderMessage } from './i18n/translate.js';
|
|
5
5
|
import { SETTINGS_ENGINE_OWNED_HOOK_EVENTS } from './generated/settingsSchemaTables.js';
|
|
6
|
+
import { SETTINGS_HOOK_EVENTS } from './generated/settingsSchemaFns.js';
|
|
6
7
|
import { HOOK_SETTINGS_SOURCE_TEXT, hooksEntryUnreadKeys, hooksGroupAuthoredSource, hooksGroupUnreadKeys, hooksKeyCoordinateText, hooksSalvageMaskOf, salvageSettingsHooksEntries, } from './settingsHooksSalvage.js';
|
|
7
8
|
export const ENGINE_FIRED_HOOK_EVENTS = SETTINGS_ENGINE_OWNED_HOOK_EVENTS;
|
|
8
9
|
export const PLUGIN_HOOK_DISPOSITIONS = ['engine', 'shell', 'not_run'];
|
|
@@ -49,7 +50,11 @@ export const SETTINGS_HOOK_DROP_REASONS = [
|
|
|
49
50
|
'workspace_untrusted',
|
|
50
51
|
'governance_unreadable',
|
|
51
52
|
'policy_disable_all',
|
|
53
|
+
'no_executor',
|
|
52
54
|
];
|
|
55
|
+
export const HOOK_ENTRY_TYPE_WORDS = Object.freeze(['command', 'prompt', 'agent', 'http', 'mcp_tool']);
|
|
56
|
+
const _hookEntryTypePins = [true, true, true, true];
|
|
57
|
+
void _hookEntryTypePins;
|
|
53
58
|
export function hooksWirePlanShapeOf(v) {
|
|
54
59
|
try {
|
|
55
60
|
if (typeof v !== 'object' || v === null || Array.isArray(v))
|
|
@@ -144,6 +149,7 @@ function hookExecutorOf(x) {
|
|
|
144
149
|
return judged(x.shellRuns ? 'shell' : 'not_run', why);
|
|
145
150
|
}
|
|
146
151
|
const ENGINE_EVENTS = new Set(ENGINE_FIRED_HOOK_EVENTS);
|
|
152
|
+
const SHELL_OWNED_EVENTS = new Set(SETTINGS_HOOK_EVENTS.filter((e) => !ENGINE_EVENTS.has(e)));
|
|
147
153
|
const USER_CONFIG_REF_ONE = /\$\{user_config\.[^}]+\}/;
|
|
148
154
|
const USER_CONFIG_REF_ALL = /\$\{user_config\.([^}]+)\}/g;
|
|
149
155
|
function isRecord(v) {
|
|
@@ -493,10 +499,23 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
|
|
|
493
499
|
const excluded = [];
|
|
494
500
|
const out = [];
|
|
495
501
|
let stripped = 0;
|
|
496
|
-
const engineEvent =
|
|
502
|
+
const engineEvent = isEngineFiredHookEvent(event);
|
|
503
|
+
const shellOwned = !engineEvent && SHELL_OWNED_EVENTS.has(event);
|
|
497
504
|
groups.forEach((group, groupIndex) => {
|
|
498
505
|
if (mask !== undefined && mask.groupDropped(event, groupIndex))
|
|
499
506
|
return;
|
|
507
|
+
if (!engineEvent) {
|
|
508
|
+
if (!shellOwned || !isRecord(group) || !Array.isArray(group.hooks))
|
|
509
|
+
return;
|
|
510
|
+
group.hooks.forEach((entry, hookIndex) => {
|
|
511
|
+
if (mask !== undefined && mask.entryDropped(event, groupIndex, hookIndex))
|
|
512
|
+
return;
|
|
513
|
+
if (shellRunsType(isRecord(entry) && typeof entry.type === 'string' ? entry.type : undefined))
|
|
514
|
+
return;
|
|
515
|
+
appendOwnElement(drops, { source, event, groupIndex, hookIndex, reason: 'no_executor', notRun: true });
|
|
516
|
+
});
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
500
519
|
if (!isRecord(group) || !Array.isArray(group.hooks)) {
|
|
501
520
|
appendOwnElement(out, group);
|
|
502
521
|
return;
|
|
@@ -522,27 +541,29 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
|
|
|
522
541
|
const sourceNotAuthored = earlier === undefined && groupSourceAuthored && (authored === 'unreadable' || entryUnread !== undefined);
|
|
523
542
|
const unreadKeys = earlier === undefined && !sourceNotAuthored ? unreadKeyPathsOf(event, groupIndex, hookIndex, groupUnread ?? [], entryUnread) : [];
|
|
524
543
|
const reason = earlier ?? (sourceNotAuthored ? 'source_not_authored' : unreadKeys.length > 0 ? 'key_not_read' : undefined);
|
|
544
|
+
const typed = hookEntryTypeWordOf(entry);
|
|
525
545
|
if (reason !== undefined) {
|
|
526
546
|
appendOwnElement(drops, {
|
|
527
547
|
source,
|
|
528
548
|
event,
|
|
529
549
|
groupIndex,
|
|
530
550
|
hookIndex,
|
|
551
|
+
...typed,
|
|
531
552
|
reason,
|
|
532
|
-
notRun:
|
|
553
|
+
notRun: !shellRunsType(isRecord(entry) && typeof entry.type === 'string' ? entry.type : undefined),
|
|
533
554
|
...(reason === 'key_not_read' ? { unreadKeys } : {}),
|
|
534
555
|
});
|
|
535
556
|
changed = true;
|
|
536
557
|
return;
|
|
537
558
|
}
|
|
538
|
-
if (
|
|
559
|
+
if (isRecord(entry) && judgeableSettingsEntry(entry)) {
|
|
539
560
|
const ex = judge(event, group, entry);
|
|
540
561
|
if (ex.kind === 'excluded') {
|
|
541
|
-
appendOwnElement(excluded, { source, event, groupIndex, hookIndex, reason: ex.reason });
|
|
562
|
+
appendOwnElement(excluded, { source, event, groupIndex, hookIndex, ...typed, reason: ex.reason });
|
|
542
563
|
changed = true;
|
|
543
564
|
return;
|
|
544
565
|
}
|
|
545
|
-
appendOwnElement(verdicts, { source, event, groupIndex, hookIndex, disposition: ex.disposition, reason: ex.reason });
|
|
566
|
+
appendOwnElement(verdicts, { source, event, groupIndex, hookIndex, ...typed, disposition: ex.disposition, reason: ex.reason });
|
|
546
567
|
if (ex.disposition === 'shell') {
|
|
547
568
|
changed = true;
|
|
548
569
|
return;
|
|
@@ -567,6 +588,17 @@ export function filterSettingsHookGroups(source, event, groups, execFormCapable,
|
|
|
567
588
|
});
|
|
568
589
|
return { groups: out, drops, stripped, verdicts, excluded };
|
|
569
590
|
}
|
|
591
|
+
export function hookEntryTypeWordOf(entry) {
|
|
592
|
+
try {
|
|
593
|
+
if (!isRecord(entry))
|
|
594
|
+
return {};
|
|
595
|
+
const t = readOwnDataValue(entry, 'type');
|
|
596
|
+
return typeof t === 'string' && HOOK_ENTRY_TYPE_WORDS.includes(t) ? { type: t } : {};
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
return {};
|
|
600
|
+
}
|
|
601
|
+
}
|
|
570
602
|
function judgeableSettingsEntry(entry) {
|
|
571
603
|
const type = entry.type;
|
|
572
604
|
if (typeof type !== 'string' || !ENGINE_HOOK_TYPE_RUNS.has(type))
|
|
@@ -899,7 +931,7 @@ function settingsExclusionRowOf(v) {
|
|
|
899
931
|
const REASON_TEXT = {
|
|
900
932
|
projected: 'it is sent to the engine',
|
|
901
933
|
shell_event: 'this client runs this event itself',
|
|
902
|
-
no_executor: '
|
|
934
|
+
no_executor: renderMessage(msg('config.hooks.plan.reason.noExecutor')),
|
|
903
935
|
engine_not_local: 'the engine was not started by this client on this machine, so it cannot reach the plugin files',
|
|
904
936
|
engine_locality_unknown: 'it is not known whether the engine was started by this client on this machine, so plugin hooks are not sent to it',
|
|
905
937
|
engine_capability_absent: 'the connected engine does not support plugin hooks',
|
|
@@ -931,6 +963,7 @@ const DROP_TEXT = {
|
|
|
931
963
|
workspace_untrusted: renderMessage(msg('config.hooks.plan.reason.closedUntrusted')),
|
|
932
964
|
governance_unreadable: renderMessage(msg('config.hooks.plan.reason.closedGovernanceUnreadable')),
|
|
933
965
|
policy_disable_all: renderMessage(msg('config.hooks.plan.reason.closedDisableAll')),
|
|
966
|
+
no_executor: REASON_TEXT.no_executor,
|
|
934
967
|
};
|
|
935
968
|
const SOURCE_TEXT = HOOK_SETTINGS_SOURCE_TEXT;
|
|
936
969
|
export function pluginHookReasonText(reason) {
|
|
@@ -1011,6 +1044,7 @@ function namedPathsOfRow(d) {
|
|
|
1011
1044
|
case 'workspace_untrusted':
|
|
1012
1045
|
case 'governance_unreadable':
|
|
1013
1046
|
case 'policy_disable_all':
|
|
1047
|
+
case 'no_executor':
|
|
1014
1048
|
return [];
|
|
1015
1049
|
}
|
|
1016
1050
|
}
|
|
@@ -24,6 +24,8 @@ export function toolEndResultToUserFrame(arm) {
|
|
|
24
24
|
}, undefined, parent === null ? 'leader' : 'subagent');
|
|
25
25
|
const envelope = toolResultEnvelopeParts(outcome);
|
|
26
26
|
const gateView = guardedRead(() => gateOutcomeOf(arm));
|
|
27
|
+
const denialKindRaw = arm._sema_denial_kind;
|
|
28
|
+
const denialKind = typeof denialKindRaw === 'string' ? denialKindRaw : undefined;
|
|
27
29
|
const content = Array.isArray(outcome.body.content) ? outcome.body.content : arm.truncated === true ? `${text}\n…(truncated)` : text;
|
|
28
30
|
return {
|
|
29
31
|
type: 'user',
|
|
@@ -39,9 +41,9 @@ export function toolEndResultToUserFrame(arm) {
|
|
|
39
41
|
],
|
|
40
42
|
},
|
|
41
43
|
parent_tool_use_id: parent,
|
|
42
|
-
...(isCcToolDenialKind(
|
|
44
|
+
...(isCcToolDenialKind(denialKind) ? { _sema_denial_kind: denialKind } : {}),
|
|
43
45
|
...(gateView !== undefined ? { _sema_gate: gateView } : {}),
|
|
44
|
-
...toolResultRowFlagParts(arm, gateView),
|
|
46
|
+
...toolResultRowFlagParts(arm, gateView, denialKind),
|
|
45
47
|
...(Object.hasOwn(envelope, 'tool_use_result') ? { tool_use_result: envelope.tool_use_result } : {}),
|
|
46
48
|
...(Object.hasOwn(envelope, '_sema_degraded') ? { _sema_degraded: envelope._sema_degraded } : {}),
|
|
47
49
|
uuid: rowIdentity.uuid,
|