@sema-agent/client-core 0.112.0 → 0.113.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 +153 -0
- package/README.md +37 -24
- package/dist/adapt/arms.js +7 -1
- package/dist/adapt/textStream.d.ts +2 -0
- package/dist/adapt/textStream.js +27 -1
- package/dist/adapter/activeRunSelfHeal.d.ts +7 -5
- package/dist/adapter/activeRunSelfHeal.js +38 -66
- package/dist/adapter/downstream/eventToSdkMessage.js +4 -0
- package/dist/adapter/downstream/terminalToSdkResult.d.ts +8 -0
- package/dist/adapter/downstream/terminalToSdkResult.js +36 -1
- package/dist/adapter/runStream.d.ts +2 -12
- package/dist/adapter/runStream.js +46 -19
- package/dist/agentSession/engineAgentRegistryRead.js +2 -1
- package/dist/agentSession/engineSessionBackgroundStop.js +2 -2
- package/dist/attachmentOutcome.d.ts +35 -0
- package/dist/attachmentOutcome.js +192 -0
- package/dist/attachmentPathPlan.d.ts +67 -0
- package/dist/attachmentPathPlan.js +203 -0
- package/dist/attachmentRoute.d.ts +9 -1
- package/dist/attachmentRoute.js +23 -2
- package/dist/declared/supportFloorDeclared.d.ts +1 -1
- package/dist/declared/supportFloorDeclared.js +1 -0
- package/dist/deviceRebind.js +2 -3
- package/dist/displayUntrusted.js +126 -19
- package/dist/engineAddress.d.ts +1 -1
- package/dist/engineAddress.js +9 -6
- package/dist/engineErrorCodes.d.ts +3 -0
- package/dist/engineErrorCodes.js +4 -0
- package/dist/engineNoticeCodes.d.ts +34 -4
- package/dist/engineNoticeCodes.js +133 -6
- package/dist/engineUnavailable.d.ts +4 -2
- package/dist/engineUnavailable.js +99 -17
- package/dist/fleet/fleetLedger.d.ts +9 -3
- package/dist/fleet/fleetLedger.js +112 -16
- package/dist/fleet/fleetProjection.d.ts +5 -0
- package/dist/fleet/fleetProjection.js +9 -1
- package/dist/gateVocabulary.d.ts +7 -0
- package/dist/gateVocabulary.js +40 -14
- package/dist/generated/engineFactTables.d.ts +4 -2
- package/dist/generated/engineFactTables.js +198 -2
- package/dist/generated/engineNoticeTables.js +56 -8
- package/dist/generated/settingsSchemaFns.d.ts +7 -0
- package/dist/generated/settingsSchemaFns.js +11 -0
- package/dist/generated/settingsSchemaHash.d.ts +1 -0
- package/dist/generated/settingsSchemaHash.js +58 -0
- package/dist/generated/settingsSchemaOwnKeyRead.js +6 -1
- package/dist/generated/settingsSchemaTables.d.ts +3 -2
- package/dist/generated/settingsSchemaTables.js +14 -0
- package/dist/generated/settingsSchemaTightenVerdict.d.ts +1 -0
- package/dist/generated/settingsSchemaTightenVerdict.js +125 -0
- package/dist/headlessPermissionModeWire.d.ts +7 -2
- package/dist/headlessPermissionModeWire.js +77 -8
- package/dist/hitl/approvalDecisionDoor.d.ts +24 -0
- package/dist/hitl/approvalDecisionDoor.js +77 -0
- package/dist/hitl/approvalDelivery.d.ts +6 -0
- package/dist/hitl/approvalDelivery.js +57 -7
- package/dist/hitl/approvalResolution.d.ts +6 -3
- package/dist/hitl/approvalResolution.js +24 -2
- package/dist/hitl/approvalsFeed.js +1 -1
- package/dist/hitl/automaticAnswerVerdict.d.ts +1 -1
- package/dist/hitl/decisionSend.d.ts +7 -4
- package/dist/hitl/decisionSend.js +90 -41
- package/dist/hitl/frameRouter.d.ts +3 -3
- package/dist/hitl/frameRouter.js +5 -0
- package/dist/hitl/hitlBridge.d.ts +1 -0
- package/dist/hitl/hitlBridge.js +17 -4
- package/dist/hitl/hitlHostSurface.d.ts +3 -2
- package/dist/hitl/hitlHostSurface.js +5 -3
- package/dist/hitl/legacyApprovalShapes.d.ts +142 -0
- package/dist/hitl/legacyApprovalShapes.js +1 -0
- package/dist/hitl/livePendingAsk.d.ts +4 -4
- package/dist/hitl/livePendingAsk.js +5 -3
- package/dist/hitl/parkResolver.js +1 -1
- package/dist/hitl/persistedRulesWire.js +2 -2
- package/dist/hitl/planReviewCard.d.ts +4 -2
- package/dist/hitl/planReviewCard.js +66 -1
- package/dist/hitl/planReviewWire.d.ts +34 -2
- package/dist/hitl/planReviewWire.js +326 -150
- package/dist/hitl/sessionPolicyWire.js +16 -7
- package/dist/hitl/subagentSource.d.ts +1 -0
- package/dist/hitl/subagentSource.js +11 -0
- package/dist/hitl/toolApprovalWire.d.ts +34 -10
- package/dist/hitl/toolApprovalWire.js +182 -33
- package/dist/hookMatcherVerdict.d.ts +2 -1
- package/dist/hookMatcherVerdict.js +3 -2
- package/dist/hooksReaderGenerations.d.ts +8 -0
- package/dist/hooksReaderGenerations.js +49 -0
- package/dist/hooksWireCaps.js +43 -18
- package/dist/hostSettingsSource.d.ts +1 -1
- package/dist/hostSettingsSource.js +2 -2
- package/dist/hostTurnSettings.d.ts +2 -2
- package/dist/hostTurnSettings.js +87 -47
- package/dist/humanTurn.d.ts +2 -1
- package/dist/humanTurn.js +44 -13
- package/dist/humanTurnRead.d.ts +7 -0
- package/dist/humanTurnRead.js +23 -14
- package/dist/humanTurnSentences.js +3 -0
- package/dist/i18n/messages.en.d.ts +93 -5
- package/dist/i18n/messages.en.js +100 -12
- package/dist/i18n/messages.zh.js +110 -15
- package/dist/index.d.ts +29 -15
- package/dist/index.js +17 -9
- package/dist/liveModelCatalog.js +1 -0
- package/dist/liveQuestionStore.d.ts +2 -0
- package/dist/liveQuestionStore.js +7 -2
- package/dist/localConfig/kernel.d.ts +2 -1
- package/dist/localConfig/kernel.js +12 -18
- package/dist/localConfig/mcp/edit.js +25 -27
- package/dist/localConfig/mcp/servers.js +5 -8
- package/dist/localConfig/modelPool.d.ts +6 -1
- package/dist/localConfig/modelPool.js +104 -27
- package/dist/localConfig/modelPoolWords.d.ts +2 -0
- package/dist/localConfig/modelPoolWords.js +1 -0
- package/dist/localConfig/settingsWrite.js +1 -14
- package/dist/localConfig/skills.js +9 -16
- package/dist/localEngineSpawn.d.ts +29 -1
- package/dist/localEngineSpawn.js +62 -1
- package/dist/mcpLiveness.d.ts +1 -1
- package/dist/mcpProbeWire.js +2 -2
- package/dist/mcpReconnect.js +2 -2
- package/dist/model/catalogLoader.js +3 -17
- package/dist/model/onboardJudgement.d.ts +8 -0
- package/dist/model/onboardJudgement.js +8 -3
- package/dist/model/onboardSteps.d.ts +19 -0
- package/dist/model/onboardSteps.js +76 -0
- package/dist/notifications.js +20 -12
- package/dist/ownKey.d.ts +4 -0
- package/dist/ownKey.js +61 -0
- package/dist/pathShape.d.ts +14 -0
- package/dist/pathShape.js +44 -0
- package/dist/planReviewCardFacts.d.ts +3 -0
- package/dist/planReviewCardFacts.js +20 -3
- package/dist/planReviewOutcomeCause.d.ts +2 -0
- package/dist/planReviewOutcomeCause.js +12 -0
- package/dist/pluginHooksWire.d.ts +20 -8
- package/dist/pluginHooksWire.js +204 -86
- package/dist/prepareRefusal.d.ts +2 -0
- package/dist/prepareRefusal.js +11 -1
- package/dist/request/taskRequest.js +3 -1
- package/dist/resultFrameKeys.d.ts +1 -0
- package/dist/resultFrameKeys.js +3 -0
- package/dist/resumeRefusalCopy.js +3 -1
- package/dist/retryStatus.d.ts +11 -1
- package/dist/retryStatus.js +15 -4
- package/dist/runTerminal.d.ts +1 -0
- package/dist/runTerminal.js +15 -1
- package/dist/sdkWireTransit.d.ts +1 -1
- package/dist/seatContract.d.ts +12 -3
- package/dist/seatContract.js +24 -13
- package/dist/sessionEngine.js +1 -1
- package/dist/sessionHooksRoster.js +8 -6
- package/dist/sessionIdSegment.d.ts +0 -1
- package/dist/sessionIdSegment.js +1 -3
- package/dist/sessionMemoryErase.js +2 -2
- package/dist/sessionMemoryStatus.js +2 -1
- package/dist/sessionOccupant.d.ts +29 -0
- package/dist/sessionOccupant.js +78 -0
- package/dist/settingsHooksSalvage.d.ts +4 -1
- package/dist/settingsHooksSalvage.js +22 -9
- package/dist/skillOverrideChain.d.ts +3 -0
- package/dist/skillOverrideChain.js +31 -4
- package/dist/skillsWireCaps.d.ts +16 -2
- package/dist/skillsWireCaps.js +47 -20
- package/dist/subagent/agentStateDetail.js +32 -8
- package/dist/subagent/engineCompactWire.js +48 -36
- package/dist/subagent/engineDelegatedPrompt.d.ts +3 -2
- package/dist/subagent/engineDelegatedPrompt.js +65 -28
- package/dist/subagentEditOutcomes.d.ts +9 -0
- package/dist/subagentEditOutcomes.js +43 -0
- package/dist/supportFloor.d.ts +2 -1
- package/dist/supportFloor.js +1 -1
- package/dist/toolResult.js +4 -2
- package/dist/toolRoster.d.ts +1 -0
- package/dist/toolRoster.js +1 -0
- package/dist/usageAnalytics.js +2 -1
- package/dist/userAttachmentEnvelope.d.ts +11 -0
- package/dist/userAttachmentEnvelope.js +7 -2
- package/dist/userAttachmentSeat.d.ts +7 -1
- package/dist/userAttachmentSeat.js +44 -7
- package/dist/wiringInstructionsAttribution.js +8 -2
- package/docs/INTEGRATION-CLIENTS.md +1654 -16
- package/package.json +5 -5
|
@@ -8,11 +8,11 @@ import { computeDeleteBlockers, computeDeleteWarnings, resolveEntryVision } from
|
|
|
8
8
|
import { routeKeyOf } from '../coreValuePorts.js';
|
|
9
9
|
import { applyProbeToEntry } from '../modelCapabilityProbe.js';
|
|
10
10
|
import { KEY_SLOT_PREFIX, keyEnvNameForEntry, onboardWriteVerdict, poolEntryNameOf, onboardBaseUrlProblem, onboardEntryCredentialIssue, onboardKeyCarriedBy, onboardRedactKey, } from '../model/onboardJudgement.js';
|
|
11
|
-
import { ownSnapshotRecord, ownSnapshotRecordFaithful, readOwnDataValue } from '../ownKey.js';
|
|
11
|
+
import { ownDataField, ownSnapshotRecord, ownSnapshotRecordFaithful, putOwnKey, readOwnDataValue, sameJson } from '../ownKey.js';
|
|
12
12
|
import { msg, renderMessage } from '../i18n/translate.js';
|
|
13
13
|
import { applyLocalConfigIntent, previewLocalConfigIntent } from './kernel.js';
|
|
14
14
|
import { settingsWritePlan } from './settingsWrite.js';
|
|
15
|
-
import { MODEL_POOL_CHANNEL_SOURCES, MODEL_POOL_EDIT_KINDS, MODEL_POOL_MAX_BATCH } from './modelPoolWords.js';
|
|
15
|
+
import { MODEL_POOL_CHANNEL_SOURCES, MODEL_POOL_EDIT_KINDS, MODEL_POOL_MAX_BATCH, MODEL_POOL_READINGS } from './modelPoolWords.js';
|
|
16
16
|
export { MODEL_POOL_EDIT_KINDS, MODEL_POOL_CHANNEL_SOURCES, MODEL_POOL_CREDENTIAL_KINDS, MODEL_POOL_COMPLETENESS, MODEL_POOL_MAX_BATCH, MODEL_POOL_PROBE_STATES, MODEL_POOL_DEFAULT_KEEP_REASONS } from './modelPoolWords.js';
|
|
17
17
|
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
18
18
|
function own(v, key) {
|
|
@@ -30,19 +30,6 @@ function cloneDoc(v) {
|
|
|
30
30
|
return snap === undefined ? undefined : JSON.parse(JSON.stringify(snap));
|
|
31
31
|
}
|
|
32
32
|
const freezeDoc = (v) => ownSnapshotRecord(v) ?? Object.freeze({});
|
|
33
|
-
function sameJson(a, b) {
|
|
34
|
-
if (a === b)
|
|
35
|
-
return true;
|
|
36
|
-
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
|
|
37
|
-
return false;
|
|
38
|
-
if (Array.isArray(a) !== Array.isArray(b))
|
|
39
|
-
return false;
|
|
40
|
-
if (Array.isArray(a) && Array.isArray(b))
|
|
41
|
-
return a.length === b.length && a.every((x, i) => sameJson(x, b[i]));
|
|
42
|
-
const ka = Object.keys(a);
|
|
43
|
-
const kb = Object.keys(b);
|
|
44
|
-
return ka.length === kb.length && ka.every((k) => Object.hasOwn(b, k) && sameJson(a[k], b[k]));
|
|
45
|
-
}
|
|
46
33
|
const en = (key, params) => renderMessage(msg(key, params));
|
|
47
34
|
const strOf = (v) => (typeof v === 'string' && v !== '' ? v : undefined);
|
|
48
35
|
const posInt = (v) => typeof v === 'number' && Number.isSafeInteger(v) && v > 0;
|
|
@@ -204,10 +191,16 @@ function shadowDisclosuresOf(settings) {
|
|
|
204
191
|
const model = own(settings, 'model');
|
|
205
192
|
return typeof model === 'string' && model.trim() !== '' ? Object.freeze([Object.freeze({ kind: 'shadowed_by', layer: 'userSettings', detail: 'model' })]) : Object.freeze([]);
|
|
206
193
|
}
|
|
194
|
+
function shadowUnknownDisclosures() {
|
|
195
|
+
return Object.freeze([Object.freeze({ kind: 'shadow_unknown', layer: 'userSettings', detail: 'model' })]);
|
|
196
|
+
}
|
|
197
|
+
function shadowOf(settings, reading) {
|
|
198
|
+
return reading === 'unreadable' ? shadowUnknownDisclosures() : shadowDisclosuresOf(settings);
|
|
199
|
+
}
|
|
207
200
|
const noneDefault = (disclosures) => Object.freeze({ kind: 'none', disclosures });
|
|
208
201
|
const unknownDefault = (disclosures) => Object.freeze({ kind: 'unknown', disclosures });
|
|
209
202
|
export function effectiveDefaultModelOf(input) {
|
|
210
|
-
const disclosures =
|
|
203
|
+
const disclosures = shadowOf(own(input, 'userSettings'), own(input, 'userSettingsReading'));
|
|
211
204
|
try {
|
|
212
205
|
const raw = own(input, 'modelsDoc');
|
|
213
206
|
if (raw === null || raw === undefined)
|
|
@@ -659,7 +652,7 @@ function planUpdate(edit, modelsRaw, settingsRaw) {
|
|
|
659
652
|
m['maxTokens'] = max;
|
|
660
653
|
return okPlan(modelsRaw, doc, settingsRaw, settingsOrEmpty(settingsRaw), {});
|
|
661
654
|
}
|
|
662
|
-
function planSetDefault(name, modelsRaw, settingsRaw) {
|
|
655
|
+
function planSetDefault(name, modelsRaw, settingsRaw, settingsReading) {
|
|
663
656
|
if (typeof name !== 'string' || name === '')
|
|
664
657
|
return refuse('invalid_request');
|
|
665
658
|
const mread = modelsDocOf(modelsRaw);
|
|
@@ -673,7 +666,7 @@ function planSetDefault(name, modelsRaw, settingsRaw) {
|
|
|
673
666
|
const roles = isRecord(doc['roles']) ? doc['roles'] : {};
|
|
674
667
|
roles['default'] = { model: name };
|
|
675
668
|
doc['roles'] = roles;
|
|
676
|
-
return okPlan(modelsRaw, doc, settingsRaw, settingsOrEmpty(settingsRaw), { disclosures:
|
|
669
|
+
return okPlan(modelsRaw, doc, settingsRaw, settingsOrEmpty(settingsRaw), { disclosures: shadowOf(settingsRaw, settingsReading) });
|
|
677
670
|
}
|
|
678
671
|
function planImportEnv(modelsRaw, settingsRaw, env) {
|
|
679
672
|
const mread = modelsDocOf(modelsRaw);
|
|
@@ -869,7 +862,7 @@ function envOf(v) {
|
|
|
869
862
|
}
|
|
870
863
|
return out;
|
|
871
864
|
}
|
|
872
|
-
function planWith(edit, modelsDoc, settingsDoc, effectiveEnv, pins, declineDefault = false) {
|
|
865
|
+
function planWith(edit, modelsDoc, settingsDoc, effectiveEnv, pins, declineDefault = false, settingsReading) {
|
|
873
866
|
try {
|
|
874
867
|
const kind = own(edit, 'kind');
|
|
875
868
|
const env = envOf(effectiveEnv);
|
|
@@ -887,7 +880,7 @@ function planWith(edit, modelsDoc, settingsDoc, effectiveEnv, pins, declineDefau
|
|
|
887
880
|
case 'remove':
|
|
888
881
|
return planRemove(own(edit, 'name'), modelsDoc, settingsDoc);
|
|
889
882
|
case 'setDefault':
|
|
890
|
-
return planSetDefault(own(edit, 'name'), modelsDoc, settingsDoc);
|
|
883
|
+
return planSetDefault(own(edit, 'name'), modelsDoc, settingsDoc, settingsReading);
|
|
891
884
|
case 'importEnvModels':
|
|
892
885
|
return planImportEnv(modelsDoc, settingsDoc, env);
|
|
893
886
|
case 'bindTier':
|
|
@@ -937,7 +930,7 @@ export function modelPoolIntentOf(edit, effectiveEnv, probe) {
|
|
|
937
930
|
const settings = docFrom(input.fresh.userSettings);
|
|
938
931
|
if (models === 'unreadable' || (settings === 'unreadable' && needsSettings))
|
|
939
932
|
return undefined;
|
|
940
|
-
return { models, settings: settings === 'unreadable' ? null : settings };
|
|
933
|
+
return { models, settings: settings === 'unreadable' ? null : settings, settingsReading: settings === 'unreadable' ? 'unreadable' : undefined };
|
|
941
934
|
};
|
|
942
935
|
const modelsStep = (role, withPins) => ({
|
|
943
936
|
doc: 'models',
|
|
@@ -952,7 +945,7 @@ export function modelPoolIntentOf(edit, effectiveEnv, probe) {
|
|
|
952
945
|
const pins = pinsRaw === undefined ? undefined : pinsOf(pinsRaw);
|
|
953
946
|
if (pinsRaw !== undefined && pins === undefined)
|
|
954
947
|
return { kind: 'refuse', reason: 'invalid_request' };
|
|
955
|
-
const p = record(planWith(edit, r.models, r.settings, effectiveEnv, pins));
|
|
948
|
+
const p = record(planWith(edit, r.models, r.settings, effectiveEnv, pins, false, r.settingsReading));
|
|
956
949
|
if (!p.ok)
|
|
957
950
|
return refuseStep(p);
|
|
958
951
|
const carry = { released: [...p.releasedKeySlots] };
|
|
@@ -1327,11 +1320,91 @@ function providersOf() {
|
|
|
1327
1320
|
});
|
|
1328
1321
|
}));
|
|
1329
1322
|
}
|
|
1323
|
+
function envHasDroppedKeys(given, snap) {
|
|
1324
|
+
try {
|
|
1325
|
+
if (typeof given !== 'object' || given === null)
|
|
1326
|
+
return true;
|
|
1327
|
+
for (const k of Reflect.ownKeys(given)) {
|
|
1328
|
+
if (typeof k !== 'string' || Object.hasOwn(snap, k))
|
|
1329
|
+
continue;
|
|
1330
|
+
const d = Object.getOwnPropertyDescriptor(given, k);
|
|
1331
|
+
if (d === undefined || d.enumerable !== true || !Object.hasOwn(d, 'value') || d.value !== undefined)
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
catch {
|
|
1337
|
+
return true;
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
function viewEnvOf(readings) {
|
|
1341
|
+
let given;
|
|
1342
|
+
try {
|
|
1343
|
+
given = typeof readings === 'object' && readings !== null ? ownDataField(readings, 'effectiveEnv') : undefined;
|
|
1344
|
+
}
|
|
1345
|
+
catch {
|
|
1346
|
+
return { reading: 'unreadable', env: {} };
|
|
1347
|
+
}
|
|
1348
|
+
if (given === undefined)
|
|
1349
|
+
return { reading: 'absent', env: {} };
|
|
1350
|
+
const snap = ownSnapshotRecordFaithful(given);
|
|
1351
|
+
if (snap === undefined || envHasDroppedKeys(given, snap))
|
|
1352
|
+
return { reading: 'unreadable', env: {} };
|
|
1353
|
+
const env = {};
|
|
1354
|
+
for (const k of Object.keys(snap)) {
|
|
1355
|
+
const val = snap[k];
|
|
1356
|
+
if (typeof val !== 'string')
|
|
1357
|
+
return { reading: 'unreadable', env: {} };
|
|
1358
|
+
putOwnKey(env, k, val);
|
|
1359
|
+
}
|
|
1360
|
+
return { reading: 'read', env };
|
|
1361
|
+
}
|
|
1362
|
+
function viewSettingsOf(readings) {
|
|
1363
|
+
try {
|
|
1364
|
+
const sr = typeof readings === 'object' && readings !== null ? ownDataField(readings, 'userSettings') : undefined;
|
|
1365
|
+
if (sr === undefined)
|
|
1366
|
+
return { reading: 'absent', raw: null };
|
|
1367
|
+
if (typeof sr !== 'object' || sr === null)
|
|
1368
|
+
return { reading: 'unreadable', raw: null };
|
|
1369
|
+
const status = ownDataField(sr, 'status');
|
|
1370
|
+
if (status === 'absent')
|
|
1371
|
+
return { reading: 'absent', raw: null };
|
|
1372
|
+
if (status !== 'loaded')
|
|
1373
|
+
return { reading: 'unreadable', raw: null };
|
|
1374
|
+
const doc = ownDataField(sr, 'doc');
|
|
1375
|
+
if (typeof doc !== 'object' || doc === null || Array.isArray(doc))
|
|
1376
|
+
return { reading: 'unreadable', raw: null };
|
|
1377
|
+
const checked = settingsDocOf(doc);
|
|
1378
|
+
if (!checked.ok)
|
|
1379
|
+
return { reading: 'unreadable', raw: null };
|
|
1380
|
+
return { reading: 'read', raw: checked.doc };
|
|
1381
|
+
}
|
|
1382
|
+
catch {
|
|
1383
|
+
return { reading: 'unreadable', raw: null };
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
export function modelPoolEnvReadingOf(view) {
|
|
1387
|
+
if (typeof view !== 'object' || view === null)
|
|
1388
|
+
return 'unreadable';
|
|
1389
|
+
try {
|
|
1390
|
+
const d = Object.getOwnPropertyDescriptor(view, 'effectiveEnv');
|
|
1391
|
+
if (d === undefined)
|
|
1392
|
+
return 'not_reported';
|
|
1393
|
+
if (!Object.hasOwn(d, 'value'))
|
|
1394
|
+
return 'unreadable';
|
|
1395
|
+
const word = d.value;
|
|
1396
|
+
if (word === undefined)
|
|
1397
|
+
return 'not_reported';
|
|
1398
|
+
return MODEL_POOL_READINGS.find((w) => w === word) ?? 'unreadable';
|
|
1399
|
+
}
|
|
1400
|
+
catch {
|
|
1401
|
+
return 'unreadable';
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1330
1404
|
export function modelPoolViewOf(readings) {
|
|
1331
|
-
const env =
|
|
1405
|
+
const { reading: envReading, env } = viewEnvOf(readings);
|
|
1332
1406
|
const mr = own(readings, 'models');
|
|
1333
|
-
const
|
|
1334
|
-
const settingsRaw = own(sr, 'status') === 'loaded' ? own(sr, 'doc') : null;
|
|
1407
|
+
const { reading: settingsReading, raw: settingsRaw } = viewSettingsOf(readings);
|
|
1335
1408
|
const settings = settingsDocOf(settingsRaw);
|
|
1336
1409
|
const sdoc = settings.ok ? settings.doc : {};
|
|
1337
1410
|
const legacyTierSettings = sdoc['semaTierGroups'] !== undefined || sdoc['semaRosters'] !== undefined;
|
|
@@ -1344,10 +1417,12 @@ export function modelPoolViewOf(readings) {
|
|
|
1344
1417
|
entries: Object.freeze([]),
|
|
1345
1418
|
roles: Object.freeze([]),
|
|
1346
1419
|
tierGroups: Object.freeze([]),
|
|
1347
|
-
defaultModel: catalog === 'absent' ? effectiveDefaultModelOf({ modelsDoc: null, userSettings: settingsRaw }) : unknownDefault(
|
|
1420
|
+
defaultModel: catalog === 'absent' ? effectiveDefaultModelOf({ modelsDoc: null, userSettings: settingsRaw, userSettingsReading: settingsReading }) : unknownDefault(shadowOf(settingsRaw, settingsReading)),
|
|
1348
1421
|
legacyTierSettings,
|
|
1349
1422
|
orphanKeySlots: catalog === 'absent' ? orphanKeySlotsOf([], settingsEnv).length : 0,
|
|
1350
1423
|
envModels: Object.freeze(catalog === 'unreadable' ? [] : [env['MODEL_ID'], env['MODEL_CHEAP_ID']].filter((v) => typeof v === 'string' && v.trim() !== '')),
|
|
1424
|
+
effectiveEnv: envReading,
|
|
1425
|
+
userSettings: settingsReading,
|
|
1351
1426
|
providers: providersOf(),
|
|
1352
1427
|
});
|
|
1353
1428
|
if (status === 'absent')
|
|
@@ -1363,7 +1438,7 @@ export function modelPoolViewOf(readings) {
|
|
|
1363
1438
|
const items = Array.isArray(list) ? list : [];
|
|
1364
1439
|
const { rows: good, unreadable } = catalogRowsOf(items);
|
|
1365
1440
|
const doc = { ...raw, models: good };
|
|
1366
|
-
const def = effectiveDefaultModelOf({ modelsDoc: raw, userSettings: settingsRaw });
|
|
1441
|
+
const def = effectiveDefaultModelOf({ modelsDoc: raw, userSettings: settingsRaw, userSettingsReading: settingsReading });
|
|
1367
1442
|
const blockDoc = withDefaultFolded(doc);
|
|
1368
1443
|
const groups = tierGroupsOf(raw).filter((g) => typeof g['name'] === 'string');
|
|
1369
1444
|
const active = typeof raw['activeTierGroup'] === 'string' ? raw['activeTierGroup'] : undefined;
|
|
@@ -1452,6 +1527,8 @@ export function modelPoolViewOf(readings) {
|
|
|
1452
1527
|
legacyTierSettings,
|
|
1453
1528
|
orphanKeySlots: items.every(isRecord) ? orphanKeySlotsOf(items, settingsEnv).length : 0,
|
|
1454
1529
|
envModels: Object.freeze(good.some(isEnabled) ? [] : [env['MODEL_ID'], env['MODEL_CHEAP_ID']].filter((v) => typeof v === 'string' && v.trim() !== '')),
|
|
1530
|
+
effectiveEnv: envReading,
|
|
1531
|
+
userSettings: settingsReading,
|
|
1455
1532
|
providers: providersOf(),
|
|
1456
1533
|
});
|
|
1457
1534
|
}
|
|
@@ -11,3 +11,5 @@ export declare const MODEL_POOL_DEFAULT_KEEP_REASONS: readonly ["has_default", "
|
|
|
11
11
|
export type ModelPoolDefaultKeepReason = (typeof MODEL_POOL_DEFAULT_KEEP_REASONS)[number];
|
|
12
12
|
export declare const MODEL_POOL_COMPLETENESS: readonly ["complete", "catalog_incomplete"];
|
|
13
13
|
export type ModelPoolCompleteness = (typeof MODEL_POOL_COMPLETENESS)[number];
|
|
14
|
+
export declare const MODEL_POOL_READINGS: readonly ["read", "absent", "unreadable"];
|
|
15
|
+
export type ModelPoolViewReading = (typeof MODEL_POOL_READINGS)[number];
|
|
@@ -18,3 +18,4 @@ export const MODEL_POOL_MAX_BATCH = 64;
|
|
|
18
18
|
export const MODEL_POOL_PROBE_STATES = Object.freeze(['verified', 'unverified', 'unprobed']);
|
|
19
19
|
export const MODEL_POOL_DEFAULT_KEEP_REASONS = Object.freeze(['has_default', 'existing_unknown', 'declined', 'nothing_added', 'none_verified']);
|
|
20
20
|
export const MODEL_POOL_COMPLETENESS = Object.freeze(['complete', 'catalog_incomplete']);
|
|
21
|
+
export const MODEL_POOL_READINGS = Object.freeze(['read', 'absent', 'unreadable']);
|
|
@@ -2,7 +2,7 @@ import { SETTINGS_UNIT_PLACES, SETTINGS_WORKSPACE_TRUST_STATES } from '../genera
|
|
|
2
2
|
import { SETTINGS_IS_RESERVED_MEMBER_NAME } from '../generated/settingsSchemaFns.js';
|
|
3
3
|
import { layerAdmissionWord } from '../settingsLayerAdmission.js';
|
|
4
4
|
import { KEY_SLOT_PREFIX } from '../model/onboardJudgement.js';
|
|
5
|
-
import { ownSnapshotRecord, readOwnDataValue } from '../ownKey.js';
|
|
5
|
+
import { ownSnapshotRecord, readOwnDataValue, sameJson } from '../ownKey.js';
|
|
6
6
|
import { SKILL_OVERRIDE_STATES } from '../skillOverrideChain.js';
|
|
7
7
|
const unitKey = (unit) => SETTINGS_UNIT_PLACES[unit].path;
|
|
8
8
|
const SKILL_OVERRIDE_WORDS = SKILL_OVERRIDE_STATES;
|
|
@@ -93,19 +93,6 @@ function listWith(current, name, present) {
|
|
|
93
93
|
return list.filter((x) => x !== name);
|
|
94
94
|
return list.includes(name) ? list : [...list, name];
|
|
95
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
96
|
export function settingsWritePlan(input) {
|
|
110
97
|
try {
|
|
111
98
|
if (!isPlainRecord(input))
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SETTINGS_IS_RESERVED_MEMBER_NAME } from '../generated/settingsSchemaFns.js';
|
|
2
2
|
import { readOwnDataValue, appendOwnElement } from '../ownKey.js';
|
|
3
|
-
import { SKILL_OVERRIDE_STATES, effectiveOfShaped, lockOfShaped, lowerTierOf, ownValueIn, secondaryNamesOf, bareNameOf, shapeSkillLayers, shapeSkillSubject, stateAt, withLayerDoc, } from '../skillOverrideChain.js';
|
|
3
|
+
import { LIST_BUDGET, SKILL_OVERRIDE_STATES, effectiveOfShaped, lockOfShaped, lowerTierOf, ownValueIn, secondaryNamesOf, bareNameOf, shapeSkillLayers, shapeSkillSubject, stateAt, withLayerDoc, } from '../skillOverrideChain.js';
|
|
4
4
|
import { settingsWritePlan } from './settingsWrite.js';
|
|
5
|
-
import {
|
|
5
|
+
import { pathShapeOf, PATH_LENGTH_LIMIT } from '../pathShape.js';
|
|
6
6
|
import { slotReadOf } from '../wireFailureShape.js';
|
|
7
7
|
import { SKILL_ROOT_LAYERS, SKILL_ROOT_KINDS, SKILL_OVERRIDE_SCOPES } from './skillsWords.js';
|
|
8
8
|
function own(v, key) {
|
|
@@ -16,7 +16,6 @@ function own(v, key) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
19
|
-
const LIST_BUDGET = 4096;
|
|
20
19
|
function listOf(v) {
|
|
21
20
|
if (!Array.isArray(v))
|
|
22
21
|
return [];
|
|
@@ -30,24 +29,18 @@ function listOf(v) {
|
|
|
30
29
|
}
|
|
31
30
|
const TRUST_LAYERS = ['project', 'additional'];
|
|
32
31
|
function pathFormOf(raw) {
|
|
33
|
-
if (typeof raw !== 'string' || raw
|
|
32
|
+
if (typeof raw !== 'string' || raw.length > PATH_LENGTH_LIMIT)
|
|
34
33
|
return undefined;
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
else if (/^[A-Za-z]:[\\/]/.test(raw))
|
|
40
|
-
floor = raw.slice(0, 3);
|
|
41
|
-
else if (/^\\\\[^\\/]+[\\/][^\\/]+/.test(raw))
|
|
42
|
-
floor = raw.match(/^\\\\[^\\/]+[\\/][^\\/]+/)[0];
|
|
43
|
-
else
|
|
34
|
+
const shape = pathShapeOf(raw);
|
|
35
|
+
if (shape === undefined || shape.kind === 'relative' || shape.hasDotSegment || shape.hasEmptySegment)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (shape.kind === 'unc' && shape.names.length > 0)
|
|
44
38
|
return undefined;
|
|
39
|
+
const sep = raw.includes('\\') && !raw.includes('/') ? '\\' : '/';
|
|
40
|
+
const floor = shape.root;
|
|
45
41
|
let path = raw;
|
|
46
42
|
while (path.length > floor.length && (path.endsWith('/') || path.endsWith('\\')))
|
|
47
43
|
path = path.slice(0, -1);
|
|
48
|
-
const rest = path.slice(floor.length);
|
|
49
|
-
if (rest !== '' && rest.split(/[\\/]/).some((seg) => seg === '' || isDotSegment(seg)))
|
|
50
|
-
return undefined;
|
|
51
44
|
return { sep, path, floor };
|
|
52
45
|
}
|
|
53
46
|
const joinPath = (f, ...segs) => (f.path === f.floor && /[\\/]$/.test(f.floor) ? f.path + segs.join(f.sep) : [f.path, ...segs].join(f.sep));
|
|
@@ -13,6 +13,9 @@ export type LocalEngineSpawnValue = {
|
|
|
13
13
|
} | {
|
|
14
14
|
readonly kind: 'derived';
|
|
15
15
|
readonly from: LocalEngineSpawnDerived;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: 'gated';
|
|
18
|
+
readonly value: string;
|
|
16
19
|
};
|
|
17
20
|
export interface LocalEngineSpawnEnvRow {
|
|
18
21
|
readonly key: string;
|
|
@@ -25,6 +28,28 @@ export declare const LOCAL_ENGINE_SPAWN_SHAPE: Readonly<{
|
|
|
25
28
|
readonly detachedSession: true;
|
|
26
29
|
readonly stdio: "engine-log-file";
|
|
27
30
|
}>;
|
|
31
|
+
export declare const LOCAL_ENGINE_SEED_REFUSALS: readonly ["policy-unreadable", "bind-not-acknowledged"];
|
|
32
|
+
export type LocalEngineSeedRefusal = (typeof LOCAL_ENGINE_SEED_REFUSALS)[number];
|
|
33
|
+
export type LocalEngineBindRefusal = Extract<LocalEngineSeedRefusal, 'bind-not-acknowledged'>;
|
|
34
|
+
export declare const LOCAL_ENGINE_BIND_DISCLOSURES: readonly ["bind-acknowledged"];
|
|
35
|
+
export type LocalEngineBindDisclosure = (typeof LOCAL_ENGINE_BIND_DISCLOSURES)[number];
|
|
36
|
+
export declare function localEngineSeedRefusalCodeOf(refusal: string): string | undefined;
|
|
37
|
+
export interface LocalEngineBindGateInput {
|
|
38
|
+
readonly requested?: string | undefined;
|
|
39
|
+
readonly acknowledged?: boolean | undefined;
|
|
40
|
+
}
|
|
41
|
+
export interface LocalEngineBindPass {
|
|
42
|
+
readonly kind: 'pass';
|
|
43
|
+
readonly handed: string | undefined;
|
|
44
|
+
readonly disclose: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface LocalEngineBindRefuse {
|
|
47
|
+
readonly kind: 'refuse';
|
|
48
|
+
readonly reason: LocalEngineBindRefusal;
|
|
49
|
+
}
|
|
50
|
+
export type LocalEngineBindGate = LocalEngineBindPass | LocalEngineBindRefuse;
|
|
51
|
+
export declare function localEngineBindGateOf(input: LocalEngineBindGateInput): LocalEngineBindGate;
|
|
52
|
+
export declare function localEngineBindSentence(gate: LocalEngineBindGate, switchKey: string, lang?: UiLanguage): string | undefined;
|
|
28
53
|
export declare function localEngineOperatorSingleUserOf(inherited: unknown): 'true' | undefined;
|
|
29
54
|
export interface LocalEngineBudgets {
|
|
30
55
|
readonly storeLockWaitMs: number;
|
|
@@ -41,6 +66,7 @@ export interface LocalEngineSpawnEnvInput {
|
|
|
41
66
|
readonly inherited: unknown;
|
|
42
67
|
readonly paths: LocalEngineSpawnPaths;
|
|
43
68
|
readonly hostBits: unknown;
|
|
69
|
+
readonly bind?: LocalEngineBindGate | undefined;
|
|
44
70
|
}
|
|
45
71
|
export interface LocalEngineSpawnApplied {
|
|
46
72
|
readonly key: string;
|
|
@@ -72,6 +98,7 @@ export interface LocalEngineSeedInput {
|
|
|
72
98
|
readonly layers: LocalEngineSettingsLayers;
|
|
73
99
|
readonly topLevel: unknown;
|
|
74
100
|
readonly platform: 'posix' | 'win32';
|
|
101
|
+
readonly bindAcknowledged?: boolean | undefined;
|
|
75
102
|
}
|
|
76
103
|
export interface LocalEngineSeedFrom {
|
|
77
104
|
readonly key: string;
|
|
@@ -85,7 +112,8 @@ export interface LocalEngineSeed {
|
|
|
85
112
|
readonly env: Readonly<Record<string, string>>;
|
|
86
113
|
readonly from: readonly LocalEngineSeedFrom[];
|
|
87
114
|
readonly dropped: readonly LocalEngineSeedDropped[];
|
|
88
|
-
readonly
|
|
115
|
+
readonly bind: LocalEngineBindGate;
|
|
116
|
+
readonly refuse?: LocalEngineSeedRefusal;
|
|
89
117
|
}
|
|
90
118
|
export declare function localEngineSeedEnv(input: LocalEngineSeedInput): LocalEngineSeed;
|
|
91
119
|
export type LocalEnginePrincipal = {
|
package/dist/localEngineSpawn.js
CHANGED
|
@@ -67,7 +67,9 @@ function freezeRecord(rows) {
|
|
|
67
67
|
Object.defineProperty(out, k, { value: v, enumerable: true, writable: true, configurable: true });
|
|
68
68
|
return Object.freeze(out);
|
|
69
69
|
}
|
|
70
|
+
const BIND_DEFAULT = '127.0.0.1';
|
|
70
71
|
const lit = (value) => Object.freeze({ kind: 'literal', value });
|
|
72
|
+
const gated = (value) => Object.freeze({ kind: 'gated', value });
|
|
71
73
|
const del = Object.freeze({ kind: 'delete' });
|
|
72
74
|
const slot = (s) => Object.freeze({ kind: 'path', slot: s });
|
|
73
75
|
const derived = (from) => Object.freeze({ kind: 'derived', from });
|
|
@@ -78,7 +80,8 @@ export const LOCAL_ENGINE_SPAWN_ENV = Object.freeze([
|
|
|
78
80
|
row('ENGINE_AUTO_EXIT', lit('true'), true),
|
|
79
81
|
row('SEMA_PARENT_PID', del, false),
|
|
80
82
|
row('SEMA_ENGINE_PARENT_PID', del, false),
|
|
81
|
-
row('BIND_HOST',
|
|
83
|
+
row('BIND_HOST', gated(BIND_DEFAULT), false),
|
|
84
|
+
row('BIND_HOST_INSECURE_SELF_SPAWN', del, false),
|
|
82
85
|
row('DB_BACKEND', lit('local'), false),
|
|
83
86
|
row('CONFIG_PROVIDER', lit('local'), false),
|
|
84
87
|
row('REMOTE_EXEC', lit('host'), true),
|
|
@@ -94,6 +97,52 @@ export const LOCAL_ENGINE_SPAWN_ENV = Object.freeze([
|
|
|
94
97
|
]);
|
|
95
98
|
export const LOCAL_ENGINE_HOST_BITS = Object.freeze(['PORT', 'SERVICE_AUTH_TOKENS', 'ELECTRON_RUN_AS_NODE', 'NODE_ENV', 'HOST_SHELL_PATH']);
|
|
96
99
|
export const LOCAL_ENGINE_SPAWN_SHAPE = Object.freeze({ detachedSession: true, stdio: 'engine-log-file' });
|
|
100
|
+
export const LOCAL_ENGINE_SEED_REFUSALS = Object.freeze(['policy-unreadable', 'bind-not-acknowledged']);
|
|
101
|
+
export const LOCAL_ENGINE_BIND_DISCLOSURES = Object.freeze(['bind-acknowledged']);
|
|
102
|
+
export function localEngineSeedRefusalCodeOf(refusal) {
|
|
103
|
+
return LOCAL_ENGINE_SEED_REFUSALS.includes(refusal) ? refusal.replace(/-/g, '_') : undefined;
|
|
104
|
+
}
|
|
105
|
+
export function localEngineBindGateOf(input) {
|
|
106
|
+
const raw = own(input, 'requested');
|
|
107
|
+
const requested = typeof raw === 'string' ? raw.trim() : '';
|
|
108
|
+
if (requested === '' || requested === BIND_DEFAULT)
|
|
109
|
+
return Object.freeze({ kind: 'pass', handed: undefined, disclose: false });
|
|
110
|
+
if (own(input, 'acknowledged') === true)
|
|
111
|
+
return Object.freeze({ kind: 'pass', handed: requested, disclose: true });
|
|
112
|
+
return Object.freeze({ kind: 'refuse', reason: 'bind-not-acknowledged' });
|
|
113
|
+
}
|
|
114
|
+
function bindSentenceKeyOf(word) {
|
|
115
|
+
switch (word) {
|
|
116
|
+
case 'bind-not-acknowledged':
|
|
117
|
+
return 'localEngine.bindNotAcknowledged';
|
|
118
|
+
case 'bind-acknowledged':
|
|
119
|
+
return 'localEngine.bindAcknowledged';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export function localEngineBindSentence(gate, switchKey, lang) {
|
|
123
|
+
try {
|
|
124
|
+
const kind = own(gate, 'kind');
|
|
125
|
+
if (kind === 'refuse') {
|
|
126
|
+
if (own(gate, 'reason') !== 'bind-not-acknowledged')
|
|
127
|
+
return undefined;
|
|
128
|
+
if (typeof switchKey !== 'string' || !/^[^\s\p{C}]{1,128}$/u.test(switchKey))
|
|
129
|
+
return undefined;
|
|
130
|
+
return renderMessage(msg(bindSentenceKeyOf('bind-not-acknowledged'), { switchKey }), lang);
|
|
131
|
+
}
|
|
132
|
+
if (kind === 'pass' && own(gate, 'disclose') === true)
|
|
133
|
+
return renderMessage(msg(bindSentenceKeyOf(LOCAL_ENGINE_BIND_DISCLOSURES[0])), lang);
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function bindHandedOf(verdict) {
|
|
141
|
+
if (own(verdict, 'kind') !== 'pass')
|
|
142
|
+
return undefined;
|
|
143
|
+
const handed = own(verdict, 'handed');
|
|
144
|
+
return typeof handed === 'string' && handed !== '' && handed === handed.trim() ? handed : undefined;
|
|
145
|
+
}
|
|
97
146
|
const BOOL_TRUE = new Set(['true', '1', 'yes', 'on']);
|
|
98
147
|
const OPERATOR_DECLARATION_KEYS = Object.freeze({ requirePrincipal: 'REQUIRE_PRINCIPAL', principals: 'OPERATOR_PRINCIPALS', singleUser: 'OPERATOR_SINGLE_USER' });
|
|
99
148
|
export function localEngineOperatorSingleUserOf(inherited) {
|
|
@@ -152,6 +201,7 @@ export function localEngineSpawnEnv(input) {
|
|
|
152
201
|
for (const [k, v] of envEntriesOf(own(input, 'inherited')) ?? [])
|
|
153
202
|
env.set(k, v);
|
|
154
203
|
const paths = own(input, 'paths');
|
|
204
|
+
const bindHanded = bindHandedOf(own(input, 'bind'));
|
|
155
205
|
for (const r of LOCAL_ENGINE_SPAWN_ENV) {
|
|
156
206
|
const inheritedValue = env.get(r.key);
|
|
157
207
|
if (r.value.kind === 'delete') {
|
|
@@ -169,6 +219,11 @@ export function localEngineSpawnEnv(input) {
|
|
|
169
219
|
let from = 'table';
|
|
170
220
|
if (r.value.kind === 'literal')
|
|
171
221
|
value = r.value.value;
|
|
222
|
+
else if (r.value.kind === 'gated') {
|
|
223
|
+
value = bindHanded ?? r.value.value;
|
|
224
|
+
if (bindHanded !== undefined)
|
|
225
|
+
from = 'user';
|
|
226
|
+
}
|
|
172
227
|
else if (r.value.kind === 'path') {
|
|
173
228
|
const p = own(paths, r.value.slot);
|
|
174
229
|
value = typeof p === 'string' && p !== '' ? p : undefined;
|
|
@@ -311,11 +366,17 @@ export function localEngineSeedEnv(input) {
|
|
|
311
366
|
dropped.push(Object.freeze({ key: 'WORKFLOW_SIZE_GUIDELINE', why: 'top-level-invalid' }));
|
|
312
367
|
}
|
|
313
368
|
}
|
|
369
|
+
const bindKey = canon('BIND_HOST');
|
|
370
|
+
const bind = localEngineBindGateOf({ requested: merged.get(bindKey)?.value, acknowledged: own(input, 'bindAcknowledged') === true });
|
|
371
|
+
merged.delete(bindKey);
|
|
372
|
+
if (refuse === undefined && bind.kind === 'refuse')
|
|
373
|
+
refuse = bind.reason;
|
|
314
374
|
const rows = [...merged.values()];
|
|
315
375
|
return Object.freeze({
|
|
316
376
|
env: freezeRecord(rows.map((r) => [r.key, r.value])),
|
|
317
377
|
from: Object.freeze(rows.map((r) => Object.freeze({ key: r.key, source: r.source }))),
|
|
318
378
|
dropped: Object.freeze(dropped),
|
|
379
|
+
bind,
|
|
319
380
|
...(refuse !== undefined ? { refuse } : {}),
|
|
320
381
|
});
|
|
321
382
|
}
|
package/dist/mcpLiveness.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export interface McpEngineLegHealth {
|
|
|
29
29
|
}
|
|
30
30
|
export declare function mcpLivenessRollupOf(rows: readonly McpLivenessBearingRow[] | undefined): McpEngineLegHealth;
|
|
31
31
|
export declare function mcpEngineLegHealthDetail(health: McpEngineLegHealth | undefined): string;
|
|
32
|
-
export declare const MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "host_refused", "unknown"];
|
|
32
|
+
export declare const MCP_FAILURE_KINDS: readonly ["connect_refused", "connection_failed", "connection_closed", "unauthorized", "http_status", "not_mcp_response", "spawn_failed", "timeout", "protocol", "invalid_config", "credential_unavailable", "host_refused", "revoked", "unknown"];
|
|
33
33
|
export declare const MCP_AUTHORIZATION_REASONS: readonly ["rejected", "scope", "none"];
|
|
34
34
|
export declare const MCP_FAILURE_UNAUTHORIZED: Extract<(typeof CORE_MCP_FAILURE_KINDS)[number], 'unauthorized'>;
|
|
35
35
|
export interface McpAuthorizationView {
|
package/dist/mcpProbeWire.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { projectMcpSection } from './adapter/downstream/eventToSdkMessage.js';
|
|
2
2
|
import { wireFailureShapeOf } from './wireFailureShape.js';
|
|
3
|
-
import { LIMIT_RATE_EXCEEDED } from './engineErrorCodes.js';
|
|
3
|
+
import { LIMIT_RATE_EXCEEDED, ROUTE_NOT_FOUND } from './engineErrorCodes.js';
|
|
4
4
|
import { mcpProbeAvailable } from './mcpProbeCapability.js';
|
|
5
5
|
import { scenarioRefusalFromError } from './scenarioRefusal.js';
|
|
6
6
|
export const MCP_PROBE_REFUSAL_CAUSES = Object.freeze([
|
|
@@ -39,7 +39,7 @@ export function classifyMcpProbeFailure(e) {
|
|
|
39
39
|
if (errorCode === undefined || errorCode === '')
|
|
40
40
|
return unknownBy('no_verdict', message, retryAfterSec);
|
|
41
41
|
switch (errorCode) {
|
|
42
|
-
case
|
|
42
|
+
case ROUTE_NOT_FOUND:
|
|
43
43
|
return refusedBy('face_absent', message);
|
|
44
44
|
case 'capability.mcp_injection_required':
|
|
45
45
|
return refusedBy('injection_not_honored', message);
|
package/dist/mcpReconnect.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { capForDisplay } from './fleetTaskDesc.js';
|
|
2
|
-
import { STEERING_NOT_RUNNING } from './engineErrorCodes.js';
|
|
2
|
+
import { ROUTE_NOT_FOUND, STEERING_NOT_RUNNING } from './engineErrorCodes.js';
|
|
3
3
|
import { ownDataField } from './ownKey.js';
|
|
4
4
|
import { isSessionIdPathSegment } from './sessionIdSegment.js';
|
|
5
5
|
import { inSlotReadOf, inValueOf, slotReadOf } from './wireFailureShape.js';
|
|
@@ -147,7 +147,7 @@ export function classifyMcpReconnectFailure(e) {
|
|
|
147
147
|
return { kind: 'unsupported', reason: 'capability' };
|
|
148
148
|
if (typeof code === 'string' && code.startsWith('feature.'))
|
|
149
149
|
return { kind: 'unsupported', reason: 'feature' };
|
|
150
|
-
if (code ===
|
|
150
|
+
if (code === ROUTE_NOT_FOUND)
|
|
151
151
|
return { kind: 'unsupported', reason: 'route' };
|
|
152
152
|
if (code === 'not_found.session')
|
|
153
153
|
return { kind: 'not_found' };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { hostEnv } from '../hostEnv.js';
|
|
2
|
+
import { sha256BytesHex } from '../sha256Bytes.js';
|
|
3
|
+
import { utf8Encode } from '../uuidV5.js';
|
|
2
4
|
import { resolveModelCatalog, } from './catalog.js';
|
|
3
5
|
export const DEFAULT_CATALOG_SOURCES = Object.freeze([
|
|
4
6
|
'https://raw.githubusercontent.com/sema-agent/sema-model-catalog/main/dist/catalog.json',
|
|
@@ -61,18 +63,6 @@ export function catalogShaUrlFor(catalogUrl) {
|
|
|
61
63
|
export function catalogCachePath(configHome) {
|
|
62
64
|
return `${configHome.replace(/\/+$/, '')}/${CATALOG_CACHE_RELATIVE_PATH}`;
|
|
63
65
|
}
|
|
64
|
-
async function sha256Hex(text) {
|
|
65
|
-
const g = globalThis;
|
|
66
|
-
const subtle = g.crypto?.subtle;
|
|
67
|
-
const Enc = g.TextEncoder;
|
|
68
|
-
if (subtle === undefined || Enc === undefined)
|
|
69
|
-
return null;
|
|
70
|
-
const digest = await subtle.digest('SHA-256', new Enc().encode(text));
|
|
71
|
-
let out = '';
|
|
72
|
-
for (const b of new Uint8Array(digest))
|
|
73
|
-
out += b.toString(16).padStart(2, '0');
|
|
74
|
-
return out;
|
|
75
|
-
}
|
|
76
66
|
function parseShaFile(text) {
|
|
77
67
|
const m = /\b([0-9a-fA-F]{64})\b/.exec(text);
|
|
78
68
|
return m?.[1] === undefined ? null : m[1].toLowerCase();
|
|
@@ -202,14 +192,10 @@ export async function loadCatalogWithSources(opts) {
|
|
|
202
192
|
let shaChecked = false;
|
|
203
193
|
if (shaGot.outcome === 'ok' && shaGot.text !== undefined) {
|
|
204
194
|
const expected = parseShaFile(shaGot.text);
|
|
205
|
-
const actual = await sha256Hex(got.text);
|
|
206
195
|
if (expected === null) {
|
|
207
196
|
warnings.push(`catalog sha256 sidecar for ${finalUrl} is not a hex digest — payload accepted without the checksum`);
|
|
208
197
|
}
|
|
209
|
-
else if (
|
|
210
|
-
warnings.push('no WebCrypto SHA-256 in this host — catalog payload accepted without the checksum');
|
|
211
|
-
}
|
|
212
|
-
else if (expected !== actual) {
|
|
198
|
+
else if (expected !== sha256BytesHex(utf8Encode(got.text))) {
|
|
213
199
|
attempts.push({ url: src, outcome: 'sha-mismatch', detail: 'catalog.sha256 does not match the payload digest' });
|
|
214
200
|
continue;
|
|
215
201
|
}
|
|
@@ -39,6 +39,14 @@ export interface OnboardProbeResponse {
|
|
|
39
39
|
text(): Promise<string>;
|
|
40
40
|
}
|
|
41
41
|
export type OnboardProbeFetch = (url: string, init: OnboardProbeRequestInit) => Promise<OnboardProbeResponse>;
|
|
42
|
+
export declare const ONBOARD_PROBE_BUDGETS: Readonly<{
|
|
43
|
+
firstTokenMs: 15000;
|
|
44
|
+
catalogMs: Readonly<{
|
|
45
|
+
'anthropic-messages': 8000;
|
|
46
|
+
'openai-completions': 10000;
|
|
47
|
+
}>;
|
|
48
|
+
discoveryMs: 10000;
|
|
49
|
+
}>;
|
|
42
50
|
export interface OnboardProbeDeps {
|
|
43
51
|
readonly fetchImpl?: OnboardProbeFetch | undefined;
|
|
44
52
|
readonly timeoutMs?: number | undefined;
|
|
@@ -117,6 +117,11 @@ export function onboardBaseUrlProblem(url, lang) {
|
|
|
117
117
|
return say('onboard.baseUrl.encoding');
|
|
118
118
|
return undefined;
|
|
119
119
|
}
|
|
120
|
+
export const ONBOARD_PROBE_BUDGETS = Object.freeze({
|
|
121
|
+
firstTokenMs: 15_000,
|
|
122
|
+
catalogMs: Object.freeze({ 'anthropic-messages': 8_000, 'openai-completions': 10_000 }),
|
|
123
|
+
discoveryMs: 10_000,
|
|
124
|
+
});
|
|
120
125
|
function keyHeaders(api, key, auth) {
|
|
121
126
|
const h = {};
|
|
122
127
|
if (key !== undefined && key !== '') {
|
|
@@ -172,7 +177,7 @@ export async function probeModelEndpoint(target, deps) {
|
|
|
172
177
|
return typeof v === 'number' && Number.isFinite(v) && v > 0 ? v : undefined;
|
|
173
178
|
};
|
|
174
179
|
const timeoutMs = num('timeoutMs');
|
|
175
|
-
const deadlineMs = num('firstTokenMs') ?? timeoutMs ??
|
|
180
|
+
const deadlineMs = num('firstTokenMs') ?? timeoutMs ?? ONBOARD_PROBE_BUDGETS.firstTokenMs;
|
|
176
181
|
const root = baseUrl.trim();
|
|
177
182
|
try {
|
|
178
183
|
if (joinRequestUrl(root, 'models') === undefined)
|
|
@@ -199,7 +204,7 @@ export async function probeModelEndpoint(target, deps) {
|
|
|
199
204
|
...(modelId !== undefined ? { modelId } : {}),
|
|
200
205
|
fetch: fetchWithKey,
|
|
201
206
|
firstTokenBudgetMs: deadlineMs,
|
|
202
|
-
catalogBudgetMs: timeoutMs ??
|
|
207
|
+
catalogBudgetMs: timeoutMs ?? ONBOARD_PROBE_BUDGETS.catalogMs[api],
|
|
203
208
|
requestUrl: (path) => joinRequestUrl(root, path),
|
|
204
209
|
redact: (text) => redact(text, redactKey),
|
|
205
210
|
});
|
|
@@ -233,7 +238,7 @@ export async function discoverEndpointModels(target, deps) {
|
|
|
233
238
|
if (url === undefined)
|
|
234
239
|
return fail('other', en('onboard.probe.judgeAbsent'));
|
|
235
240
|
const t = field(deps, 'timeoutMs');
|
|
236
|
-
const budget = typeof t === 'number' && Number.isFinite(t) && t > 0 ? t :
|
|
241
|
+
const budget = typeof t === 'number' && Number.isFinite(t) && t > 0 ? t : ONBOARD_PROBE_BUDGETS.discoveryMs;
|
|
237
242
|
const headers = { ...(api === 'anthropic-messages' ? { 'anthropic-version': '2023-06-01' } : {}), ...keyHeaders(api, key, auth === 'bearer' || auth === 'x-api-key' ? auth : undefined) };
|
|
238
243
|
const settled = await settleWithinDeadline(budget, async (signal) => {
|
|
239
244
|
const res = await f(url, { method: 'GET', headers, redirect: 'manual', signal });
|