@gajae-code/coding-agent 0.16.0 → 0.16.3
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 +52 -1
- package/dist/types/async/job-manager.d.ts +32 -1
- package/dist/types/browser-backend.d.ts +12 -0
- package/dist/types/cli/update-cli.d.ts +1 -0
- package/dist/types/commands/sdk.d.ts +2 -0
- package/dist/types/config/billing-path.d.ts +25 -0
- package/dist/types/config/config-schema-version.d.ts +13 -1
- package/dist/types/config/model-registry.d.ts +16 -0
- package/dist/types/config/settings-schema.d.ts +17 -7
- package/dist/types/extensibility/extensions/types.d.ts +8 -3
- package/dist/types/gjc-runtime/launch-worktree.d.ts +25 -1
- package/dist/types/gjc-runtime/session-state-lock.d.ts +22 -0
- package/dist/types/main.d.ts +1 -0
- package/dist/types/modes/acp/acp-agent.d.ts +21 -21
- package/dist/types/modes/components/model-selector.d.ts +4 -0
- package/dist/types/modes/components/session-selector.d.ts +1 -1
- package/dist/types/modes/components/sessions-dashboard.d.ts +2 -1
- package/dist/types/modes/interactive-mode.d.ts +16 -2
- package/dist/types/modes/theme/theme.d.ts +2 -1
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +2 -1
- package/dist/types/sdk/broker/ensure.d.ts +3 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +6 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +14 -0
- package/dist/types/sdk/broker/startup-budget.d.ts +52 -0
- package/dist/types/sdk/broker/state-version.d.ts +17 -0
- package/dist/types/sdk/bus/discord-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/index.d.ts +3 -1
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +1 -1
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +1 -1
- package/dist/types/sdk/bus/slack-conversation.d.ts +1 -1
- package/dist/types/sdk/bus/slack-daemon.d.ts +1 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/cli/rows.d.ts +15 -2
- package/dist/types/sdk/cli/session-cli.d.ts +2 -1
- package/dist/types/sdk/host/events.d.ts +2 -0
- package/dist/types/sdk/host/host.d.ts +2 -0
- package/dist/types/sdk/host/query/cursor.d.ts +4 -2
- package/dist/types/sdk/host/query/handlers.d.ts +1 -0
- package/dist/types/sdk/host/query/revision-store.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +18 -17
- package/dist/types/sdk/lifecycle-session.d.ts +1 -1
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -5
- package/dist/types/sdk/receipt-state.d.ts +2 -0
- package/dist/types/sdk/router/session-router.d.ts +4 -0
- package/dist/types/sdk/turn-result.d.ts +6 -0
- package/dist/types/session/agent-session.d.ts +47 -7
- package/dist/types/session/fold-coordinator.d.ts +29 -2
- package/dist/types/session/session-manager.d.ts +14 -2
- package/dist/types/tools/ask.d.ts +1 -0
- package/dist/types/tools/bash.d.ts +12 -0
- package/dist/types/tools/browser/launch.d.ts +10 -0
- package/dist/types/tools/browser/registry.d.ts +8 -0
- package/dist/types/tools/index.d.ts +4 -10
- package/dist/types/tools/job.d.ts +3 -1
- package/dist/types/utils/external-editor.d.ts +12 -0
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/pirate.ts +7 -4
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +7 -1
- package/src/async/job-manager.ts +107 -9
- package/src/browser-backend.ts +29 -0
- package/src/cli/plugin-cli.ts +29 -0
- package/src/cli/update-cli.ts +63 -12
- package/src/commands/sdk.ts +22 -7
- package/src/config/billing-path.ts +42 -0
- package/src/config/config-schema-version.ts +18 -1
- package/src/config/model-preset-registry.ts +177 -18
- package/src/config/model-registry.ts +268 -42
- package/src/config/settings-schema.ts +19 -7
- package/src/config/settings.ts +46 -15
- package/src/coordinator-mcp/projection-scan.ts +6 -6
- package/src/coordinator-mcp/server.ts +21 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/extensibility/extensions/runner.ts +27 -0
- package/src/extensibility/extensions/types.ts +8 -3
- package/src/extensibility/gjc-plugins/installer.ts +51 -11
- package/src/extensibility/runtime-skill-discovery.ts +110 -3
- package/src/extensibility/skills.ts +22 -12
- package/src/gjc-runtime/launch-worktree.ts +285 -4
- package/src/gjc-runtime/session-state-lock.ts +156 -32
- package/src/gjc-runtime/session-state-sidecar.ts +10 -17
- package/src/gjc-runtime/tmux-owner-isolation.ts +16 -1
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/main.ts +4 -1
- package/src/modes/acp/acp-agent.ts +34 -19
- package/src/modes/components/model-selector.ts +76 -8
- package/src/modes/components/session-selector.ts +23 -15
- package/src/modes/components/sessions-dashboard.ts +8 -5
- package/src/modes/controllers/command-controller.ts +1 -1
- package/src/modes/controllers/event-controller.ts +30 -4
- package/src/modes/controllers/extension-ui-controller.ts +13 -13
- package/src/modes/controllers/input-controller.ts +2 -2
- package/src/modes/controllers/selector-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +36 -12
- package/src/modes/prompt-action-autocomplete.ts +30 -4
- package/src/modes/runtime-init.ts +12 -9
- package/src/modes/theme/theme.ts +5 -0
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/ui-helpers.ts +22 -3
- package/src/prompts/agent-fragments/browser-aside.md +22 -0
- package/src/prompts/tools/ask.md +1 -1
- package/src/prompts/tools/bash.md +1 -0
- package/src/prompts/tools/job.md +1 -1
- package/src/sdk/acp/adapter.ts +6 -1
- package/src/sdk/broker/broker.ts +10 -1
- package/src/sdk/broker/ensure.ts +76 -3
- package/src/sdk/broker/lifecycle-ledger.ts +6 -0
- package/src/sdk/broker/lifecycle.ts +254 -34
- package/src/sdk/broker/spawn-substrate.ts +45 -2
- package/src/sdk/broker/startup-budget.ts +144 -2
- package/src/sdk/broker/state-version.ts +17 -0
- package/src/sdk/bus/chat-daemon-control.ts +2 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +118 -24
- package/src/sdk/bus/discord-daemon.ts +50 -10
- package/src/sdk/bus/index.ts +33 -3
- package/src/sdk/bus/kind-aware-reconciliation.ts +296 -48
- package/src/sdk/bus/lifecycle-commands.ts +4 -0
- package/src/sdk/bus/notification-service.ts +22 -5
- package/src/sdk/bus/prompt-reconciliation.ts +7 -2
- package/src/sdk/bus/reconciliation-store.ts +55 -31
- package/src/sdk/bus/slack-conversation.ts +1 -1
- package/src/sdk/bus/slack-daemon.ts +72 -38
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/cli/rows.ts +75 -7
- package/src/sdk/cli/session-cli.ts +68 -35
- package/src/sdk/host/control/dispatch.ts +2 -2
- package/src/sdk/host/events.ts +26 -2
- package/src/sdk/host/host.ts +6 -1
- package/src/sdk/host/query/cursor.ts +52 -7
- package/src/sdk/host/query/handlers.ts +33 -12
- package/src/sdk/host/query/revision-store.ts +12 -0
- package/src/sdk/host/session-runtime.test.ts +497 -31
- package/src/sdk/host/session-runtime.ts +387 -54
- package/src/sdk/host/surface-policy.ts +3 -3
- package/src/sdk/lifecycle-session.ts +7 -2
- package/src/sdk/prompt-deadline-manager.ts +2 -1
- package/src/sdk/protocol/operation-inventory.generated.json +54 -3
- package/src/sdk/protocol/operation-registry.ts +1 -1
- package/src/sdk/receipt-state.ts +10 -0
- package/src/sdk/router/session-router.ts +210 -94
- package/src/sdk/session.ts +59 -41
- package/src/sdk/turn-result.ts +22 -0
- package/src/session/agent-session.ts +1033 -260
- package/src/session/fold-coordinator.ts +40 -3
- package/src/session/session-manager.ts +517 -77
- package/src/slash-commands/builtin-registry.ts +41 -0
- package/src/task/executor.ts +9 -4
- package/src/tools/ask-contract.test.ts +64 -0
- package/src/tools/ask-contract.ts +36 -1
- package/src/tools/ask.ts +10 -8
- package/src/tools/bash-interactive.ts +11 -2
- package/src/tools/bash.ts +158 -33
- package/src/tools/browser/launch.ts +37 -0
- package/src/tools/browser/registry.ts +99 -9
- package/src/tools/cron.ts +6 -4
- package/src/tools/descriptors.test.ts +15 -0
- package/src/tools/descriptors.ts +5 -1
- package/src/tools/index.ts +4 -6
- package/src/tools/job.ts +4 -1
- package/src/tools/monitor.ts +12 -9
- package/src/tools/resolve.ts +30 -10
- package/src/tools/tool-catalog.generated.ts +2 -2
- package/src/utils/external-editor.ts +86 -1
|
@@ -47,6 +47,7 @@ const MODEL_PRESET_REGISTRY_MAX_STATE_BYTES = 32 * 1024 * 1024;
|
|
|
47
47
|
const MODEL_PRESET_REGISTRY_MAX_HISTORY = 4;
|
|
48
48
|
const MODEL_PRESET_REGISTRY_MAX_RETENTION_ANCESTRY = 64;
|
|
49
49
|
const MODEL_PRESET_REGISTRY_MAX_ERROR_BYTES = 1024;
|
|
50
|
+
const MODEL_PRESET_REGISTRY_IDENTITY_SKELETON_CACHE_MAX = 200_000;
|
|
50
51
|
const MODEL_PRESET_REGISTRY_FETCH_TIMEOUT_MS = 8_000;
|
|
51
52
|
const REVISION_PATTERN = /^[0-9]{8}$/;
|
|
52
53
|
const SHA256_PATTERN = /^[a-f0-9]{64}$/;
|
|
@@ -592,10 +593,23 @@ function assertSafeRegistryDocument(value: unknown, location = "$"): void {
|
|
|
592
593
|
}
|
|
593
594
|
}
|
|
594
595
|
|
|
596
|
+
/**
|
|
597
|
+
* Confusable folding is a pure string function evaluated once per identity per
|
|
598
|
+
* document, and startup validates the same catalog identities repeatedly. The
|
|
599
|
+
* bounded memo keeps the fold cost proportional to the distinct identity count
|
|
600
|
+
* instead of the number of validation passes.
|
|
601
|
+
*/
|
|
602
|
+
const identitySkeletonCache = new Map<string, string>();
|
|
603
|
+
|
|
595
604
|
function identitySkeleton(value: string): string {
|
|
596
|
-
|
|
605
|
+
const cached = identitySkeletonCache.get(value);
|
|
606
|
+
if (cached !== undefined) return cached;
|
|
607
|
+
const skeleton = [...value.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase()]
|
|
597
608
|
.map(character => IDENTITY_HOMOGLYPHS.get(character) ?? character)
|
|
598
609
|
.join("");
|
|
610
|
+
if (identitySkeletonCache.size >= MODEL_PRESET_REGISTRY_IDENTITY_SKELETON_CACHE_MAX) identitySkeletonCache.clear();
|
|
611
|
+
identitySkeletonCache.set(value, skeleton);
|
|
612
|
+
return skeleton;
|
|
599
613
|
}
|
|
600
614
|
|
|
601
615
|
function assertUniqueRegistryNames(values: readonly string[], label: string): void {
|
|
@@ -824,23 +838,21 @@ function assertProfilePresetReferences(
|
|
|
824
838
|
}
|
|
825
839
|
}
|
|
826
840
|
|
|
827
|
-
function
|
|
841
|
+
function validateGenerationUncached(
|
|
828
842
|
generation: AcceptedGeneration,
|
|
829
843
|
trustedKeys: ReadonlyMap<string, ModelPresetRegistryTrustedKey>,
|
|
830
|
-
allowRevoked
|
|
831
|
-
):
|
|
832
|
-
const manifest =
|
|
844
|
+
allowRevoked: boolean,
|
|
845
|
+
): void {
|
|
846
|
+
const { manifest, snapshot, profiles, presets } = generation;
|
|
833
847
|
assertSafeRegistryDocument(manifest);
|
|
834
848
|
verifyManifest(manifest, trustedKeys, allowRevoked);
|
|
835
849
|
assertManifestBindings(manifest);
|
|
836
|
-
const snapshotBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(
|
|
850
|
+
const snapshotBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(snapshot));
|
|
837
851
|
assertContentDescriptor(snapshotBytes, manifest.signed.snapshot, "Cached registry snapshot");
|
|
838
|
-
const snapshot = ModelPresetRegistrySnapshotSchema.parse(generation.snapshot);
|
|
839
852
|
assertSafeRegistryDocument(snapshot);
|
|
840
853
|
assertSnapshotBindings(manifest, snapshot);
|
|
841
|
-
const profileBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(
|
|
854
|
+
const profileBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(profiles));
|
|
842
855
|
assertContentDescriptor(profileBytes, manifest.signed.contents.profiles, "Cached registry profiles");
|
|
843
|
-
const profiles = ModelPresetRegistryProfilesSchema.parse(generation.profiles);
|
|
844
856
|
assertSafeRegistryDocument(profiles);
|
|
845
857
|
assertRegistryIdentityPolicy(profiles);
|
|
846
858
|
if (
|
|
@@ -848,9 +860,8 @@ function validateGeneration(
|
|
|
848
860
|
profiles.profiles.length !== manifest.signed.contents.profiles.count
|
|
849
861
|
)
|
|
850
862
|
throw new Error("Cached registry profile identity is invalid.");
|
|
851
|
-
const presetBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(
|
|
863
|
+
const presetBytes = new TextEncoder().encode(canonicalModelPresetRegistryJson(presets));
|
|
852
864
|
assertContentDescriptor(presetBytes, manifest.signed.contents.presets, "Cached registry presets");
|
|
853
|
-
const presets = ModelPresetRegistryPresetsSchema.parse(generation.presets);
|
|
854
865
|
assertSafeRegistryDocument(presets);
|
|
855
866
|
assertRegistryIdentityPolicy(presets);
|
|
856
867
|
if (
|
|
@@ -859,24 +870,73 @@ function validateGeneration(
|
|
|
859
870
|
)
|
|
860
871
|
throw new Error("Cached registry preset identity is invalid.");
|
|
861
872
|
assertProfilePresetReferences(profiles, presets);
|
|
862
|
-
|
|
863
|
-
|
|
873
|
+
if (sha256(canonicalModelPresetRegistryJson(manifest)) !== generation.manifestSha256)
|
|
874
|
+
throw new Error("Cached registry manifest digest is invalid.");
|
|
864
875
|
assertSafeRegistryDocument(generation.retainedProfiles);
|
|
865
876
|
assertSafeRegistryDocument(generation.retainedPresets);
|
|
866
877
|
assertSafeRegistryDocument(generation.retainedDynamicProviders);
|
|
867
|
-
const effectiveProfiles =
|
|
878
|
+
const effectiveProfiles: ModelPresetRegistryProfiles = {
|
|
868
879
|
...profiles,
|
|
869
880
|
dynamicProviders: [...generation.retainedDynamicProviders, ...profiles.dynamicProviders],
|
|
870
881
|
profiles: [...generation.retainedProfiles, ...profiles.profiles],
|
|
871
|
-
}
|
|
872
|
-
const effectivePresets =
|
|
882
|
+
};
|
|
883
|
+
const effectivePresets: ModelPresetRegistryPresets = {
|
|
873
884
|
...presets,
|
|
874
885
|
presets: [...generation.retainedPresets, ...presets.presets],
|
|
875
|
-
}
|
|
886
|
+
};
|
|
876
887
|
assertRegistryIdentityPolicy(effectiveProfiles);
|
|
877
888
|
assertRegistryIdentityPolicy(effectivePresets);
|
|
878
889
|
assertProfilePresetReferences(effectiveProfiles, effectivePresets);
|
|
879
|
-
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Signature and binding verification is a pure function of the generation, the
|
|
894
|
+
* trusted key set, and the revocation allowance, and one accepted-registry read
|
|
895
|
+
* verifies the same generation objects from several recovery angles. The memo
|
|
896
|
+
* records both outcomes per (generation, keys, allowance) so a startup read
|
|
897
|
+
* verifies each cached generation exactly once instead of once per angle.
|
|
898
|
+
*/
|
|
899
|
+
type GenerationValidationOutcome = { ok: true } | { ok: false; error: unknown };
|
|
900
|
+
|
|
901
|
+
const generationValidationCache = new WeakMap<
|
|
902
|
+
AcceptedGeneration,
|
|
903
|
+
WeakMap<ReadonlyMap<string, ModelPresetRegistryTrustedKey>, Map<boolean, GenerationValidationOutcome>>
|
|
904
|
+
>();
|
|
905
|
+
|
|
906
|
+
/**
|
|
907
|
+
* Every caller supplies a generation whose documents were already schema-parsed
|
|
908
|
+
* (cache reads through `parseState`, refresh through `parseCanonicalDocument`),
|
|
909
|
+
* so this asserts the cryptographic and structural bindings and returns the
|
|
910
|
+
* input rather than re-deriving an identical parse.
|
|
911
|
+
*/
|
|
912
|
+
function validateGeneration(
|
|
913
|
+
generation: AcceptedGeneration,
|
|
914
|
+
trustedKeys: ReadonlyMap<string, ModelPresetRegistryTrustedKey>,
|
|
915
|
+
allowRevoked = false,
|
|
916
|
+
): AcceptedGeneration {
|
|
917
|
+
let byKeys = generationValidationCache.get(generation);
|
|
918
|
+
if (!byKeys) {
|
|
919
|
+
byKeys = new WeakMap();
|
|
920
|
+
generationValidationCache.set(generation, byKeys);
|
|
921
|
+
}
|
|
922
|
+
let byAllowance = byKeys.get(trustedKeys);
|
|
923
|
+
if (!byAllowance) {
|
|
924
|
+
byAllowance = new Map();
|
|
925
|
+
byKeys.set(trustedKeys, byAllowance);
|
|
926
|
+
}
|
|
927
|
+
const memoized = byAllowance.get(allowRevoked);
|
|
928
|
+
if (memoized) {
|
|
929
|
+
if (!memoized.ok) throw memoized.error;
|
|
930
|
+
return generation;
|
|
931
|
+
}
|
|
932
|
+
try {
|
|
933
|
+
validateGenerationUncached(generation, trustedKeys, allowRevoked);
|
|
934
|
+
} catch (error) {
|
|
935
|
+
byAllowance.set(allowRevoked, { ok: false, error });
|
|
936
|
+
throw error;
|
|
937
|
+
}
|
|
938
|
+
byAllowance.set(allowRevoked, { ok: true });
|
|
939
|
+
return generation;
|
|
880
940
|
}
|
|
881
941
|
|
|
882
942
|
function readJsonSync(file: string): unknown | undefined {
|
|
@@ -1488,9 +1548,92 @@ function acceptedRegistryFromState(
|
|
|
1488
1548
|
};
|
|
1489
1549
|
}
|
|
1490
1550
|
|
|
1551
|
+
/**
|
|
1552
|
+
* Accepted-registry reads are pure over the on-disk state, backup, and control
|
|
1553
|
+
* files, and a single launch resolves the registry from several subsystems.
|
|
1554
|
+
* The memo keys on the content digest of those inputs, so any byte change from
|
|
1555
|
+
* any writer (refresh, rollback, pin, tampering) is re-verified from scratch
|
|
1556
|
+
* while an unchanged launch pays the verification cost once. Digesting the
|
|
1557
|
+
* inputs is bounded by their size cap and stays far below the signature,
|
|
1558
|
+
* schema, and canonical-form work it replaces.
|
|
1559
|
+
*/
|
|
1560
|
+
const acceptedRegistryReadCache = new Map<string, { fingerprint: string; value: AcceptedModelPresetRegistry }>();
|
|
1561
|
+
|
|
1562
|
+
function cloneAcceptedModelPresetRegistry(value: AcceptedModelPresetRegistry): AcceptedModelPresetRegistry {
|
|
1563
|
+
return {
|
|
1564
|
+
...value,
|
|
1565
|
+
profiles: new Map(
|
|
1566
|
+
[...value.profiles].map(([id, profile]) => [id, structuredClone(profile)] as [string, ModelProfileDefinition]),
|
|
1567
|
+
),
|
|
1568
|
+
presets: structuredClone(value.presets),
|
|
1569
|
+
dynamicProviders: [...value.dynamicProviders],
|
|
1570
|
+
retainedProfiles: [...value.retainedProfiles],
|
|
1571
|
+
retainedPresets: [...value.retainedPresets],
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
function registryFileFingerprint(file: string): string {
|
|
1576
|
+
try {
|
|
1577
|
+
return sha256(fsSync.readFileSync(file));
|
|
1578
|
+
} catch {
|
|
1579
|
+
return "absent";
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
function acceptedRegistryFingerprint(
|
|
1584
|
+
agentDir: string,
|
|
1585
|
+
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir">,
|
|
1586
|
+
): string {
|
|
1587
|
+
const paths = registryPaths(agentDir);
|
|
1588
|
+
return [
|
|
1589
|
+
refreshDependencyId(effectiveTrustedKeys(dependencies, agentDir) as object),
|
|
1590
|
+
...[paths.state, paths.backup, paths.control].map(registryFileFingerprint),
|
|
1591
|
+
].join("|");
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
async function registryFileFingerprintAsync(file: string): Promise<string> {
|
|
1595
|
+
try {
|
|
1596
|
+
return sha256(new Uint8Array(await Bun.file(file).arrayBuffer()));
|
|
1597
|
+
} catch {
|
|
1598
|
+
return "absent";
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
async function acceptedRegistryFingerprintAsync(
|
|
1603
|
+
agentDir: string,
|
|
1604
|
+
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir">,
|
|
1605
|
+
): Promise<string> {
|
|
1606
|
+
const paths = registryPaths(agentDir);
|
|
1607
|
+
const files = await Promise.all(
|
|
1608
|
+
[paths.state, paths.backup, paths.control].map(file => registryFileFingerprintAsync(file)),
|
|
1609
|
+
);
|
|
1610
|
+
return [refreshDependencyId(effectiveTrustedKeys(dependencies, agentDir) as object), ...files].join("|");
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
/** Only the dependency-free startup read is memoized; injected dependencies always recompute. */
|
|
1614
|
+
function acceptedRegistryReadIsCacheable(dependencies: Omit<ModelPresetRegistryDependencies, "agentDir">): boolean {
|
|
1615
|
+
return Object.keys(dependencies).length === 0;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1491
1618
|
export function loadAcceptedModelPresetRegistry(
|
|
1492
1619
|
agentDir = getAgentDir(),
|
|
1493
1620
|
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir"> = {},
|
|
1621
|
+
): AcceptedModelPresetRegistry {
|
|
1622
|
+
if (!acceptedRegistryReadIsCacheable(dependencies) || environmentDisabled())
|
|
1623
|
+
return loadAcceptedModelPresetRegistryUncached(agentDir, dependencies);
|
|
1624
|
+
const fingerprint = acceptedRegistryFingerprint(agentDir, dependencies);
|
|
1625
|
+
const cached = acceptedRegistryReadCache.get(agentDir);
|
|
1626
|
+
if (cached && cached.fingerprint === fingerprint) return cloneAcceptedModelPresetRegistry(cached.value);
|
|
1627
|
+
const value = loadAcceptedModelPresetRegistryUncached(agentDir, dependencies);
|
|
1628
|
+
const verifiedFingerprint = acceptedRegistryFingerprint(agentDir, dependencies);
|
|
1629
|
+
if (verifiedFingerprint !== fingerprint) return loadAcceptedModelPresetRegistryUncached(agentDir, dependencies);
|
|
1630
|
+
acceptedRegistryReadCache.set(agentDir, { fingerprint, value });
|
|
1631
|
+
return cloneAcceptedModelPresetRegistry(value);
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
function loadAcceptedModelPresetRegistryUncached(
|
|
1635
|
+
agentDir: string,
|
|
1636
|
+
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir">,
|
|
1494
1637
|
): AcceptedModelPresetRegistry {
|
|
1495
1638
|
if (environmentDisabled())
|
|
1496
1639
|
return {
|
|
@@ -1551,6 +1694,22 @@ export function loadAcceptedModelPresetRegistry(
|
|
|
1551
1694
|
export async function loadAcceptedModelPresetRegistryAsync(
|
|
1552
1695
|
agentDir = getAgentDir(),
|
|
1553
1696
|
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir"> = {},
|
|
1697
|
+
): Promise<AcceptedModelPresetRegistry> {
|
|
1698
|
+
if (!acceptedRegistryReadIsCacheable(dependencies) || environmentDisabled())
|
|
1699
|
+
return loadAcceptedModelPresetRegistryAsyncUncached(agentDir, dependencies);
|
|
1700
|
+
const fingerprint = await acceptedRegistryFingerprintAsync(agentDir, dependencies);
|
|
1701
|
+
const cached = acceptedRegistryReadCache.get(agentDir);
|
|
1702
|
+
if (cached && cached.fingerprint === fingerprint) return cloneAcceptedModelPresetRegistry(cached.value);
|
|
1703
|
+
const value = await loadAcceptedModelPresetRegistryAsyncUncached(agentDir, dependencies);
|
|
1704
|
+
const verifiedFingerprint = await acceptedRegistryFingerprintAsync(agentDir, dependencies);
|
|
1705
|
+
if (verifiedFingerprint !== fingerprint) return loadAcceptedModelPresetRegistryAsyncUncached(agentDir, dependencies);
|
|
1706
|
+
acceptedRegistryReadCache.set(agentDir, { fingerprint, value });
|
|
1707
|
+
return cloneAcceptedModelPresetRegistry(value);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
async function loadAcceptedModelPresetRegistryAsyncUncached(
|
|
1711
|
+
agentDir: string,
|
|
1712
|
+
dependencies: Omit<ModelPresetRegistryDependencies, "agentDir">,
|
|
1554
1713
|
): Promise<AcceptedModelPresetRegistry> {
|
|
1555
1714
|
if (environmentDisabled())
|
|
1556
1715
|
return {
|