@sema-agent/client-core 0.100.0 → 0.101.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 +395 -0
- package/README.md +164 -117
- package/dist/adapt/arms.js +51 -16
- package/dist/adapt/textStream.js +7 -4
- package/dist/adapt/toolCards.js +9 -8
- package/dist/adapt.js +7 -1
- package/dist/adapter/activeRunSelfHeal.d.ts +24 -2
- package/dist/adapter/activeRunSelfHeal.js +108 -6
- package/dist/adapter/downstream/eventToSdkMessage.js +33 -12
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +60 -1
- package/dist/adapter/downstream/terminalToSdkResult.js +209 -39
- package/dist/adapter/runStream.d.ts +4 -4
- package/dist/adapter/runStream.js +158 -43
- package/dist/agentsWireCaps.d.ts +2 -7
- package/dist/agentsWireCaps.js +1 -2
- package/dist/approvalDecidedByCapability.js +2 -2
- package/dist/approvalFrameFamilies.d.ts +33 -0
- package/dist/approvalFrameFamilies.js +120 -0
- package/dist/approvalsStreamLiveCapability.js +2 -2
- package/dist/attachmentsWireCaps.js +41 -13
- package/dist/callerCwdCapability.js +2 -2
- package/dist/centerWiringCapability.js +2 -2
- package/dist/clockReading.d.ts +2 -0
- package/dist/clockReading.js +4 -0
- package/dist/cloudConfigWireCaps.d.ts +19 -5
- package/dist/cloudConfigWireCaps.js +193 -56
- package/dist/coreValuePorts.d.ts +12 -2
- package/dist/coreValuePorts.js +9 -0
- package/dist/decideFailureNote.js +5 -3
- package/dist/decideReceipt.js +2 -2
- package/dist/deviceExecutorManagementCapability.js +2 -2
- package/dist/deviceFlowPolling.js +1 -1
- package/dist/disableSkillsWire.d.ts +1 -1
- package/dist/disableSkillsWire.js +4 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +65 -8
- package/dist/engineCapReader.js +1 -1
- package/dist/engineConfigDrift.js +1 -1
- package/dist/engineErrorCodes.d.ts +14 -5
- package/dist/engineErrorCodes.js +27 -6
- package/dist/engineGenerationConvergence.d.ts +39 -0
- package/dist/engineGenerationConvergence.js +95 -0
- package/dist/engineGenerationPort.d.ts +61 -0
- package/dist/engineGenerationPort.js +144 -0
- package/dist/engineHealthFacts.d.ts +23 -0
- package/dist/engineHealthFacts.js +92 -0
- package/dist/engineIdentity.d.ts +4 -0
- package/dist/engineIdentity.js +11 -0
- package/dist/engineNoticeCodes.d.ts +2 -5
- package/dist/engineRowRef.js +3 -0
- package/dist/engineSessionMessages.js +2 -2
- package/dist/engineToolDirectory.js +2 -2
- package/dist/engineWireFor.d.ts +99 -0
- package/dist/engineWireFor.js +248 -6
- package/dist/engineWireTarget.d.ts +1 -0
- package/dist/engineWireTarget.js +8 -0
- package/dist/env/uiLanguage.js +1 -1
- package/dist/errorSupplementRoles.d.ts +3 -0
- package/dist/errorSupplementRoles.js +37 -0
- package/dist/executionLaneCapability.js +2 -2
- package/dist/fileHistoryCaptureCapability.js +3 -3
- package/dist/finalVerifyWire.d.ts +6 -3
- package/dist/finalVerifyWire.js +6 -23
- package/dist/flagInput.d.ts +4 -0
- package/dist/flagInput.js +24 -0
- package/dist/fleet/fleetLedger.js +5 -2
- package/dist/fleet/fleetProjection.d.ts +1 -0
- package/dist/fleet/fleetProjection.js +15 -2
- package/dist/gateVocabulary.js +3 -0
- package/dist/generated/engineFactTables.d.ts +7 -3
- package/dist/generated/engineFactTables.js +52 -0
- package/dist/generated/engineNoticeTables.js +12 -0
- package/dist/generated/settingsSchemaActiveTiers.d.ts +1 -0
- package/dist/generated/settingsSchemaActiveTiers.js +14 -0
- package/dist/generated/settingsSchemaCallerTextEcho.d.ts +1 -0
- package/dist/generated/settingsSchemaCallerTextEcho.js +8 -0
- package/dist/generated/settingsSchemaControlAndBidi.d.ts +1 -0
- package/dist/generated/settingsSchemaControlAndBidi.js +8 -0
- package/dist/generated/settingsSchemaDefaultModel.d.ts +11 -0
- package/dist/generated/settingsSchemaDefaultModel.js +25 -0
- package/dist/generated/settingsSchemaFns.d.ts +54 -0
- package/dist/generated/settingsSchemaFns.js +26 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.d.ts +1 -1
- package/dist/generated/settingsSchemaMcpRequestEntry.js +1 -7
- package/dist/generated/settingsSchemaSafetyMergeSpec.d.ts +1 -0
- package/dist/generated/settingsSchemaSafetyMergeSpec.js +95 -0
- package/dist/generated/settingsSchemaSettingsSources.d.ts +1 -0
- package/dist/generated/settingsSchemaSettingsSources.js +58 -0
- package/dist/generated/settingsSchemaTables.d.ts +2 -0
- package/dist/generated/settingsSchemaTables.js +13 -0
- package/dist/generated/settingsSchemaUrlPattern.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlPattern.js +183 -0
- package/dist/headlessPermissionModeWire.d.ts +18 -2
- package/dist/headlessPermissionModeWire.js +30 -19
- package/dist/hitl/allowRuleShadow.js +7 -5
- package/dist/hitl/approvalCardReading.d.ts +3 -0
- package/dist/hitl/approvalCardReading.js +17 -0
- package/dist/hitl/approvalCompleteParked.js +1 -1
- package/dist/hitl/approvalDelivery.d.ts +87 -0
- package/dist/hitl/approvalDelivery.js +193 -0
- package/dist/hitl/approvalResolution.d.ts +11 -0
- package/dist/hitl/approvalResolution.js +50 -11
- package/dist/hitl/askClassPair.d.ts +6 -0
- package/dist/hitl/askClassPair.js +30 -3
- package/dist/hitl/askParkAutoReopenBlock.d.ts +30 -0
- package/dist/hitl/askParkAutoReopenBlock.js +117 -0
- package/dist/hitl/askParkRowRouting.js +4 -1
- package/dist/hitl/attributionLadder.d.ts +42 -3
- package/dist/hitl/attributionLadder.js +79 -8
- package/dist/hitl/automaticAnswerVerdict.d.ts +6 -1
- package/dist/hitl/automaticAnswerVerdict.js +46 -11
- package/dist/hitl/crashConverged.js +2 -2
- package/dist/hitl/decisionConflict.d.ts +6 -2
- package/dist/hitl/decisionConflict.js +24 -9
- package/dist/hitl/decisionRefusal.d.ts +20 -10
- package/dist/hitl/decisionRefusal.js +99 -54
- package/dist/hitl/decisionSend.d.ts +3 -0
- package/dist/hitl/decisionSend.js +87 -103
- package/dist/hitl/frameRouter.d.ts +1 -0
- package/dist/hitl/frameRouter.js +9 -2
- package/dist/hitl/hitlBridge.d.ts +18 -6
- package/dist/hitl/hitlBridge.js +41 -37
- package/dist/hitl/livePendingAsk.js +4 -3
- package/dist/hitl/noAllowCause.js +1 -1
- package/dist/hitl/parkResolver.js +3 -2
- package/dist/hitl/persistedRulesWire.js +1 -0
- package/dist/hitl/planReviewWire.d.ts +4 -0
- package/dist/hitl/planReviewWire.js +59 -30
- package/dist/hitl/resumeRunningCard.d.ts +3 -2
- package/dist/hitl/resumeRunningCard.js +17 -11
- package/dist/hitl/sessionPolicyDeliverable.d.ts +5 -2
- package/dist/hitl/sessionPolicyDeliverable.js +62 -29
- package/dist/hitl/sessionPolicyWire.d.ts +13 -3
- package/dist/hitl/sessionPolicyWire.js +81 -16
- package/dist/hitl/standingRows.js +1 -1
- package/dist/hitl/toolApprovalWire.d.ts +9 -10
- package/dist/hitl/toolApprovalWire.js +72 -54
- package/dist/hookMatcherVerdict.d.ts +2 -0
- package/dist/hookMatcherVerdict.js +12 -0
- package/dist/hooksCompactTransition.d.ts +19 -0
- package/dist/hooksCompactTransition.js +41 -0
- package/dist/hooksWireCaps.d.ts +1 -1
- package/dist/hooksWireCaps.js +202 -203
- package/dist/host.d.ts +1 -14
- package/dist/host.js +0 -8
- package/dist/hostCallbackGuard.d.ts +1 -0
- package/dist/hostCallbackGuard.js +1 -1
- package/dist/hostSettingsSource.d.ts +172 -0
- package/dist/hostSettingsSource.js +675 -0
- package/dist/hostTurnSettings.d.ts +73 -17
- package/dist/hostTurnSettings.js +594 -97
- package/dist/httpHookPolicy.d.ts +37 -0
- package/dist/httpHookPolicy.js +176 -0
- package/dist/humanTurn.d.ts +2 -1
- package/dist/humanTurn.js +37 -7
- package/dist/humanTurnRead.js +4 -3
- package/dist/humanTurnSentences.d.ts +10 -0
- package/dist/humanTurnSentences.js +74 -0
- package/dist/i18n/messages.en.d.ts +184 -2
- package/dist/i18n/messages.en.js +187 -5
- package/dist/i18n/messages.zh.js +197 -5
- package/dist/i18n/translate.js +3 -3
- package/dist/index.d.ts +69 -15
- package/dist/index.js +45 -13
- package/dist/inheritEnvCapability.d.ts +3 -1
- package/dist/inheritEnvCapability.js +31 -17
- package/dist/inheritEnvWire.d.ts +2 -1
- package/dist/inheritEnvWire.js +11 -5
- package/dist/interactiveToolsWire.d.ts +4 -2
- package/dist/interactiveToolsWire.js +5 -5
- package/dist/jsonFaithful.d.ts +20 -0
- package/dist/jsonFaithful.js +152 -0
- package/dist/limitsWire.d.ts +7 -2
- package/dist/limitsWire.js +19 -13
- package/dist/liveInitToolFace.d.ts +6 -1
- package/dist/liveInitToolFace.js +5 -3
- package/dist/liveModelCatalog.d.ts +22 -0
- package/dist/liveModelCatalog.js +132 -18
- package/dist/mcpPanel.js +1 -1
- package/dist/mcpProbeCapability.js +2 -2
- package/dist/mcpStatusSupersetKeys.d.ts +24 -0
- package/dist/mcpStatusSupersetKeys.js +45 -0
- package/dist/mcpToolToggles.js +2 -1
- package/dist/mcpWireCaps.d.ts +39 -1
- package/dist/mcpWireCaps.js +254 -50
- package/dist/memoryComplianceCapability.js +2 -2
- package/dist/memoryOriginCapability.js +2 -2
- package/dist/model/catalogDefault.d.ts +24 -0
- package/dist/model/catalogDefault.js +4 -0
- package/dist/model/liveCatalogShape.js +5 -4
- package/dist/model/modelsPolicy.js +4 -3
- package/dist/model/onboardJudgement.d.ts +1 -0
- package/dist/model/onboardJudgement.js +1 -1
- package/dist/model/subagentModelWord.js +2 -2
- package/dist/modelCapabilityProbe.js +6 -6
- package/dist/modelIdentityResolvability.d.ts +10 -1
- package/dist/modelIdentityResolvability.js +62 -39
- package/dist/modsKernelIdentity.d.ts +10 -0
- package/dist/modsKernelIdentity.js +103 -0
- package/dist/modsKernelTransit.d.ts +8 -0
- package/dist/modsKernelTransit.js +6 -0
- package/dist/notifications.d.ts +30 -12
- package/dist/notifications.js +241 -53
- package/dist/outputStyleSeatCapability.js +2 -2
- package/dist/ownKey.d.ts +11 -0
- package/dist/ownKey.js +164 -3
- package/dist/panelReduce.js +1 -1
- package/dist/peerFrames.d.ts +1 -1
- package/dist/peerFrames.js +6 -2
- package/dist/peerLaneCapability.js +2 -2
- package/dist/permissionModesCapability.js +4 -4
- package/dist/permissionRuleIssue.js +2 -0
- package/dist/permissionRulesWriteCapability.js +2 -2
- package/dist/permissionsAllowGrantCapability.js +2 -2
- package/dist/permissionsDeclaration.d.ts +43 -4
- package/dist/permissionsDeclaration.js +102 -35
- package/dist/pluginHooksWire.d.ts +20 -4
- package/dist/pluginHooksWire.js +92 -53
- package/dist/prepareRefusal.d.ts +3 -2
- package/dist/prepareRefusal.js +27 -9
- package/dist/printInitToolFace.js +2 -2
- package/dist/printModelStatus.js +1 -1
- package/dist/projectMemory.d.ts +32 -0
- package/dist/projectMemory.js +70 -0
- package/dist/promptBlockedCopy.d.ts +2 -1
- package/dist/promptBlockedCopy.js +2 -1
- package/dist/promptDelivery.d.ts +23 -3
- package/dist/promptDelivery.js +169 -30
- package/dist/providerRejection.d.ts +19 -1
- package/dist/providerRejection.js +75 -4
- package/dist/queuedDelivery.d.ts +48 -0
- package/dist/queuedDelivery.js +233 -0
- package/dist/reattachWindow.d.ts +94 -0
- package/dist/reattachWindow.js +127 -0
- package/dist/request/printNotification.d.ts +1 -1
- package/dist/request/printNotification.js +5 -1
- package/dist/request/submissionIdentity.d.ts +37 -0
- package/dist/request/submissionIdentity.js +65 -0
- package/dist/request/taskRequest.d.ts +12 -4
- package/dist/request/taskRequest.js +221 -152
- package/dist/resultFrameKeys.d.ts +1 -0
- package/dist/resultFrameKeys.js +4 -1
- package/dist/retryStatus.d.ts +8 -0
- package/dist/retryStatus.js +57 -9
- package/dist/rewindArchiveCapability.js +2 -2
- package/dist/rewindEngineAction.d.ts +2 -0
- package/dist/rewindEngineAction.js +23 -1
- package/dist/rowKind.d.ts +36 -0
- package/dist/rowKind.js +97 -0
- package/dist/ruleCompileVerdict.d.ts +18 -0
- package/dist/ruleCompileVerdict.js +67 -2
- package/dist/ruleReadings.d.ts +58 -0
- package/dist/ruleReadings.js +132 -0
- package/dist/ruleRefusalSentence.d.ts +4 -0
- package/dist/ruleRefusalSentence.js +9 -3
- package/dist/runCancelContext.d.ts +0 -1
- package/dist/runCancelContext.js +1 -2
- package/dist/runTerminal.d.ts +5 -0
- package/dist/runTerminal.js +52 -17
- package/dist/sandboxWire.d.ts +1 -1
- package/dist/sandboxWire.js +4 -6
- package/dist/scenarioRefusal.js +1 -1
- package/dist/scenarioSkills.d.ts +20 -0
- package/dist/scenarioSkills.js +72 -0
- package/dist/scenarioWire.d.ts +5 -2
- package/dist/scenarioWire.js +9 -9
- package/dist/sealedKeyCapability.js +2 -2
- package/dist/seam.d.ts +2 -0
- package/dist/seam.js +2 -2
- package/dist/seatContract.d.ts +46 -1
- package/dist/seatContract.js +49 -19
- package/dist/selfOrchestrationDenial.js +1 -1
- package/dist/sessionPolicyCapability.js +2 -2
- package/dist/sessionRulesChildrenReadLive.d.ts +6 -0
- package/dist/sessionRulesChildrenReadLive.js +5 -0
- package/dist/sessionRulesNamespaceFormsCapability.d.ts +12 -0
- package/dist/sessionRulesNamespaceFormsCapability.js +29 -0
- package/dist/sessionSyncFileHistoryCapability.js +2 -2
- package/dist/settingsCredentialKeyPaths.js +60 -5
- package/dist/settingsHooksSalvage.d.ts +1 -0
- package/dist/settingsHooksSalvage.js +7 -1
- package/dist/settingsLayerAdmission.d.ts +4 -0
- package/dist/settingsLayerAdmission.js +16 -0
- package/dist/skillToolListsCapability.js +6 -5
- package/dist/skillsWireCaps.d.ts +14 -0
- package/dist/skillsWireCaps.js +47 -16
- package/dist/slashCommandGate.d.ts +24 -0
- package/dist/slashCommandGate.js +74 -0
- package/dist/slashCommandTable.d.ts +14 -0
- package/dist/slashCommandTable.js +99 -0
- package/dist/sqlEngineCapability.js +2 -2
- package/dist/steerPriorityCapability.js +2 -2
- package/dist/storePostureCapability.js +2 -2
- package/dist/subagent/agentStateDetail.js +1 -1
- package/dist/subagent/engineDelegatedPrompt.d.ts +9 -0
- package/dist/subagent/engineDelegatedPrompt.js +38 -7
- package/dist/subagent/engineRowStopGate.js +2 -2
- package/dist/subagent/engineSubagentResume.js +3 -3
- package/dist/subagent/engineTaskHandleWire.d.ts +1 -0
- package/dist/subagent/engineTaskHandleWire.js +10 -0
- package/dist/submitFailure.d.ts +8 -0
- package/dist/submitFailure.js +17 -0
- package/dist/supportFloor.d.ts +1 -0
- package/dist/supportFloor.js +7 -0
- package/dist/terminationIntent.d.ts +55 -0
- package/dist/terminationIntent.js +352 -0
- package/dist/toolHistoryMismatch.d.ts +8 -0
- package/dist/toolHistoryMismatch.js +37 -6
- package/dist/toolResult.d.ts +13 -3
- package/dist/toolResult.js +158 -9
- package/dist/toolResultContent.d.ts +13 -0
- package/dist/toolResultContent.js +82 -7
- package/dist/toolRoster.d.ts +18 -0
- package/dist/toolRoster.js +64 -0
- package/dist/turnFailurePresentation.js +27 -90
- package/dist/usageLimitAutoResume.d.ts +74 -0
- package/dist/usageLimitAutoResume.js +227 -0
- package/dist/userAttachmentEnvelope.js +1 -1
- package/dist/userAttachmentSeat.js +5 -5
- package/dist/userInvokedSkillsCapability.js +2 -2
- package/dist/webSearchBackendCapability.js +2 -2
- package/dist/wireErrorTriage.js +99 -50
- package/dist/wireFailureShape.d.ts +25 -1
- package/dist/wireFailureShape.js +92 -5
- package/dist/wireRefusalCopy.d.ts +24 -1
- package/dist/wireRefusalCopy.js +253 -32
- package/dist/wiringFleetDoctor.d.ts +3 -0
- package/dist/wiringFleetDoctor.js +21 -0
- package/dist/workflow.d.ts +2 -1
- package/dist/workflow.js +38 -1
- package/dist/workflowClient.d.ts +2 -7
- package/dist/workflowsJournalCapability.js +2 -2
- package/dist/writeProtectionCapability.js +2 -2
- package/docs/INTEGRATION-CLIENTS.md +607 -181
- package/package.json +14 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWithHttpScheme) => {
|
|
1
|
+
export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWithHttpScheme, echoCallerText) => {
|
|
2
2
|
function describeValueShape(v) {
|
|
3
3
|
if (v === undefined)
|
|
4
4
|
return "nothing (the key is absent)";
|
|
@@ -18,12 +18,6 @@ export const SETTINGS_MCP_REQUEST_ENTRY_CLOSURE = (MCP_CONTENT_ORIGINS, startsWi
|
|
|
18
18
|
function isStringArray(v) {
|
|
19
19
|
return Array.isArray(v) && v.every((a) => typeof a === "string");
|
|
20
20
|
}
|
|
21
|
-
const CONTROL_AND_BIDI_STRIP_RE = /[\u0000-\u001f\u007f\u061c\u200e\u200f\u202a-\u202e\u2066-\u2069]/g;
|
|
22
|
-
const CALLER_TEXT_ECHO_MAX_CHARS = 64;
|
|
23
|
-
function echoCallerText(text) {
|
|
24
|
-
const clean = text.replace(CONTROL_AND_BIDI_STRIP_RE, "");
|
|
25
|
-
return clean.length > CALLER_TEXT_ECHO_MAX_CHARS ? `${clean.slice(0, CALLER_TEXT_ECHO_MAX_CHARS)}…` : clean;
|
|
26
|
-
}
|
|
27
21
|
function quotedCallerText(text) {
|
|
28
22
|
return `"${echoCallerText(text)}"`;
|
|
29
23
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_SAFETY_MERGE_CLOSURE: (MIN_TRUST_WORDS: readonly ["local", "session", "project", "global", "managed", "task"]) => any;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export const SETTINGS_SAFETY_MERGE_CLOSURE = (MIN_TRUST_WORDS) => {
|
|
2
|
+
function trustRank(layer) {
|
|
3
|
+
switch (layer) {
|
|
4
|
+
case "managed": return 6;
|
|
5
|
+
case "global": return 5;
|
|
6
|
+
case "project": return 4;
|
|
7
|
+
case "local": return 3;
|
|
8
|
+
case "session": return 2;
|
|
9
|
+
case "task": return 1;
|
|
10
|
+
default: {
|
|
11
|
+
const unknown = layer;
|
|
12
|
+
throw new RangeError(`MinTrust: unknown trust word '${String(unknown)}' (words: ${MIN_TRUST_WORDS.join(", ")})`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function isAtLeast(layer, minTrust) {
|
|
17
|
+
return trustRank(layer) >= trustRank(minTrust);
|
|
18
|
+
}
|
|
19
|
+
const SAFETY_MERGE_SPEC = {
|
|
20
|
+
permissions: {
|
|
21
|
+
mergeShape: "denyFirst", minTrust: "global", tighten: { rule: "policyDenyWins" }, enforcement: "gate", fail: "closed",
|
|
22
|
+
seam: "toolPolicy + deny-narrowing (SessionPolicyStore)", coreAxis: "permissionDecision",
|
|
23
|
+
members: {
|
|
24
|
+
allow: { direction: "loosen", minTrust: "global" },
|
|
25
|
+
deny: { direction: "tighten", minTrust: "local" },
|
|
26
|
+
ask: { direction: "tighten", minTrust: "local" },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
permissionMode: { mergeShape: "replace", minTrust: "global", tighten: { rule: "enumRank", order: ["bypassPermissions", "auto", "acceptEdits", "default", "dontAsk", "plan"] }, enforcement: "gate", fail: "closed", seam: "derive → toolPolicy / onAsk / handsReadOnly (§6.4); bypass = launch-flag only; the kill-switches are the killSwitches row" },
|
|
30
|
+
handsReadOnly: { mergeShape: "replace", minTrust: "global", tighten: { rule: "boolStricter", strict: true }, enforcement: "gate", fail: "closed", seam: "handsReadOnly" },
|
|
31
|
+
shellGate: { mergeShape: "replace", minTrust: "global", tighten: { rule: "enumRank", order: ["always"] }, enforcement: "gate", fail: "closed", seam: "shellGate", coreAxis: "shellGate" },
|
|
32
|
+
approver: { mergeShape: "replace", minTrust: "global", tighten: { rule: "none" }, enforcement: "gate", fail: "closed", seam: "onAsk (conflict → reject)" },
|
|
33
|
+
sandboxNetwork: {
|
|
34
|
+
mergeShape: "denyFirst", minTrust: "global", tighten: { rule: "setNarrower" }, enforcement: "gate", fail: "closed",
|
|
35
|
+
seam: "ExecutionEnv (fs+net) + sensitive-path", coreAxis: "egress",
|
|
36
|
+
members: {
|
|
37
|
+
enabled: { direction: "tighten", minTrust: "global", boolPole: { strict: true, minTrust: "local" } },
|
|
38
|
+
allowUnsandboxedCommands: { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
39
|
+
autoAllowBashIfSandboxed: { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
40
|
+
enableWeakerNestedSandbox: { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
41
|
+
enableWeakerNetworkIsolation: { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
42
|
+
"network.allowManagedDomainsOnly": { direction: "tighten", minTrust: "global", boolPole: { strict: true, minTrust: "local" } },
|
|
43
|
+
"network.allowAllUnixSockets": { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
44
|
+
"network.allowLocalBinding": { direction: "tighten", minTrust: "global", boolPole: { strict: false, minTrust: "local" } },
|
|
45
|
+
"filesystem.allowManagedReadPathsOnly": { direction: "tighten", minTrust: "global", boolPole: { strict: true, minTrust: "local" } },
|
|
46
|
+
"filesystem.denyWrite": { direction: "tighten", minTrust: "local" },
|
|
47
|
+
"filesystem.denyRead": { direction: "tighten", minTrust: "local" },
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
hooks: { mergeShape: "runAll", minTrust: "project", tighten: { rule: "none" }, enforcement: "gate", fail: "closed", seam: "hooks (single source or adapter-composed)" },
|
|
51
|
+
mcpServers: { mergeShape: "overrideByName", minTrust: "project", tighten: { rule: "none" }, enforcement: "resolver", fail: "open", seam: "spec.mcp + allowTools" },
|
|
52
|
+
rulesInstructions: { mergeShape: "concat", minTrust: "project", tighten: { rule: "none" }, enforcement: "resolver", fail: "open", seam: "appendSystemPrompt / memory (GLOBAL→PROJECT→SESSION)" },
|
|
53
|
+
model: { mergeShape: "replace", minTrust: "session", tighten: { rule: "none" }, enforcement: "client", fail: "open", seam: "RoleSpec / TaskSpec.{model,thinking}" },
|
|
54
|
+
env: { mergeShape: "concat", minTrust: "project", tighten: { rule: "none" }, enforcement: "resolver", fail: "open", seam: "NodeExecutionEnv.shellEnv (later layer overrides same name)" },
|
|
55
|
+
envSecret: { mergeShape: "replace", minTrust: "global", tighten: { rule: "none" }, enforcement: "resolver", fail: "closed", seam: "§7 secret-ref resolution" },
|
|
56
|
+
memoryScopes: { mergeShape: "concat", minTrust: "global", tighten: { rule: "none" }, enforcement: "client", fail: "open", seam: "MemoryStore" },
|
|
57
|
+
autoCompaction: { mergeShape: "replace", minTrust: "session", tighten: { rule: "none" }, enforcement: "client", fail: "open", seam: "compaction config" },
|
|
58
|
+
ui: { mergeShape: "replace", minTrust: "local", tighten: { rule: "none" }, enforcement: "client", fail: "open", seam: "shell-only (theme/keybindings/statusLine) — never touches the engine" },
|
|
59
|
+
org: { mergeShape: "replace", minTrust: "managed", tighten: { rule: "none" }, enforcement: "server", fail: "closed", seam: "web-admin → governanceBaseline (SSO/SCIM/audit/budget, TOB-only)" },
|
|
60
|
+
httpHookAllowlists: { mergeShape: "denyFirst", minTrust: "global", tighten: { rule: "setNarrower" }, enforcement: "resolver", fail: "closed", seam: "http hook URL / header-env allowlists (httpHookUrlVerdict / httpHookEnvVarsAllowed)" },
|
|
61
|
+
killSwitches: {
|
|
62
|
+
mergeShape: "replace", minTrust: "global", tighten: { rule: "boolStricter", strict: true }, enforcement: "gate", fail: "closed",
|
|
63
|
+
seam: "permission-mode kill-switches (a switch ON removes bypassPermissions / auto from every layer's mode choice)",
|
|
64
|
+
members: {
|
|
65
|
+
disableBypassPermissionsMode: { direction: "tighten", minTrust: "global", boolPole: { strict: true, minTrust: "local" } },
|
|
66
|
+
disableAutoMode: { direction: "tighten", minTrust: "global", boolPole: { strict: true, minTrust: "local" } },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
function categorySpec(category) {
|
|
71
|
+
if (!Object.hasOwn(SAFETY_MERGE_SPEC, category)) {
|
|
72
|
+
throw new RangeError(`SAFETY_MERGE_SPEC: unknown category '${category}' (categories: ${Object.keys(SAFETY_MERGE_SPEC).join(", ")})`);
|
|
73
|
+
}
|
|
74
|
+
return SAFETY_MERGE_SPEC[category];
|
|
75
|
+
}
|
|
76
|
+
function resolveMemberAdmission(spec, member, categoryLabel = "(unnamed category)", value) {
|
|
77
|
+
if (spec.members === undefined) {
|
|
78
|
+
throw new RangeError(`SAFETY_MERGE_SPEC: category '${categoryLabel}' has no member-level admission — its minTrust applies to the whole key`);
|
|
79
|
+
}
|
|
80
|
+
if (!Object.hasOwn(spec.members, member)) {
|
|
81
|
+
throw new RangeError(`SAFETY_MERGE_SPEC: unknown member '${member}' of category '${categoryLabel}' (members: ${Object.keys(spec.members).join(", ")})`);
|
|
82
|
+
}
|
|
83
|
+
const row = spec.members[member];
|
|
84
|
+
const rowFloor = row.minTrust ?? spec.minTrust;
|
|
85
|
+
if (row.boolPole !== undefined) {
|
|
86
|
+
const floor = value === row.boolPole.strict ? row.boolPole.minTrust : rowFloor;
|
|
87
|
+
return { direction: row.direction, minTrust: floor, boolPole: row.boolPole };
|
|
88
|
+
}
|
|
89
|
+
return { direction: row.direction, minTrust: rowFloor };
|
|
90
|
+
}
|
|
91
|
+
function memberAdmission(category, member, value) {
|
|
92
|
+
return resolveMemberAdmission(categorySpec(category), member, category, value);
|
|
93
|
+
}
|
|
94
|
+
return { isAtLeast, memberAdmission, SAFETY_MERGE_SPEC };
|
|
95
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_LAYER_SOURCES_CLOSURE: (SAFETY_MERGE_SPEC: object, isAtLeast: (layer: string, minTrust: string) => boolean, memberAdmission: (category: string, member: string) => object) => any;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const SETTINGS_LAYER_SOURCES_CLOSURE = (SAFETY_MERGE_SPEC, isAtLeast, memberAdmission) => {
|
|
2
|
+
const SETTINGS_SOURCES = ["userSettings", "projectSettings", "localSettings", "flagSettings", "policySettings", "foreignProjectSettings"];
|
|
3
|
+
const SETTINGS_SOURCE_CONTRACT = {
|
|
4
|
+
userSettings: { trust: "global", repoControllable: false },
|
|
5
|
+
projectSettings: { trust: "project", repoControllable: true },
|
|
6
|
+
localSettings: { trust: "project", repoControllable: true },
|
|
7
|
+
flagSettings: { trust: "global", repoControllable: false },
|
|
8
|
+
policySettings: { trust: "managed", repoControllable: false },
|
|
9
|
+
foreignProjectSettings: { trust: "project", repoControllable: true, tightenOnly: true },
|
|
10
|
+
};
|
|
11
|
+
function settingsSourceContract(source) {
|
|
12
|
+
if (!Object.hasOwn(SETTINGS_SOURCE_CONTRACT, source)) {
|
|
13
|
+
throw new RangeError(`SETTINGS_SOURCE_CONTRACT: unknown settings source '${String(source)}' (sources: ${SETTINGS_SOURCES.join(", ")})`);
|
|
14
|
+
}
|
|
15
|
+
return SETTINGS_SOURCE_CONTRACT[source];
|
|
16
|
+
}
|
|
17
|
+
const WORKSPACE_TRUST_STATES = ["accepted", "declined", "no_trust_step"];
|
|
18
|
+
function layerAdmission(source, workspace, category, member, value) {
|
|
19
|
+
const layer = settingsSourceContract(source);
|
|
20
|
+
const tightenOnlyLayer = readsTightenOnly(layer, workspace);
|
|
21
|
+
let floor;
|
|
22
|
+
let direction;
|
|
23
|
+
if (member === undefined) {
|
|
24
|
+
if (!Object.hasOwn(SAFETY_MERGE_SPEC, category)) {
|
|
25
|
+
throw new RangeError(`SAFETY_MERGE_SPEC: unknown category '${String(category)}' (categories: ${Object.keys(SAFETY_MERGE_SPEC).join(", ")})`);
|
|
26
|
+
}
|
|
27
|
+
floor = SAFETY_MERGE_SPEC[category].minTrust;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const resolved = memberAdmission(category, member, value);
|
|
31
|
+
floor = resolved.minTrust;
|
|
32
|
+
direction = resolved.direction;
|
|
33
|
+
}
|
|
34
|
+
if (!isAtLeast(layer.trust, floor))
|
|
35
|
+
return "below_trust_floor";
|
|
36
|
+
if (direction === "tighten" || !tightenOnlyLayer)
|
|
37
|
+
return "admitted";
|
|
38
|
+
return layer.tightenOnly === true ? "tighten_only" : "trust_withheld";
|
|
39
|
+
}
|
|
40
|
+
function readsTightenOnly(layer, workspace) {
|
|
41
|
+
const accepted = workspaceAccepted(workspace);
|
|
42
|
+
return layer.tightenOnly === true || (layer.repoControllable && !accepted);
|
|
43
|
+
}
|
|
44
|
+
function workspaceAccepted(workspace) {
|
|
45
|
+
switch (workspace) {
|
|
46
|
+
case "accepted":
|
|
47
|
+
return true;
|
|
48
|
+
case "declined":
|
|
49
|
+
case "no_trust_step":
|
|
50
|
+
return false;
|
|
51
|
+
default: {
|
|
52
|
+
const unknown = workspace;
|
|
53
|
+
throw new RangeError(`WORKSPACE_TRUST_STATES: unknown workspace trust reading '${String(unknown)}' (readings: ${WORKSPACE_TRUST_STATES.join(", ")})`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return { layerAdmission };
|
|
58
|
+
};
|
|
@@ -11,3 +11,5 @@ export declare const SETTINGS_MODEL_API_WORDS: readonly ["openai-completions", "
|
|
|
11
11
|
export declare const SETTINGS_TOOL_NAME_MATCHER_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure"];
|
|
12
12
|
export declare const SETTINGS_UI_LANGUAGE_VALUES: readonly ["en", "zh"];
|
|
13
13
|
export declare const SETTINGS_MCP_CONTENT_ORIGINS: readonly ["local", "execution", "external"];
|
|
14
|
+
export declare const SETTINGS_MIN_TRUST_WORDS: readonly ["local", "session", "project", "global", "managed", "task"];
|
|
15
|
+
export declare const SETTINGS_WORKSPACE_TRUST_STATES: readonly ["accepted", "declined", "no_trust_step"];
|
|
@@ -50,3 +50,16 @@ export const SETTINGS_MCP_CONTENT_ORIGINS = Object.freeze([
|
|
|
50
50
|
"execution",
|
|
51
51
|
"external",
|
|
52
52
|
]);
|
|
53
|
+
export const SETTINGS_MIN_TRUST_WORDS = Object.freeze([
|
|
54
|
+
"local",
|
|
55
|
+
"session",
|
|
56
|
+
"project",
|
|
57
|
+
"global",
|
|
58
|
+
"managed",
|
|
59
|
+
"task",
|
|
60
|
+
]);
|
|
61
|
+
export const SETTINGS_WORKSPACE_TRUST_STATES = Object.freeze([
|
|
62
|
+
"accepted",
|
|
63
|
+
"declined",
|
|
64
|
+
"no_trust_step",
|
|
65
|
+
]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SETTINGS_URL_ALLOW_PATTERN_MATCHES_CLOSURE: () => (url: string, pattern: string) => boolean;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export const SETTINGS_URL_ALLOW_PATTERN_MATCHES_CLOSURE = () => {
|
|
2
|
+
const SPECIAL_SCHEMES = new Set(["http:", "https:", "ws:", "wss:", "ftp:", "file:"]);
|
|
3
|
+
const HOST_ROUTED_SCHEMES = new Set(["http:", "https:", "ws:", "wss:"]);
|
|
4
|
+
const OTHER_DEFAULT_PORT_SCHEME = { "http:": "https", "https:": "http", "ws:": "wss", "wss:": "ws", "ftp:": "http" };
|
|
5
|
+
const SOCKET_PATH_SCHEME = "ws+unix:";
|
|
6
|
+
function parseUrl(s) {
|
|
7
|
+
try {
|
|
8
|
+
return new URL(s);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function occurrences(haystack, needle) {
|
|
15
|
+
return haystack.split(needle).length - 1;
|
|
16
|
+
}
|
|
17
|
+
function parserReadings(s) {
|
|
18
|
+
const fold = (x) => x.replace(/\p{Default_Ignorable_Code_Point}/gu, "").normalize("NFKC").toLowerCase().normalize("NFKC");
|
|
19
|
+
const seen = asParserSees(s);
|
|
20
|
+
const decoded = seen.replace(/(?:%[0-9a-f]{2})+/gi, (run) => {
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(run);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return run;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return [fold(seen), fold(decoded)];
|
|
29
|
+
}
|
|
30
|
+
function freeToken(stem, avoid, build) {
|
|
31
|
+
const taken = new Set();
|
|
32
|
+
const shape = new RegExp(`zz${stem}(\\d+)qq`, "g");
|
|
33
|
+
for (const reading of parserReadings(avoid))
|
|
34
|
+
for (const m of reading.matchAll(shape))
|
|
35
|
+
taken.add(m[1]);
|
|
36
|
+
for (let i = 0;; i++) {
|
|
37
|
+
if (taken.has(String(i)))
|
|
38
|
+
continue;
|
|
39
|
+
const token = `zz${stem}${i}qq`;
|
|
40
|
+
const { built, inserted } = build(token);
|
|
41
|
+
if (parserReadings(built).every((r) => occurrences(r, token) === inserted))
|
|
42
|
+
return { token, built };
|
|
43
|
+
taken.add(String(i));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function asParserSees(s) {
|
|
47
|
+
let start = 0;
|
|
48
|
+
let end = s.length;
|
|
49
|
+
while (start < end && s.charCodeAt(start) <= 0x20)
|
|
50
|
+
start++;
|
|
51
|
+
while (end > start && s.charCodeAt(end - 1) <= 0x20)
|
|
52
|
+
end--;
|
|
53
|
+
return s.slice(start, end).replace(/[\t\n\r]/g, "");
|
|
54
|
+
}
|
|
55
|
+
function defaultPortWritten(marked, pat) {
|
|
56
|
+
if (pat.port !== "")
|
|
57
|
+
return false;
|
|
58
|
+
const other = OTHER_DEFAULT_PORT_SCHEME[pat.protocol];
|
|
59
|
+
if (other === undefined)
|
|
60
|
+
return false;
|
|
61
|
+
const seen = asParserSees(marked);
|
|
62
|
+
const colon = seen.indexOf(":");
|
|
63
|
+
if (colon === -1)
|
|
64
|
+
return false;
|
|
65
|
+
const alt = parseUrl(other + seen.slice(colon));
|
|
66
|
+
return alt !== undefined && alt.port !== "";
|
|
67
|
+
}
|
|
68
|
+
function namesScheme(pattern, protocol) {
|
|
69
|
+
return asParserSees(pattern).toLowerCase().startsWith(protocol);
|
|
70
|
+
}
|
|
71
|
+
function socketPart(path) {
|
|
72
|
+
const i = path.indexOf(":");
|
|
73
|
+
return i === -1 ? path : path.slice(0, i);
|
|
74
|
+
}
|
|
75
|
+
function globMatches(pattern, value) {
|
|
76
|
+
const parts = pattern.split("*");
|
|
77
|
+
const head = parts[0] ?? "";
|
|
78
|
+
if (parts.length === 1)
|
|
79
|
+
return head === value;
|
|
80
|
+
const tail = parts[parts.length - 1] ?? "";
|
|
81
|
+
const end = value.length - tail.length;
|
|
82
|
+
if (end < head.length || !value.startsWith(head) || !value.endsWith(tail))
|
|
83
|
+
return false;
|
|
84
|
+
let at = head.length;
|
|
85
|
+
for (const mid of parts.slice(1, -1)) {
|
|
86
|
+
if (mid === "")
|
|
87
|
+
continue;
|
|
88
|
+
const found = value.indexOf(mid, at);
|
|
89
|
+
if (found === -1 || found + mid.length > end)
|
|
90
|
+
return false;
|
|
91
|
+
at = found + mid.length;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function nextSeparator(s, separators, from) {
|
|
96
|
+
let i = from;
|
|
97
|
+
while (i < s.length && !separators.includes(s.charAt(i)))
|
|
98
|
+
i++;
|
|
99
|
+
return i;
|
|
100
|
+
}
|
|
101
|
+
function segmentedGlobMatches(pattern, value, separators) {
|
|
102
|
+
let p = 0;
|
|
103
|
+
let v = 0;
|
|
104
|
+
for (;;) {
|
|
105
|
+
const pe = nextSeparator(pattern, separators, p);
|
|
106
|
+
const ve = nextSeparator(value, separators, v);
|
|
107
|
+
if (pattern.charAt(pe) !== value.charAt(ve) || !globMatches(pattern.slice(p, pe), value.slice(v, ve)))
|
|
108
|
+
return false;
|
|
109
|
+
if (pe === pattern.length)
|
|
110
|
+
return true;
|
|
111
|
+
p = pe + 1;
|
|
112
|
+
v = ve + 1;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function componentMatches(url, pattern, reading) {
|
|
116
|
+
if (pattern === "*")
|
|
117
|
+
return true;
|
|
118
|
+
const target = parseUrl(url);
|
|
119
|
+
if (target === undefined)
|
|
120
|
+
return false;
|
|
121
|
+
const strict = reading === "allow";
|
|
122
|
+
if (strict && !HOST_ROUTED_SCHEMES.has(target.protocol) && !namesScheme(pattern, target.protocol))
|
|
123
|
+
return false;
|
|
124
|
+
const socketTarget = strict && target.protocol === SOCKET_PATH_SCHEME;
|
|
125
|
+
if (socketTarget) {
|
|
126
|
+
const socket = socketPart(target.pathname + target.search);
|
|
127
|
+
if (socket === "" || socket.split("/").includes(".."))
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
const { token: WILDCARD, built: starred } = freeToken("wildcard", `${pattern}\n${url}`, (t) => ({ built: pattern.replaceAll("*", t), inserted: occurrences(pattern, "*") }));
|
|
131
|
+
const { token: SHIELD, built: marked } = freeToken("punycode", `${starred}\n${url}`, (t) => {
|
|
132
|
+
let inserted = 0;
|
|
133
|
+
const built = starred.replace(/[a-z0-9-]+/gi, (run) => {
|
|
134
|
+
if (!/^xn--/i.test(run) || !run.includes(WILDCARD))
|
|
135
|
+
return run;
|
|
136
|
+
inserted++;
|
|
137
|
+
return t + run;
|
|
138
|
+
});
|
|
139
|
+
return { built, inserted };
|
|
140
|
+
});
|
|
141
|
+
const unshield = (s) => s.replaceAll(SHIELD, "");
|
|
142
|
+
let portAny = false;
|
|
143
|
+
let pat = parseUrl(marked);
|
|
144
|
+
if (pat === undefined) {
|
|
145
|
+
const zeroPort = marked.replace(new RegExp(`:${WILDCARD}(?=[/?#]|$)`), ":0");
|
|
146
|
+
if (zeroPort !== marked) {
|
|
147
|
+
pat = parseUrl(zeroPort);
|
|
148
|
+
portAny = pat !== undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (pat !== undefined && (occurrences(pat.href, WILDCARD) > occurrences(pattern, "*") || occurrences(pat.href, SHIELD) > occurrences(marked, SHIELD)))
|
|
152
|
+
pat = undefined;
|
|
153
|
+
if (pat === undefined || (SPECIAL_SCHEMES.has(pat.protocol) && pat.hostname.split(".").some((l) => l.startsWith("xn--") && l.includes(WILDCARD)))) {
|
|
154
|
+
return !strict && segmentedGlobMatches(pattern, `${target.protocol}//${target.host}${target.pathname}${target.search}`, "/");
|
|
155
|
+
}
|
|
156
|
+
if (pat.protocol !== `${WILDCARD}:` && pat.protocol !== target.protocol)
|
|
157
|
+
return false;
|
|
158
|
+
if (strict && unshield(pat.hostname).includes("*"))
|
|
159
|
+
return false;
|
|
160
|
+
const host = target.hostname.replace(/\.$/, "").toLowerCase();
|
|
161
|
+
const hostPattern = unshield(pat.hostname).replace(/\.$/, "").toLowerCase().replaceAll(WILDCARD, "*");
|
|
162
|
+
if (!globMatches(hostPattern, host))
|
|
163
|
+
return false;
|
|
164
|
+
if (pat.port === "" && pat.hostname.includes(WILDCARD) && !(strict && defaultPortWritten(marked, pat)))
|
|
165
|
+
portAny = true;
|
|
166
|
+
if (!portAny && pat.port !== target.port)
|
|
167
|
+
return false;
|
|
168
|
+
if ((pat.pathname === "/" || pat.pathname === "") && pat.search === "" && !marked.endsWith("/"))
|
|
169
|
+
return !socketTarget;
|
|
170
|
+
const pathPattern = unshield(pat.pathname + pat.search).replaceAll(WILDCARD, "*");
|
|
171
|
+
const targetPath = target.pathname + target.search;
|
|
172
|
+
if (!globMatches(pathPattern, targetPath))
|
|
173
|
+
return false;
|
|
174
|
+
if (!socketTarget)
|
|
175
|
+
return true;
|
|
176
|
+
const socketPattern = socketPart(pathPattern);
|
|
177
|
+
return !socketPattern.includes("*") && socketPattern === socketPart(targetPath);
|
|
178
|
+
}
|
|
179
|
+
function urlAllowPatternMatches(url, pattern) {
|
|
180
|
+
return componentMatches(url, pattern, "allow");
|
|
181
|
+
}
|
|
182
|
+
return urlAllowPatternMatches;
|
|
183
|
+
};
|
|
@@ -4,11 +4,27 @@ import { type EnvLike } from './hostEnv.js';
|
|
|
4
4
|
export declare const HEADLESS_PERMISSION_MODE_ENV = "SEMA_HEADLESS_PERMISSION_MODE";
|
|
5
5
|
export declare const HEADLESS_PERMISSION_WIRE_MODES: readonly PermissionMode[];
|
|
6
6
|
export declare function normalizeShellPermissionModeForWire(mode: string | undefined): string | undefined;
|
|
7
|
+
export interface HeadlessPermissionFlags {
|
|
8
|
+
readonly flag?: string;
|
|
9
|
+
readonly missing?: true;
|
|
10
|
+
readonly dangerouslySkipPermissions?: boolean;
|
|
11
|
+
}
|
|
7
12
|
export type HeadlessPermissionResolution = {
|
|
8
13
|
fields: PermissionModeField;
|
|
9
14
|
source: 'flag' | 'env' | 'default';
|
|
10
15
|
warning?: string;
|
|
11
16
|
};
|
|
12
|
-
export declare function
|
|
13
|
-
export
|
|
17
|
+
export declare function resolveHeadlessPermissionMode(flags: HeadlessPermissionFlags | undefined, env?: EnvLike, permissionModes?: PermissionModesReading): HeadlessPermissionResolution;
|
|
18
|
+
export type HeadlessPermissionModeKnob = {
|
|
19
|
+
readonly kind: 'absent';
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: 'word';
|
|
22
|
+
readonly word: PermissionMode;
|
|
23
|
+
} | {
|
|
24
|
+
readonly kind: 'invalid';
|
|
25
|
+
readonly raw: string;
|
|
26
|
+
readonly warning: string;
|
|
27
|
+
};
|
|
28
|
+
export declare function readHeadlessPermissionModeKnob(env?: EnvLike): HeadlessPermissionModeKnob;
|
|
29
|
+
export declare function headlessDontAskDowngradeWarning(permissionModes?: PermissionModesReading): string;
|
|
14
30
|
export declare function _resetHeadlessPermissionModeWireForTest(): void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { permissionModeField } from './permissionWireCaps.js';
|
|
2
2
|
import { permissionModeAdmitted } from './permissionModesCapability.js';
|
|
3
3
|
import { hostEnv } from './hostEnv.js';
|
|
4
|
-
import {
|
|
4
|
+
import { flagString, flagTrue } from './flagInput.js';
|
|
5
5
|
import { PERMISSION_MODE_WORDS } from './taskRequestWords.js';
|
|
6
6
|
import { readOwnDataValue } from './ownKey.js';
|
|
7
7
|
export const HEADLESS_PERMISSION_MODE_ENV = 'SEMA_HEADLESS_PERMISSION_MODE';
|
|
@@ -12,33 +12,29 @@ export function normalizeShellPermissionModeForWire(mode) {
|
|
|
12
12
|
return undefined;
|
|
13
13
|
return SHELL_INTERNAL_MODE_TO_WIRE.get(mode) ?? mode;
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
const flag =
|
|
17
|
-
if (flag
|
|
18
|
-
return flag
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (a === '--')
|
|
22
|
-
break;
|
|
23
|
-
if (a === '--dangerously-skip-permissions')
|
|
24
|
-
return 'bypassPermissions';
|
|
25
|
-
}
|
|
15
|
+
function permissionModeOfFlags(flags) {
|
|
16
|
+
const flag = flagString(flags, 'flag');
|
|
17
|
+
if (flag !== undefined)
|
|
18
|
+
return flag;
|
|
19
|
+
if (flagTrue(flags, 'dangerouslySkipPermissions'))
|
|
20
|
+
return 'bypassPermissions';
|
|
26
21
|
return undefined;
|
|
27
22
|
}
|
|
28
23
|
let warnedInvalidEnv = false;
|
|
29
|
-
export function resolveHeadlessPermissionMode(
|
|
30
|
-
const flagMode =
|
|
24
|
+
export function resolveHeadlessPermissionMode(flags, env = hostEnv(), permissionModes) {
|
|
25
|
+
const flagMode = permissionModeOfFlags(flags);
|
|
31
26
|
if (flagMode !== undefined) {
|
|
32
27
|
const snap = flagMode === 'dontAsk' ? dontAskSnapshot(permissionModes) : undefined;
|
|
33
28
|
const normalized = normalizeShellPermissionModeForWire(flagMode);
|
|
34
29
|
const projected = permissionModeField(normalized, { stampDefault: true, permissionModes: snap });
|
|
35
30
|
return { fields: projected.permissionMode !== undefined ? projected : permissionModeField('default', { stampDefault: true }), source: 'flag' };
|
|
36
31
|
}
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
32
|
+
const knob = readHeadlessPermissionModeKnob(env);
|
|
33
|
+
if (knob.kind === 'absent') {
|
|
39
34
|
return { fields: permissionModeField('default', { stampDefault: true }), source: 'default' };
|
|
40
35
|
}
|
|
41
|
-
if (
|
|
36
|
+
if (knob.kind === 'word') {
|
|
37
|
+
const raw = knob.word;
|
|
42
38
|
const snap = raw === 'dontAsk' ? dontAskSnapshot(permissionModes) : undefined;
|
|
43
39
|
const resolution = {
|
|
44
40
|
fields: permissionModeField(raw, { stampDefault: true, permissionModes: snap }),
|
|
@@ -46,7 +42,7 @@ export function resolveHeadlessPermissionMode(argv, env = hostEnv(), permissionM
|
|
|
46
42
|
};
|
|
47
43
|
if (raw === 'dontAsk' && resolution.fields.permissionMode !== 'dontAsk' && !warnedInvalidEnv) {
|
|
48
44
|
warnedInvalidEnv = true;
|
|
49
|
-
resolution.warning =
|
|
45
|
+
resolution.warning = headlessDontAskDowngradeWarning(permissionModes);
|
|
50
46
|
}
|
|
51
47
|
return resolution;
|
|
52
48
|
}
|
|
@@ -56,10 +52,25 @@ export function resolveHeadlessPermissionMode(argv, env = hostEnv(), permissionM
|
|
|
56
52
|
};
|
|
57
53
|
if (!warnedInvalidEnv) {
|
|
58
54
|
warnedInvalidEnv = true;
|
|
59
|
-
resolution.warning =
|
|
55
|
+
resolution.warning = knob.warning;
|
|
60
56
|
}
|
|
61
57
|
return resolution;
|
|
62
58
|
}
|
|
59
|
+
export function readHeadlessPermissionModeKnob(env = hostEnv()) {
|
|
60
|
+
const raw = env[HEADLESS_PERMISSION_MODE_ENV]?.trim();
|
|
61
|
+
if (raw === undefined || raw === '')
|
|
62
|
+
return Object.freeze({ kind: 'absent' });
|
|
63
|
+
if (HEADLESS_PERMISSION_WIRE_MODES.includes(raw))
|
|
64
|
+
return Object.freeze({ kind: 'word', word: raw });
|
|
65
|
+
return Object.freeze({
|
|
66
|
+
kind: 'invalid',
|
|
67
|
+
raw,
|
|
68
|
+
warning: `sema: ${HEADLESS_PERMISSION_MODE_ENV}="${raw}" is not a recognized permission mode (expected one of: ${HEADLESS_PERMISSION_WIRE_MODES.join(', ')}) — ignoring it, this run keeps the default permission behavior`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
export function headlessDontAskDowngradeWarning(permissionModes) {
|
|
72
|
+
return `sema: ${HEADLESS_PERMISSION_MODE_ENV}="dontAsk" is only sent once this client knows the engine accepts that mode, and ${dontAskWithheldClause(permissionModes)} — this run uses "default"`;
|
|
73
|
+
}
|
|
63
74
|
function dontAskSnapshot(reading) {
|
|
64
75
|
return permissionModeAdmitted(reading, 'dontAsk') ? { kind: 'present', modes: Object.freeze(['dontAsk']) } : undefined;
|
|
65
76
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { appendOwnElement } from '../ownKey.js';
|
|
2
|
+
import { slotPresenceOf } from '../wireFailureShape.js';
|
|
1
3
|
import { CORE_ALLOW_RULE_MEMBERS } from '../generated/engineFactTables.js';
|
|
2
4
|
import { displayUntrusted, quoteUntrustedForSentence } from '../displayUntrusted.js';
|
|
3
5
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
@@ -25,7 +27,7 @@ function readMemberRecord(r) {
|
|
|
25
27
|
let ok = true;
|
|
26
28
|
for (let i = 0; i < length; i++) {
|
|
27
29
|
const d = Object.getOwnPropertyDescriptor(rawEntries, i);
|
|
28
|
-
if (d === undefined || !('value'
|
|
30
|
+
if (d === undefined || !Object.hasOwn(d, 'value')) {
|
|
29
31
|
ok = false;
|
|
30
32
|
break;
|
|
31
33
|
}
|
|
@@ -34,7 +36,7 @@ function readMemberRecord(r) {
|
|
|
34
36
|
ok = false;
|
|
35
37
|
break;
|
|
36
38
|
}
|
|
37
|
-
out
|
|
39
|
+
appendOwnElement(out, e);
|
|
38
40
|
}
|
|
39
41
|
if (ok && rawEntries.length === length)
|
|
40
42
|
entries = Object.freeze(out);
|
|
@@ -92,7 +94,7 @@ export function retiredAllowRuleShadowKeyPresent(carrier, leg) {
|
|
|
92
94
|
const host = leg === 'row' ? keyValue(carrier, 'riskDescriptor') : carrier;
|
|
93
95
|
if (typeof host !== 'object' || host === null)
|
|
94
96
|
return false;
|
|
95
|
-
return RETIRED_SHADOW_KEY[leg]
|
|
97
|
+
return slotPresenceOf(host, RETIRED_SHADOW_KEY[leg]) !== 'absent';
|
|
96
98
|
}
|
|
97
99
|
catch {
|
|
98
100
|
return true;
|
|
@@ -100,7 +102,7 @@ export function retiredAllowRuleShadowKeyPresent(carrier, leg) {
|
|
|
100
102
|
}
|
|
101
103
|
function readMemberAt(arr, i) {
|
|
102
104
|
const d = Object.getOwnPropertyDescriptor(arr, i);
|
|
103
|
-
return d !== undefined && 'value'
|
|
105
|
+
return d !== undefined && Object.hasOwn(d, 'value') ? readMemberRecord(d.value) : freezeMember({ known: false, malformed: true });
|
|
104
106
|
}
|
|
105
107
|
export function readAllowRuleShadowFromWire(carrier, leg) {
|
|
106
108
|
try {
|
|
@@ -133,7 +135,7 @@ function readStampedValue(raw) {
|
|
|
133
135
|
for (let i = 0; i < length; i++) {
|
|
134
136
|
const r = readMemberAt(members, i);
|
|
135
137
|
const d = Object.getOwnPropertyDescriptor(members, i);
|
|
136
|
-
const was = d !== undefined && 'value'
|
|
138
|
+
const was = d !== undefined && Object.hasOwn(d, 'value') && typeof d.value === 'object' && d.value !== null && d.value.malformed === true;
|
|
137
139
|
out.push(was && r.malformed !== true ? freezeMember({ ...r, malformed: true }) : r);
|
|
138
140
|
}
|
|
139
141
|
if (members.length !== length)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CORE_TOOL_APPROVAL_CARDS } from '../generated/engineFactTables.js';
|
|
1
2
|
import type { ApprovalCardRequest } from './toolApprovalWire.js';
|
|
2
3
|
export declare function readRequiresRealApproval(carrier: object | null | undefined): boolean;
|
|
3
4
|
export interface ApprovalWindowKeys {
|
|
@@ -13,3 +14,5 @@ export interface ApprovalWindowReadOpts {
|
|
|
13
14
|
}
|
|
14
15
|
export declare function approvalWindowKeysOf(carrier: object | null | undefined, opts?: ApprovalWindowReadOpts | null): Readonly<ApprovalWindowKeys>;
|
|
15
16
|
export declare function probeCauseRowsOf(card: Pick<ApprovalCardRequest, 'probeCause'> | null | undefined): readonly string[] | undefined;
|
|
17
|
+
export type ApprovalCardWord = (typeof CORE_TOOL_APPROVAL_CARDS)[number];
|
|
18
|
+
export declare function readApprovalCardWord(carrier: unknown): ApprovalCardWord | undefined;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CORE_TOOL_APPROVAL_CARDS } from '../generated/engineFactTables.js';
|
|
1
2
|
import { displayUntrusted } from '../displayUntrusted.js';
|
|
2
3
|
import { guardedRead, readOwnDataValue } from '../ownKey.js';
|
|
3
4
|
export function readRequiresRealApproval(carrier) {
|
|
@@ -152,3 +153,19 @@ export function probeCauseRowsOf(card) {
|
|
|
152
153
|
return undefined;
|
|
153
154
|
}
|
|
154
155
|
}
|
|
156
|
+
const _approvalCardWordPins = [true, true];
|
|
157
|
+
void _approvalCardWordPins;
|
|
158
|
+
const APPROVAL_CARD_WORD_SET = new Set(CORE_TOOL_APPROVAL_CARDS);
|
|
159
|
+
export function readApprovalCardWord(carrier) {
|
|
160
|
+
try {
|
|
161
|
+
if (typeof carrier !== 'object' || carrier === null)
|
|
162
|
+
return undefined;
|
|
163
|
+
const d = Object.getOwnPropertyDescriptor(carrier, 'approvalCard');
|
|
164
|
+
if (d === undefined || !Object.hasOwn(d, 'value'))
|
|
165
|
+
return undefined;
|
|
166
|
+
return APPROVAL_CARD_WORD_SET.has(d.value) ? d.value : undefined;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function ownData(o, key) {
|
|
2
2
|
const d = Object.getOwnPropertyDescriptor(o, key);
|
|
3
|
-
return d !== undefined && 'value'
|
|
3
|
+
return d !== undefined && Object.hasOwn(d, 'value') ? d.value : undefined;
|
|
4
4
|
}
|
|
5
5
|
export function approvalCompleteParked(frame) {
|
|
6
6
|
try {
|