@sema-agent/client-core 0.110.0 → 0.112.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 +244 -0
- package/README.md +59 -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/agentSession/engineSessionBackgroundStop.js +2 -2
- 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/checkpointRowVerdict.d.ts +3 -0
- package/dist/checkpointRowVerdict.js +14 -1
- package/dist/compactionStatus.d.ts +9 -0
- package/dist/compactionStatus.js +29 -5
- package/dist/consoleCaPin.d.ts +136 -0
- package/dist/consoleCaPin.js +827 -0
- package/dist/controlRouter.js +2 -1
- package/dist/coreValuePorts.d.ts +39 -1
- package/dist/coreValuePorts.js +10 -0
- package/dist/decideReceipt.d.ts +2 -1
- package/dist/deviceRebind.js +3 -3
- package/dist/displayUntrusted.d.ts +1 -0
- package/dist/displayUntrusted.js +6 -0
- package/dist/effectiveFacts.d.ts +9 -0
- package/dist/effectiveFacts.js +33 -0
- package/dist/engineAddress.d.ts +1 -0
- package/dist/engineAddress.js +4 -1
- package/dist/engineCredentialRelease.d.ts +54 -0
- package/dist/engineCredentialRelease.js +146 -0
- package/dist/engineErrorCodes.d.ts +1 -0
- package/dist/engineErrorCodes.js +1 -0
- package/dist/engineHealthProbeVerdict.d.ts +24 -0
- package/dist/engineHealthProbeVerdict.js +123 -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 +45 -0
- package/dist/engineUnavailable.js +496 -0
- package/dist/engineUrl.js +4 -2
- package/dist/eventLeg.js +3 -3
- package/dist/gateFailureCodes.js +2 -2
- package/dist/generated/sdkFactTables.d.ts +2 -1
- package/dist/generated/sdkFactTables.js +14 -0
- package/dist/generated/settingsSchemaFns.d.ts +1 -0
- package/dist/generated/settingsSchemaFns.js +3 -0
- package/dist/generated/settingsSchemaHooksClassifier.js +38 -9
- package/dist/generated/settingsSchemaTables.d.ts +56 -0
- package/dist/generated/settingsSchemaTables.js +19 -0
- package/dist/generated/settingsSchemaTypes.d.ts +23 -13
- package/dist/generated/settingsSchemaUrlShape.d.ts +1 -0
- package/dist/generated/settingsSchemaUrlShape.js +17 -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 +6 -0
- package/dist/hitl/decisionRefusal.js +19 -10
- 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 +70 -0
- package/dist/hitl/localAllowRedemption.js +276 -0
- package/dist/hitl/parkOwnership.js +2 -1
- package/dist/hitl/parkResolver.js +14 -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 +363 -0
- package/dist/hitl/sessionPolicyWire.js +2 -2
- package/dist/hitl/standingRows.d.ts +6 -2
- package/dist/hitl/standingRows.js +27 -2
- package/dist/hitl/toolApprovalWire.d.ts +30 -8
- package/dist/hitl/toolApprovalWire.js +264 -121
- package/dist/hooksReaderGenerations.js +1 -1
- 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 +292 -0
- package/dist/i18n/messages.en.js +298 -7
- package/dist/i18n/messages.zh.js +316 -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 +71 -20
- package/dist/index.js +44 -13
- package/dist/interactiveHalt.js +2 -1
- package/dist/interactiveInterrupt.js +20 -2
- package/dist/liveModelCatalog.d.ts +4 -0
- package/dist/liveModelCatalog.js +12 -3
- package/dist/localConfig/documents.d.ts +61 -0
- package/dist/localConfig/documents.js +51 -0
- package/dist/localConfig/kernel.d.ts +149 -0
- package/dist/localConfig/kernel.js +597 -0
- package/dist/localConfig/mcp/edit.d.ts +161 -0
- package/dist/localConfig/mcp/edit.js +846 -0
- package/dist/localConfig/mcp/servers.d.ts +165 -0
- package/dist/localConfig/mcp/servers.js +776 -0
- package/dist/localConfig/mcp/views.d.ts +170 -0
- package/dist/localConfig/mcp/views.js +429 -0
- package/dist/localConfig/modelPool.d.ts +262 -0
- package/dist/localConfig/modelPool.js +1489 -0
- package/dist/localConfig/modelPoolWords.d.ts +13 -0
- package/dist/localConfig/modelPoolWords.js +20 -0
- package/dist/localConfig/receiptShape.d.ts +7 -0
- package/dist/localConfig/receiptShape.js +135 -0
- package/dist/localConfig/settingsWrite.d.ts +127 -0
- package/dist/localConfig/settingsWrite.js +237 -0
- package/dist/localConfig/skills.d.ts +124 -0
- package/dist/localConfig/skills.js +397 -0
- package/dist/localConfig/skillsWords.d.ts +10 -0
- package/dist/localConfig/skillsWords.js +5 -0
- 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/mcpProbeWire.js +2 -1
- package/dist/mcpReconnect.js +3 -3
- package/dist/mcpWireCaps.js +1 -1
- package/dist/memoryVerbsWire.js +3 -2
- package/dist/model/engineModelWords.d.ts +3 -0
- package/dist/model/engineModelWords.js +13 -0
- package/dist/model/onboardJudgement.d.ts +14 -4
- package/dist/model/onboardJudgement.js +91 -139
- package/dist/model/subagentModelWord.d.ts +21 -2
- package/dist/model/subagentModelWord.js +100 -29
- package/dist/modelCapabilityProbe.js +3 -40
- package/dist/modelConfigGapNotice.d.ts +20 -0
- package/dist/modelConfigGapNotice.js +102 -0
- package/dist/modsKernelIdentity.js +2 -47
- package/dist/notifications.d.ts +19 -0
- package/dist/notifications.js +114 -12
- package/dist/ownKey.d.ts +7 -0
- package/dist/ownKey.js +71 -8
- package/dist/pendingUserRow.d.ts +4 -0
- package/dist/pendingUserRow.js +16 -0
- package/dist/permissionsDeclaration.d.ts +3 -1
- package/dist/permissionsDeclaration.js +33 -9
- 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 +12 -7
- 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/resumeRefusalCopy.d.ts +3 -1
- package/dist/resumeRefusalCopy.js +12 -4
- package/dist/rewindArchiveReading.js +4 -4
- package/dist/runCancelContext.d.ts +2 -1
- package/dist/runCancelContext.js +1 -0
- package/dist/runLedgerSnapshot.js +3 -3
- package/dist/runPermissionModeSwitch.js +3 -4
- 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 +259 -9
- package/dist/seatContract.js +444 -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/sessionIdSegment.d.ts +1 -0
- package/dist/sessionIdSegment.js +4 -1
- package/dist/sessionMemoryErase.js +2 -1
- 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/sha256Bytes.d.ts +1 -0
- package/dist/sha256Bytes.js +46 -0
- package/dist/skillOverrideChain.d.ts +83 -0
- package/dist/skillOverrideChain.js +378 -0
- package/dist/skillsWireCaps.d.ts +3 -0
- package/dist/skillsWireCaps.js +16 -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/turnFailurePresentation.js +4 -10
- 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 +2718 -17
- package/package.json +7 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MODEL_POOL_EDIT_KINDS: readonly ["add", "update", "remove", "setDefault", "importEnvModels", "importChannel", "bindTier", "switchTierGroup", "addTierGroup", "removeTierGroup", "migrateTierGroups", "sweepOrphanKeySlots"];
|
|
2
|
+
export type ModelPoolEditKind = (typeof MODEL_POOL_EDIT_KINDS)[number];
|
|
3
|
+
export declare const MODEL_POOL_CHANNEL_SOURCES: readonly ["cc-switch", "claude-settings", "openclaw", "hermes"];
|
|
4
|
+
export type ModelPoolChannelSource = (typeof MODEL_POOL_CHANNEL_SOURCES)[number];
|
|
5
|
+
export declare const MODEL_POOL_CREDENTIAL_KINDS: readonly ["key", "none"];
|
|
6
|
+
export type ModelPoolCredentialKind = (typeof MODEL_POOL_CREDENTIAL_KINDS)[number];
|
|
7
|
+
export declare const MODEL_POOL_MAX_BATCH = 64;
|
|
8
|
+
export declare const MODEL_POOL_PROBE_STATES: readonly ["verified", "unverified", "unprobed"];
|
|
9
|
+
export type ModelPoolProbeState = (typeof MODEL_POOL_PROBE_STATES)[number];
|
|
10
|
+
export declare const MODEL_POOL_DEFAULT_KEEP_REASONS: readonly ["has_default", "existing_unknown", "declined", "nothing_added", "none_verified"];
|
|
11
|
+
export type ModelPoolDefaultKeepReason = (typeof MODEL_POOL_DEFAULT_KEEP_REASONS)[number];
|
|
12
|
+
export declare const MODEL_POOL_COMPLETENESS: readonly ["complete", "catalog_incomplete"];
|
|
13
|
+
export type ModelPoolCompleteness = (typeof MODEL_POOL_COMPLETENESS)[number];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const MODEL_POOL_EDIT_KINDS = Object.freeze([
|
|
2
|
+
'add',
|
|
3
|
+
'update',
|
|
4
|
+
'remove',
|
|
5
|
+
'setDefault',
|
|
6
|
+
'importEnvModels',
|
|
7
|
+
'importChannel',
|
|
8
|
+
'bindTier',
|
|
9
|
+
'switchTierGroup',
|
|
10
|
+
'addTierGroup',
|
|
11
|
+
'removeTierGroup',
|
|
12
|
+
'migrateTierGroups',
|
|
13
|
+
'sweepOrphanKeySlots',
|
|
14
|
+
]);
|
|
15
|
+
export const MODEL_POOL_CHANNEL_SOURCES = Object.freeze(['cc-switch', 'claude-settings', 'openclaw', 'hermes']);
|
|
16
|
+
export const MODEL_POOL_CREDENTIAL_KINDS = Object.freeze(['key', 'none']);
|
|
17
|
+
export const MODEL_POOL_MAX_BATCH = 64;
|
|
18
|
+
export const MODEL_POOL_PROBE_STATES = Object.freeze(['verified', 'unverified', 'unprobed']);
|
|
19
|
+
export const MODEL_POOL_DEFAULT_KEEP_REASONS = Object.freeze(['has_default', 'existing_unknown', 'declined', 'nothing_added', 'none_verified']);
|
|
20
|
+
export const MODEL_POOL_COMPLETENESS = Object.freeze(['complete', 'catalog_incomplete']);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type LocalConfigShapeVerdict = true | {
|
|
2
|
+
readonly reason: string;
|
|
3
|
+
readonly field?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function localConfigReceiptShapeOf(v: {} | null | undefined, at?: string): LocalConfigShapeVerdict;
|
|
6
|
+
export declare function localConfigUnavailableShapeOf(v: {} | null | undefined, at?: string): LocalConfigShapeVerdict;
|
|
7
|
+
export declare function localConfigDisclosureShapeOf(v: {} | null | undefined, at?: string): LocalConfigShapeVerdict;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { isPlainRecord as isJsonPlainRecord } from '../jsonFaithful.js';
|
|
2
|
+
import { ownDataField, ownSendableField } from '../ownKey.js';
|
|
3
|
+
import { LOCAL_CONFIG_APPLIES_ON, LOCAL_CONFIG_DISCLOSURE_KINDS, LOCAL_CONFIG_REFUSALS, LOCAL_CONFIG_RESIDUES, LOCAL_CONFIG_UNAVAILABLE_CAUSES, LOCAL_CONFIG_UNKNOWN_CAUSES, } from './kernel.js';
|
|
4
|
+
import { isWritableLocalConfigDocument, localConfigDocumentOf } from './documents.js';
|
|
5
|
+
const req = (judge) => ({ opt: false, judge });
|
|
6
|
+
const opt = (judge) => ({ opt: true, judge });
|
|
7
|
+
const fail = (reason, at) => (at === '' ? { reason } : { reason, field: at });
|
|
8
|
+
const pathAt = (at, key) => (at === '' ? key : `${at}.${key}`);
|
|
9
|
+
const NOT_PLAIN = 'not plain';
|
|
10
|
+
const UNREADABLE = 'unreadable';
|
|
11
|
+
function slotOf(v, key) {
|
|
12
|
+
try {
|
|
13
|
+
return { ok: true, value: ownSendableField(v, key) };
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { ok: false };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v) && isJsonPlainRecord(v);
|
|
20
|
+
const badValue = (label, at) => fail(`bad value (${label})`, at);
|
|
21
|
+
const valueOf = (label, test) => (v, at) => (test(v) ? true : badValue(label, at));
|
|
22
|
+
const oneOf = (label, words) => valueOf(label, (v) => typeof v === 'string' && words.includes(v));
|
|
23
|
+
const NONEMPTY = valueOf('non-empty string', (v) => typeof v === 'string' && v.length > 0);
|
|
24
|
+
const BOOL = valueOf('boolean', (v) => typeof v === 'boolean');
|
|
25
|
+
const isSlotKey = (k, n) => k === 'length' || (/^(0|[1-9][0-9]*)$/.test(k) && Number(k) < n);
|
|
26
|
+
function listOf(label, item, nonEmpty) {
|
|
27
|
+
return (v, at) => {
|
|
28
|
+
if (!Array.isArray(v))
|
|
29
|
+
return badValue(label, at);
|
|
30
|
+
const n = ownDataField(v, 'length');
|
|
31
|
+
const len = typeof n === 'number' ? n : 0;
|
|
32
|
+
for (const k of Reflect.ownKeys(v))
|
|
33
|
+
if (typeof k === 'string' && !isSlotKey(k, len))
|
|
34
|
+
return fail('unknown key', pathAt(at, k));
|
|
35
|
+
if (nonEmpty && len === 0)
|
|
36
|
+
return badValue(label, at);
|
|
37
|
+
for (let i = 0; i < len; i += 1) {
|
|
38
|
+
const s = slotOf(v, String(i));
|
|
39
|
+
if (!s.ok)
|
|
40
|
+
return fail(NOT_PLAIN, `${at}[${i}]`);
|
|
41
|
+
const r = item(s.value, `${at}[${i}]`);
|
|
42
|
+
if (r !== true)
|
|
43
|
+
return r;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function fieldsVerdict(fields, v, at, disc) {
|
|
49
|
+
if (!isRecord(v))
|
|
50
|
+
return fail('not object', at);
|
|
51
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
52
|
+
if (typeof k !== 'string')
|
|
53
|
+
continue;
|
|
54
|
+
if (!slotOf(v, k).ok)
|
|
55
|
+
return fail(NOT_PLAIN, pathAt(at, k));
|
|
56
|
+
if (k !== disc && !Object.hasOwn(fields, k))
|
|
57
|
+
return fail('unknown key', pathAt(at, k));
|
|
58
|
+
}
|
|
59
|
+
for (const k of Object.keys(fields)) {
|
|
60
|
+
const f = fields[k];
|
|
61
|
+
const s = slotOf(v, k);
|
|
62
|
+
if (!s.ok)
|
|
63
|
+
return fail(NOT_PLAIN, pathAt(at, k));
|
|
64
|
+
if (s.value === undefined) {
|
|
65
|
+
if (!f.opt)
|
|
66
|
+
return fail('missing key', pathAt(at, k));
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const r = f.judge(s.value, pathAt(at, k));
|
|
70
|
+
if (r !== true)
|
|
71
|
+
return r;
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const DISCLOSURE_KIND = req(oneOf('disclosure kind', LOCAL_CONFIG_DISCLOSURE_KINDS));
|
|
76
|
+
const LAYER = opt(valueOf('document', (v) => localConfigDocumentOf(v) !== undefined));
|
|
77
|
+
const DETAIL = opt(NONEMPTY);
|
|
78
|
+
function disclosureFields() {
|
|
79
|
+
return { kind: DISCLOSURE_KIND, layer: LAYER, detail: DETAIL };
|
|
80
|
+
}
|
|
81
|
+
const disclosureJudge = (v, at) => fieldsVerdict(disclosureFields(), v, at);
|
|
82
|
+
const RESIDUES = opt(listOf('residue', oneOf('residue', LOCAL_CONFIG_RESIDUES), true));
|
|
83
|
+
const DISCLOSURES = opt(listOf('disclosure', disclosureJudge, true));
|
|
84
|
+
const APPLIES_ON = req(oneOf('applies on', LOCAL_CONFIG_APPLIES_ON));
|
|
85
|
+
const WRITES = req(listOf('writes', valueOf('writable document', (v) => isWritableLocalConfigDocument(v)), false));
|
|
86
|
+
const CHANGED = req(BOOL);
|
|
87
|
+
const REASON = req(oneOf('refusal', LOCAL_CONFIG_REFUSALS));
|
|
88
|
+
const UNAVAILABLE_CAUSE = req(oneOf('unavailable cause', LOCAL_CONFIG_UNAVAILABLE_CAUSES));
|
|
89
|
+
const UNKNOWN_CAUSE = req(oneOf('unknown cause', LOCAL_CONFIG_UNKNOWN_CAUSES));
|
|
90
|
+
function receiptArms() {
|
|
91
|
+
return {
|
|
92
|
+
applied: { appliesOn: APPLIES_ON, changed: CHANGED, residue: RESIDUES, disclosures: DISCLOSURES },
|
|
93
|
+
refused: { reason: REASON, detail: DETAIL, residue: RESIDUES },
|
|
94
|
+
unavailable: { cause: UNAVAILABLE_CAUSE },
|
|
95
|
+
unknown: { cause: UNKNOWN_CAUSE, residue: RESIDUES },
|
|
96
|
+
preview: { appliesOn: APPLIES_ON, changed: CHANGED, writes: WRITES, disclosures: DISCLOSURES },
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function armVerdict(v, at, only) {
|
|
100
|
+
try {
|
|
101
|
+
if (!isRecord(v))
|
|
102
|
+
return fail('not object', at);
|
|
103
|
+
const d = slotOf(v, 'kind');
|
|
104
|
+
if (!d.ok)
|
|
105
|
+
return fail(NOT_PLAIN, pathAt(at, 'kind'));
|
|
106
|
+
const arms = receiptArms();
|
|
107
|
+
const kind = typeof d.value === 'string' && Object.hasOwn(arms, d.value) && (only === undefined || d.value === only) ? d.value : undefined;
|
|
108
|
+
if (kind === undefined)
|
|
109
|
+
return fail('unknown arm', pathAt(at, 'kind'));
|
|
110
|
+
const r = fieldsVerdict(arms[kind], v, at, 'kind');
|
|
111
|
+
if (r !== true || kind !== 'preview')
|
|
112
|
+
return r;
|
|
113
|
+
const writes = slotOf(v, 'writes');
|
|
114
|
+
const changed = slotOf(v, 'changed');
|
|
115
|
+
const n = writes.ok && Array.isArray(writes.value) ? ownDataField(writes.value, 'length') : undefined;
|
|
116
|
+
return changed.ok && changed.value === (typeof n === 'number' && n > 0) ? true : badValue('changed', pathAt(at, 'changed'));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return fail(UNREADABLE, at);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function localConfigReceiptShapeOf(v, at = '') {
|
|
123
|
+
return armVerdict(v, at);
|
|
124
|
+
}
|
|
125
|
+
export function localConfigUnavailableShapeOf(v, at = '') {
|
|
126
|
+
return armVerdict(v, at, 'unavailable');
|
|
127
|
+
}
|
|
128
|
+
export function localConfigDisclosureShapeOf(v, at = '') {
|
|
129
|
+
try {
|
|
130
|
+
return disclosureJudge(v, at);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return fail(UNREADABLE, at);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { SettingsDocument } from '../host.js';
|
|
2
|
+
import type { WorkspaceTrustState } from '../hostSettingsSource.js';
|
|
3
|
+
import type { LocalConfigWritableDocumentName } from './documents.js';
|
|
4
|
+
import type { LocalConfigRefusal, LocalConfigResidue, LocalConfigStep, LocalConfigStepRole } from './kernel.js';
|
|
5
|
+
export declare const LOCAL_CONFIG_WRITE_INTENTS: readonly [Readonly<{
|
|
6
|
+
readonly intent: "skillOverride";
|
|
7
|
+
readonly key: readonly ["skillOverrides"];
|
|
8
|
+
readonly member: "name";
|
|
9
|
+
readonly targets: readonly ["localSettings", "userSettings"];
|
|
10
|
+
readonly unit: null;
|
|
11
|
+
readonly values: readonly ["on", "name-only", "user-invocable-only", "off"];
|
|
12
|
+
}>, Readonly<{
|
|
13
|
+
readonly intent: "modelKeySlot";
|
|
14
|
+
readonly key: readonly ["env"];
|
|
15
|
+
readonly member: "keySlot";
|
|
16
|
+
readonly targets: readonly ["userSettings"];
|
|
17
|
+
readonly unit: "env";
|
|
18
|
+
readonly values: null;
|
|
19
|
+
}>, Readonly<{
|
|
20
|
+
readonly intent: "additionalDirectories";
|
|
21
|
+
readonly key: readonly ["permissions", "additionalDirectories"];
|
|
22
|
+
readonly member: null;
|
|
23
|
+
readonly targets: readonly ["userSettings", "projectSettings", "localSettings"];
|
|
24
|
+
readonly unit: "additionalDirectories";
|
|
25
|
+
readonly values: null;
|
|
26
|
+
}>, Readonly<{
|
|
27
|
+
readonly intent: "modelCatalog";
|
|
28
|
+
readonly key: readonly ["models"];
|
|
29
|
+
readonly member: null;
|
|
30
|
+
readonly targets: readonly ["models"];
|
|
31
|
+
readonly unit: null;
|
|
32
|
+
readonly values: null;
|
|
33
|
+
}>, Readonly<{
|
|
34
|
+
readonly intent: "defaultModel";
|
|
35
|
+
readonly key: readonly ["roles", "default"];
|
|
36
|
+
readonly member: null;
|
|
37
|
+
readonly targets: readonly ["models"];
|
|
38
|
+
readonly unit: null;
|
|
39
|
+
readonly values: null;
|
|
40
|
+
}>, Readonly<{
|
|
41
|
+
readonly intent: "tierGroups";
|
|
42
|
+
readonly key: readonly ["tierGroups"];
|
|
43
|
+
readonly member: null;
|
|
44
|
+
readonly targets: readonly ["models"];
|
|
45
|
+
readonly unit: null;
|
|
46
|
+
readonly values: null;
|
|
47
|
+
}>, Readonly<{
|
|
48
|
+
readonly intent: "activeTierGroup";
|
|
49
|
+
readonly key: readonly ["activeTierGroup"];
|
|
50
|
+
readonly member: null;
|
|
51
|
+
readonly targets: readonly ["models"];
|
|
52
|
+
readonly unit: null;
|
|
53
|
+
readonly values: null;
|
|
54
|
+
}>, Readonly<{
|
|
55
|
+
readonly intent: "mcpJsonEnabled";
|
|
56
|
+
readonly key: readonly ["enabledMcpjsonServers"];
|
|
57
|
+
readonly member: "listItem";
|
|
58
|
+
readonly targets: readonly ["localSettings"];
|
|
59
|
+
readonly unit: null;
|
|
60
|
+
readonly values: null;
|
|
61
|
+
readonly admitVia: "mcpServers";
|
|
62
|
+
}>, Readonly<{
|
|
63
|
+
readonly intent: "mcpJsonDisabled";
|
|
64
|
+
readonly key: readonly ["disabledMcpjsonServers"];
|
|
65
|
+
readonly member: "listItem";
|
|
66
|
+
readonly targets: readonly ["localSettings"];
|
|
67
|
+
readonly unit: null;
|
|
68
|
+
readonly values: null;
|
|
69
|
+
}>, Readonly<{
|
|
70
|
+
readonly intent: "legacyTierGroups";
|
|
71
|
+
readonly key: readonly ["semaTierGroups"];
|
|
72
|
+
readonly member: null;
|
|
73
|
+
readonly targets: readonly ["userSettings"];
|
|
74
|
+
readonly unit: null;
|
|
75
|
+
readonly values: null;
|
|
76
|
+
}>, Readonly<{
|
|
77
|
+
readonly intent: "legacyRosters";
|
|
78
|
+
readonly key: readonly ["semaRosters"];
|
|
79
|
+
readonly member: null;
|
|
80
|
+
readonly targets: readonly ["userSettings"];
|
|
81
|
+
readonly unit: null;
|
|
82
|
+
readonly values: null;
|
|
83
|
+
}>];
|
|
84
|
+
export type LocalConfigWriteIntentRow = (typeof LOCAL_CONFIG_WRITE_INTENTS)[number];
|
|
85
|
+
export type LocalConfigWriteIntent = LocalConfigWriteIntentRow['intent'];
|
|
86
|
+
declare const SETTINGS_LAYER_DOCUMENTS: readonly ["userSettings", "projectSettings", "localSettings"];
|
|
87
|
+
type SettingsLayerDocument = (typeof SETTINGS_LAYER_DOCUMENTS)[number];
|
|
88
|
+
type SettingsIntentRow = Extract<LocalConfigWriteIntentRow, {
|
|
89
|
+
readonly targets: readonly SettingsLayerDocument[];
|
|
90
|
+
}>;
|
|
91
|
+
export type SettingsWriteIntent = SettingsIntentRow['intent'];
|
|
92
|
+
export declare const SETTINGS_WRITE_KEYS: readonly string[];
|
|
93
|
+
export type SettingsWriteEdit = {
|
|
94
|
+
readonly intent: SettingsWriteIntent;
|
|
95
|
+
readonly member?: string;
|
|
96
|
+
readonly op: 'set';
|
|
97
|
+
readonly value: string | readonly string[];
|
|
98
|
+
} | {
|
|
99
|
+
readonly intent: SettingsWriteIntent;
|
|
100
|
+
readonly member?: string;
|
|
101
|
+
readonly op: 'delete';
|
|
102
|
+
};
|
|
103
|
+
export interface SettingsWritePlanInput {
|
|
104
|
+
readonly doc: LocalConfigWritableDocumentName;
|
|
105
|
+
readonly current: SettingsDocument | null;
|
|
106
|
+
readonly trust: WorkspaceTrustState | 'unreadable';
|
|
107
|
+
readonly edits: readonly SettingsWriteEdit[];
|
|
108
|
+
}
|
|
109
|
+
export type SettingsWritePlan = {
|
|
110
|
+
readonly ok: true;
|
|
111
|
+
readonly next: SettingsDocument;
|
|
112
|
+
readonly changed: boolean;
|
|
113
|
+
} | {
|
|
114
|
+
readonly ok: false;
|
|
115
|
+
readonly reason: LocalConfigRefusal;
|
|
116
|
+
readonly detail?: string;
|
|
117
|
+
};
|
|
118
|
+
export declare function settingsWritePlan(input: SettingsWritePlanInput): SettingsWritePlan;
|
|
119
|
+
export interface SettingsWriteStepInput {
|
|
120
|
+
readonly doc: LocalConfigWritableDocumentName;
|
|
121
|
+
readonly trust: WorkspaceTrustState | 'unreadable';
|
|
122
|
+
readonly edits: readonly SettingsWriteEdit[];
|
|
123
|
+
readonly role?: LocalConfigStepRole;
|
|
124
|
+
readonly residue?: LocalConfigResidue;
|
|
125
|
+
}
|
|
126
|
+
export declare function settingsWriteStep(input: SettingsWriteStepInput): LocalConfigStep;
|
|
127
|
+
export {};
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { SETTINGS_UNIT_PLACES, SETTINGS_WORKSPACE_TRUST_STATES } from '../generated/settingsSchemaTables.js';
|
|
2
|
+
import { SETTINGS_IS_RESERVED_MEMBER_NAME } from '../generated/settingsSchemaFns.js';
|
|
3
|
+
import { layerAdmissionWord } from '../settingsLayerAdmission.js';
|
|
4
|
+
import { KEY_SLOT_PREFIX } from '../model/onboardJudgement.js';
|
|
5
|
+
import { ownSnapshotRecord, readOwnDataValue } from '../ownKey.js';
|
|
6
|
+
import { SKILL_OVERRIDE_STATES } from '../skillOverrideChain.js';
|
|
7
|
+
const unitKey = (unit) => SETTINGS_UNIT_PLACES[unit].path;
|
|
8
|
+
const SKILL_OVERRIDE_WORDS = SKILL_OVERRIDE_STATES;
|
|
9
|
+
export const LOCAL_CONFIG_WRITE_INTENTS = Object.freeze([
|
|
10
|
+
Object.freeze({ intent: 'skillOverride', key: Object.freeze(['skillOverrides']), member: 'name', targets: Object.freeze(['localSettings', 'userSettings']), unit: null, values: SKILL_OVERRIDE_WORDS }),
|
|
11
|
+
Object.freeze({ intent: 'modelKeySlot', key: unitKey('env'), member: 'keySlot', targets: Object.freeze(['userSettings']), unit: 'env', values: null }),
|
|
12
|
+
Object.freeze({ intent: 'additionalDirectories', key: unitKey('additionalDirectories'), member: null, targets: Object.freeze(['userSettings', 'projectSettings', 'localSettings']), unit: 'additionalDirectories', values: null }),
|
|
13
|
+
Object.freeze({ intent: 'modelCatalog', key: Object.freeze(['models']), member: null, targets: Object.freeze(['models']), unit: null, values: null }),
|
|
14
|
+
Object.freeze({ intent: 'defaultModel', key: Object.freeze(['roles', 'default']), member: null, targets: Object.freeze(['models']), unit: null, values: null }),
|
|
15
|
+
Object.freeze({ intent: 'tierGroups', key: Object.freeze(['tierGroups']), member: null, targets: Object.freeze(['models']), unit: null, values: null }),
|
|
16
|
+
Object.freeze({ intent: 'activeTierGroup', key: Object.freeze(['activeTierGroup']), member: null, targets: Object.freeze(['models']), unit: null, values: null }),
|
|
17
|
+
Object.freeze({ intent: 'mcpJsonEnabled', key: Object.freeze(['enabledMcpjsonServers']), member: 'listItem', targets: Object.freeze(['localSettings']), unit: null, values: null, admitVia: 'mcpServers' }),
|
|
18
|
+
Object.freeze({ intent: 'mcpJsonDisabled', key: Object.freeze(['disabledMcpjsonServers']), member: 'listItem', targets: Object.freeze(['localSettings']), unit: null, values: null }),
|
|
19
|
+
Object.freeze({ intent: 'legacyTierGroups', key: Object.freeze(['semaTierGroups']), member: null, targets: Object.freeze(['userSettings']), unit: null, values: null }),
|
|
20
|
+
Object.freeze({ intent: 'legacyRosters', key: Object.freeze(['semaRosters']), member: null, targets: Object.freeze(['userSettings']), unit: null, values: null }),
|
|
21
|
+
]);
|
|
22
|
+
const SETTINGS_LAYER_DOCUMENTS = Object.freeze(['userSettings', 'projectSettings', 'localSettings']);
|
|
23
|
+
const isSettingsLayerDocument = (v) => SETTINGS_LAYER_DOCUMENTS.some((d) => d === v);
|
|
24
|
+
const settingsRows = () => LOCAL_CONFIG_WRITE_INTENTS.filter((r) => r.targets.every((t) => isSettingsLayerDocument(t)));
|
|
25
|
+
const memberShape = (member) => member === 'name' ? '.<name>' : member === 'keySlot' ? `.${KEY_SLOT_PREFIX}<entry>` : member === 'listItem' ? '[<name>]' : '';
|
|
26
|
+
export const SETTINGS_WRITE_KEYS = Object.freeze(settingsRows().map((r) => `${r.key.join('.')}${memberShape(r.member)}`));
|
|
27
|
+
const MAX_EDITS = 64;
|
|
28
|
+
const KEY_SLOT_RE = new RegExp(`^${KEY_SLOT_PREFIX}[A-Z0-9_]+$`);
|
|
29
|
+
function own(v, key) {
|
|
30
|
+
try {
|
|
31
|
+
return readOwnDataValue(v, key);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const isPlainRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
38
|
+
const refuse = (reason, detail) => Object.freeze({ ok: false, reason, ...(detail === undefined ? {} : { detail }) });
|
|
39
|
+
function admissionRefusal(doc, trust, unit) {
|
|
40
|
+
return categoryAdmissionRefusal(doc, trust, SETTINGS_UNIT_PLACES[unit].category);
|
|
41
|
+
}
|
|
42
|
+
function categoryAdmissionRefusal(doc, trust, category) {
|
|
43
|
+
let word;
|
|
44
|
+
try {
|
|
45
|
+
word = layerAdmissionWord(doc, trust, category);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return 'invalid_request';
|
|
49
|
+
}
|
|
50
|
+
if (word === 'admitted')
|
|
51
|
+
return undefined;
|
|
52
|
+
if (word === 'trust_withheld')
|
|
53
|
+
return 'untrusted_folder';
|
|
54
|
+
return 'scope_unwritable';
|
|
55
|
+
}
|
|
56
|
+
function stringListOf(v) {
|
|
57
|
+
if (!Array.isArray(v) || v.length > 4096)
|
|
58
|
+
return undefined;
|
|
59
|
+
const out = [];
|
|
60
|
+
for (let i = 0; i < v.length; i++) {
|
|
61
|
+
const s = own(v, String(i));
|
|
62
|
+
if (typeof s !== 'string' || s === '')
|
|
63
|
+
return undefined;
|
|
64
|
+
out.push(s);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function valueFor(row, raw) {
|
|
69
|
+
const values = row.values;
|
|
70
|
+
if (Array.isArray(values))
|
|
71
|
+
return typeof raw === 'string' && values.some((w) => w === raw) ? raw : undefined;
|
|
72
|
+
if (values !== null)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (row.unit === null)
|
|
75
|
+
return undefined;
|
|
76
|
+
const reading = 'reading' in SETTINGS_UNIT_PLACES[row.unit] ? SETTINGS_UNIT_PLACES[row.unit].reading : undefined;
|
|
77
|
+
if (reading === 'stringList' && row.member === null)
|
|
78
|
+
return stringListOf(raw);
|
|
79
|
+
if (reading === 'envMap' && row.member !== null)
|
|
80
|
+
return typeof raw === 'string' ? raw : undefined;
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
function memberFits(row, member) {
|
|
84
|
+
if (typeof member !== 'string' || member === '' || member.length > 512 || SETTINGS_IS_RESERVED_MEMBER_NAME(member))
|
|
85
|
+
return false;
|
|
86
|
+
return row.member === 'keySlot' ? KEY_SLOT_RE.test(member) : true;
|
|
87
|
+
}
|
|
88
|
+
function listWith(current, name, present) {
|
|
89
|
+
const list = current === undefined ? [] : stringListOf(current);
|
|
90
|
+
if (list === undefined)
|
|
91
|
+
return undefined;
|
|
92
|
+
if (!present)
|
|
93
|
+
return list.filter((x) => x !== name);
|
|
94
|
+
return list.includes(name) ? list : [...list, name];
|
|
95
|
+
}
|
|
96
|
+
function sameJson(a, b) {
|
|
97
|
+
if (a === b)
|
|
98
|
+
return true;
|
|
99
|
+
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
100
|
+
return false;
|
|
101
|
+
if (Array.isArray(a) !== Array.isArray(b))
|
|
102
|
+
return false;
|
|
103
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
104
|
+
return a.length === b.length && a.every((x, i) => sameJson(x, b[i]));
|
|
105
|
+
const ka = Object.keys(a);
|
|
106
|
+
const kb = Object.keys(b);
|
|
107
|
+
return ka.length === kb.length && ka.every((k) => Object.hasOwn(b, k) && sameJson(a[k], b[k]));
|
|
108
|
+
}
|
|
109
|
+
export function settingsWritePlan(input) {
|
|
110
|
+
try {
|
|
111
|
+
if (!isPlainRecord(input))
|
|
112
|
+
return refuse('invalid_request');
|
|
113
|
+
const doc = own(input, 'doc');
|
|
114
|
+
if (!isSettingsLayerDocument(doc))
|
|
115
|
+
return refuse('invalid_request');
|
|
116
|
+
const currentRaw = own(input, 'current');
|
|
117
|
+
if (currentRaw !== null && !isPlainRecord(currentRaw))
|
|
118
|
+
return refuse('invalid_request');
|
|
119
|
+
const snap = currentRaw === null ? {} : ownSnapshotRecord(currentRaw);
|
|
120
|
+
if (snap === undefined)
|
|
121
|
+
return refuse('invalid_request');
|
|
122
|
+
const before = JSON.parse(JSON.stringify(snap));
|
|
123
|
+
const next = JSON.parse(JSON.stringify(snap));
|
|
124
|
+
const trustRaw = own(input, 'trust');
|
|
125
|
+
const trust = SETTINGS_WORKSPACE_TRUST_STATES.find((w) => w === trustRaw) ?? 'unreadable';
|
|
126
|
+
const edits = own(input, 'edits');
|
|
127
|
+
if (!Array.isArray(edits) || edits.length === 0 || edits.length > MAX_EDITS)
|
|
128
|
+
return refuse('invalid_request');
|
|
129
|
+
const rows = settingsRows();
|
|
130
|
+
for (let i = 0; i < edits.length; i++) {
|
|
131
|
+
const edit = own(edits, String(i));
|
|
132
|
+
if (!isPlainRecord(edit))
|
|
133
|
+
return refuse('invalid_request');
|
|
134
|
+
const row = rows.find((r) => r.intent === own(edit, 'intent'));
|
|
135
|
+
if (row === undefined)
|
|
136
|
+
return refuse('invalid_request');
|
|
137
|
+
const op = own(edit, 'op');
|
|
138
|
+
if (op !== 'set' && op !== 'delete')
|
|
139
|
+
return refuse('invalid_request');
|
|
140
|
+
const memberRaw = own(edit, 'member');
|
|
141
|
+
if (row.member === null ? memberRaw !== undefined : !memberFits(row, memberRaw))
|
|
142
|
+
return refuse('invalid_request');
|
|
143
|
+
if (!row.targets.some((t) => t === doc))
|
|
144
|
+
return refuse('scope_unwritable');
|
|
145
|
+
if (row.member === 'listItem') {
|
|
146
|
+
const name = memberRaw;
|
|
147
|
+
if (op === 'set') {
|
|
148
|
+
if (own(edit, 'value') !== name)
|
|
149
|
+
return refuse('invalid_request');
|
|
150
|
+
if ('admitVia' in row) {
|
|
151
|
+
const why = categoryAdmissionRefusal(doc, trust, row.admitVia);
|
|
152
|
+
if (why !== undefined)
|
|
153
|
+
return refuse(why);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
let box = next;
|
|
157
|
+
for (let k = 0; k < row.key.length - 1; k++) {
|
|
158
|
+
const seg = row.key[k];
|
|
159
|
+
const child = Object.hasOwn(box, seg) ? box[seg] : undefined;
|
|
160
|
+
if (child === undefined) {
|
|
161
|
+
const made = {};
|
|
162
|
+
Object.defineProperty(box, seg, { value: made, writable: true, enumerable: true, configurable: true });
|
|
163
|
+
box = made;
|
|
164
|
+
}
|
|
165
|
+
else if (isPlainRecord(child))
|
|
166
|
+
box = child;
|
|
167
|
+
else
|
|
168
|
+
return refuse('scope_unreadable', row.key.slice(0, k + 1).join('.'));
|
|
169
|
+
}
|
|
170
|
+
const last = row.key[row.key.length - 1];
|
|
171
|
+
const had = Object.hasOwn(box, last);
|
|
172
|
+
const list = listWith(had ? box[last] : undefined, name, op === 'set');
|
|
173
|
+
if (list === undefined)
|
|
174
|
+
return refuse('scope_unreadable', row.key.join('.'));
|
|
175
|
+
if (had || list.length > 0)
|
|
176
|
+
Object.defineProperty(box, last, { value: list, writable: true, enumerable: true, configurable: true });
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
const path = [...row.key, ...(row.member === null ? [] : [memberRaw])];
|
|
180
|
+
let value;
|
|
181
|
+
if (op === 'set') {
|
|
182
|
+
value = valueFor(row, own(edit, 'value'));
|
|
183
|
+
if (value === undefined)
|
|
184
|
+
return refuse('invalid_request');
|
|
185
|
+
if (row.unit !== null) {
|
|
186
|
+
const why = admissionRefusal(doc, trust, row.unit);
|
|
187
|
+
if (why !== undefined)
|
|
188
|
+
return refuse(why);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
let box = next;
|
|
192
|
+
for (let k = 0; k < path.length - 1; k++) {
|
|
193
|
+
const seg = path[k];
|
|
194
|
+
const child = Object.hasOwn(box, seg) ? box[seg] : undefined;
|
|
195
|
+
if (child === undefined) {
|
|
196
|
+
if (op === 'delete') {
|
|
197
|
+
box = {};
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
const made = {};
|
|
201
|
+
Object.defineProperty(box, seg, { value: made, writable: true, enumerable: true, configurable: true });
|
|
202
|
+
box = made;
|
|
203
|
+
}
|
|
204
|
+
else if (isPlainRecord(child))
|
|
205
|
+
box = child;
|
|
206
|
+
else
|
|
207
|
+
return refuse('scope_unreadable', path.slice(0, k + 1).join('.'));
|
|
208
|
+
}
|
|
209
|
+
const last = path[path.length - 1];
|
|
210
|
+
if (op === 'delete')
|
|
211
|
+
delete box[last];
|
|
212
|
+
else
|
|
213
|
+
Object.defineProperty(box, last, { value, writable: true, enumerable: true, configurable: true });
|
|
214
|
+
}
|
|
215
|
+
const frozen = ownSnapshotRecord(next);
|
|
216
|
+
if (frozen === undefined)
|
|
217
|
+
return refuse('invalid_request');
|
|
218
|
+
return Object.freeze({ ok: true, next: frozen, changed: !sameJson(before, next) });
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return refuse('invalid_request');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
export function settingsWriteStep(input) {
|
|
225
|
+
const doc = input.doc;
|
|
226
|
+
const trust = input.trust;
|
|
227
|
+
const edits = input.edits;
|
|
228
|
+
const plan = ({ fresh }) => {
|
|
229
|
+
const reading = fresh[doc];
|
|
230
|
+
const current = reading !== undefined && reading.status === 'loaded' ? reading.doc : null;
|
|
231
|
+
const r = settingsWritePlan({ doc, current, trust, edits });
|
|
232
|
+
if (!r.ok)
|
|
233
|
+
return { kind: 'refuse', reason: r.reason, ...(r.detail === undefined ? {} : { detail: r.detail }) };
|
|
234
|
+
return r.changed ? { kind: 'write', next: r.next } : { kind: 'unchanged' };
|
|
235
|
+
};
|
|
236
|
+
return Object.freeze({ doc, role: input.role ?? 'effect', ...(input.residue === undefined ? {} : { residue: input.residue }), plan });
|
|
237
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { SettingsDocument } from '../host.js';
|
|
2
|
+
import { type SkillOverrideEffective, type SkillOverrideLayers, type SkillOverrideLockSource, type SkillOverrideState, type SkillOverrideSubject } from '../skillOverrideChain.js';
|
|
3
|
+
import type { LocalConfigIntent, LocalConfigRefusal } from './kernel.js';
|
|
4
|
+
import { type SkillRootLayer, type SkillRootKind, type SkillsViewExcludedReason, type SkillsViewLayer, type SkillOverrideScope } from './skillsWords.js';
|
|
5
|
+
export interface SkillRootHostFacts {
|
|
6
|
+
readonly configHome: string;
|
|
7
|
+
readonly gitRoot?: string | null;
|
|
8
|
+
readonly additionalDirectories?: readonly string[];
|
|
9
|
+
readonly managedDir?: string;
|
|
10
|
+
readonly plugins?: readonly {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly root: string;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
export interface SkillRoot {
|
|
16
|
+
readonly layer: SkillRootLayer;
|
|
17
|
+
readonly kind: SkillRootKind;
|
|
18
|
+
readonly dir: string;
|
|
19
|
+
readonly base: string;
|
|
20
|
+
readonly plugin?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface SkillRootsTable {
|
|
23
|
+
readonly skills: readonly SkillRoot[];
|
|
24
|
+
readonly commands: readonly SkillRoot[];
|
|
25
|
+
readonly agents: readonly SkillRoot[];
|
|
26
|
+
}
|
|
27
|
+
export declare function skillRootsOf(cwd: string, hostFacts: SkillRootHostFacts): SkillRootsTable | undefined;
|
|
28
|
+
export interface SkillListing extends Omit<SkillOverrideSubject, 'disableModelInvocation'> {
|
|
29
|
+
readonly root?: SkillRoot;
|
|
30
|
+
readonly frontmatter?: SkillFrontmatter | null;
|
|
31
|
+
}
|
|
32
|
+
export interface SkillFrontmatter {
|
|
33
|
+
readonly description?: string;
|
|
34
|
+
readonly 'disable-model-invocation'?: boolean | 'true' | 'false';
|
|
35
|
+
}
|
|
36
|
+
type SourceRootsVerdictSubset = SourceRootsJudgedSubset | {
|
|
37
|
+
readonly state: 'unjudged';
|
|
38
|
+
};
|
|
39
|
+
interface SourceRootsJudgedSubset {
|
|
40
|
+
readonly state: 'judged';
|
|
41
|
+
readonly roots: readonly SourceRootVerdictSubset[];
|
|
42
|
+
}
|
|
43
|
+
interface SourceRootVerdictSubset {
|
|
44
|
+
readonly dir: string;
|
|
45
|
+
readonly trusted: boolean;
|
|
46
|
+
readonly why?: {
|
|
47
|
+
readonly kind: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export type SkillsViewEditable = {
|
|
51
|
+
readonly ok: true;
|
|
52
|
+
} | {
|
|
53
|
+
readonly ok: false;
|
|
54
|
+
readonly lockedBy: SkillOverrideLockSource;
|
|
55
|
+
};
|
|
56
|
+
export interface SkillsViewEntryBase {
|
|
57
|
+
readonly name: string;
|
|
58
|
+
readonly layer: SkillsViewLayer;
|
|
59
|
+
readonly effective: SkillOverrideEffective;
|
|
60
|
+
readonly editable: SkillsViewEditable;
|
|
61
|
+
}
|
|
62
|
+
export interface SkillsViewAppliedEntry extends SkillsViewEntryBase {
|
|
63
|
+
readonly status: 'applied';
|
|
64
|
+
readonly description?: string;
|
|
65
|
+
readonly nameOnly?: true;
|
|
66
|
+
}
|
|
67
|
+
export interface SkillsViewExcludedEntry extends SkillsViewEntryBase {
|
|
68
|
+
readonly status: 'excluded';
|
|
69
|
+
readonly reason: SkillsViewExcludedReason;
|
|
70
|
+
}
|
|
71
|
+
export type SkillsViewEntry = SkillsViewAppliedEntry | SkillsViewExcludedEntry;
|
|
72
|
+
export interface SkillsView {
|
|
73
|
+
readonly entries: readonly SkillsViewEntry[];
|
|
74
|
+
readonly withheldRoots: {
|
|
75
|
+
readonly untrusted: number;
|
|
76
|
+
readonly unconfirmed: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export declare function skillsViewOf(listings: readonly SkillListing[], layers: SkillOverrideLayers, trust: SourceRootsVerdictSubset | undefined): SkillsView;
|
|
80
|
+
export type SkillsEdit = {
|
|
81
|
+
readonly kind: 'set_override';
|
|
82
|
+
readonly name: string;
|
|
83
|
+
readonly state: SkillOverrideState;
|
|
84
|
+
readonly scope: SkillOverrideScope;
|
|
85
|
+
} | {
|
|
86
|
+
readonly kind: 'clear_override';
|
|
87
|
+
readonly name: string;
|
|
88
|
+
readonly scope: SkillOverrideScope;
|
|
89
|
+
};
|
|
90
|
+
export declare function skillsSetEditOf(entry: Pick<SkillsViewEntry, 'name'>, state: SkillOverrideState, scope: SkillOverrideScope): SkillsEdit;
|
|
91
|
+
export declare function skillsClearEditOf(entry: Pick<SkillsViewEntry, 'name' | 'effective'> & {
|
|
92
|
+
readonly editable?: SkillsViewEditable;
|
|
93
|
+
}): SkillsEdit | undefined;
|
|
94
|
+
export interface SkillOverrideWriteContext {
|
|
95
|
+
readonly subjects: readonly SkillOverrideSubject[];
|
|
96
|
+
readonly flagSettings?: SettingsDocument | null;
|
|
97
|
+
readonly session?: SkillOverrideLayers['session'];
|
|
98
|
+
readonly disabledSources?: SkillOverrideLayers['disabledSources'];
|
|
99
|
+
readonly bundledSkillsDisabledByEnv?: boolean;
|
|
100
|
+
}
|
|
101
|
+
export type SkillOverrideWritePlan = {
|
|
102
|
+
readonly ok: true;
|
|
103
|
+
readonly intent: LocalConfigIntent;
|
|
104
|
+
} | {
|
|
105
|
+
readonly ok: false;
|
|
106
|
+
readonly reason: LocalConfigRefusal;
|
|
107
|
+
};
|
|
108
|
+
export declare function skillOverrideWritePlan(edit: SkillsEdit, context: SkillOverrideWriteContext): SkillOverrideWritePlan;
|
|
109
|
+
export interface SkillCreateIntent {
|
|
110
|
+
readonly root: SkillRoot;
|
|
111
|
+
readonly name: string;
|
|
112
|
+
readonly content: string;
|
|
113
|
+
}
|
|
114
|
+
export interface SkillRemoveIntent {
|
|
115
|
+
readonly root: SkillRoot;
|
|
116
|
+
readonly name: string;
|
|
117
|
+
readonly date: string;
|
|
118
|
+
}
|
|
119
|
+
export type SkillFileEditPlan = {
|
|
120
|
+
readonly kind: 'pending';
|
|
121
|
+
};
|
|
122
|
+
export declare function skillCreatePlan(_intent: SkillCreateIntent): SkillFileEditPlan;
|
|
123
|
+
export declare function skillRemovePlan(_intent: SkillRemoveIntent): SkillFileEditPlan;
|
|
124
|
+
export {};
|