@byok-sdk/keys 0.5.0 → 0.6.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/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import path2, { dirname, isAbsolute } from 'path';
|
|
2
3
|
import { spawn } from 'child_process';
|
|
3
|
-
import { promises, mkdirSync, existsSync, chmodSync } from 'fs';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
import path2, { isAbsolute, dirname } from 'path';
|
|
6
4
|
import { z } from 'zod';
|
|
7
5
|
import { createHash } from 'crypto';
|
|
6
|
+
import { promises, mkdirSync, existsSync, chmodSync } from 'fs';
|
|
7
|
+
import { parseImplementationSpawnBinding, assertImplementationSpawnBinding, projectKeysPiInheritedEnvironment } from '@byok-sdk/implementation-identity';
|
|
8
8
|
import { createRequire } from 'module';
|
|
9
9
|
|
|
10
10
|
// src/errors.ts
|
|
@@ -591,6 +591,7 @@ function assertKeychainPath(keychainPath) {
|
|
|
591
591
|
return keychainPath;
|
|
592
592
|
}
|
|
593
593
|
var PI_PROJECTED_KEY_ENV = "PI_PROVIDER_API_KEY";
|
|
594
|
+
var PI_LAUNCHER_RUNTIME_ENTRIES = ["pi-rpc", "pi-prepared"];
|
|
594
595
|
function piProjectionProviderId(profileRef) {
|
|
595
596
|
return `byok-sdk-${profileRef}`;
|
|
596
597
|
}
|
|
@@ -632,7 +633,14 @@ function buildPiProviderArgs(profile, delegatedArgs) {
|
|
|
632
633
|
if (singleFlags.has(flag)) throw new Error(`Pi launcher duplicate argument ${flag}`);
|
|
633
634
|
singleFlags.add(flag);
|
|
634
635
|
}
|
|
635
|
-
if (flag === "--no-tools") continue;
|
|
636
|
+
if (flag === "--no-tools" || flag === "--no-skills" || flag === "--no-extensions") continue;
|
|
637
|
+
if (flag === "--config") {
|
|
638
|
+
const value = delegatedArgs[++index];
|
|
639
|
+
if (typeof value !== "string" || !isAbsolute(value) || /[\u0000\r\n]/u.test(value)) {
|
|
640
|
+
throw new Error("Pi launcher --config requires an absolute single-line path");
|
|
641
|
+
}
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
636
644
|
if (flag === "--extension") {
|
|
637
645
|
const value = delegatedArgs[++index];
|
|
638
646
|
if (typeof value !== "string" || !isAbsolute(value) || /[\u0000\r\n]/u.test(value)) {
|
|
@@ -672,42 +680,22 @@ function buildPiProviderArgs(profile, delegatedArgs) {
|
|
|
672
680
|
config.thinkingLevel
|
|
673
681
|
];
|
|
674
682
|
}
|
|
683
|
+
function buildPiPreparedArgs(delegatedArgs) {
|
|
684
|
+
if (delegatedArgs.length !== 2 || delegatedArgs[0] !== "--config") {
|
|
685
|
+
throw new Error("Pi prepared launcher requires exactly --config <path>");
|
|
686
|
+
}
|
|
687
|
+
const value = delegatedArgs[1];
|
|
688
|
+
if (typeof value !== "string" || !isAbsolute(value) || /[\u0000\r\n]/u.test(value)) {
|
|
689
|
+
throw new Error("Pi launcher --config requires an absolute single-line path");
|
|
690
|
+
}
|
|
691
|
+
return [...delegatedArgs];
|
|
692
|
+
}
|
|
675
693
|
function requirePiModelConfig(profile) {
|
|
676
694
|
if (profile.pi_model === void 0) throw new Error("Pi execution requires explicit pi_model configuration");
|
|
677
695
|
return PiModelConfigSchema.parse(profile.pi_model);
|
|
678
696
|
}
|
|
679
697
|
|
|
680
698
|
// src/pi-provider-launcher-core.ts
|
|
681
|
-
var PI_CHILD_BASE_ENV_NAMES = [
|
|
682
|
-
"PATH",
|
|
683
|
-
"HOME",
|
|
684
|
-
"USERPROFILE",
|
|
685
|
-
"TMPDIR",
|
|
686
|
-
"TEMP",
|
|
687
|
-
"TMP",
|
|
688
|
-
"LANG",
|
|
689
|
-
"TZ",
|
|
690
|
-
"TERM",
|
|
691
|
-
"SHELL",
|
|
692
|
-
"HTTP_PROXY",
|
|
693
|
-
"HTTPS_PROXY",
|
|
694
|
-
"NO_PROXY",
|
|
695
|
-
"ALL_PROXY",
|
|
696
|
-
"http_proxy",
|
|
697
|
-
"https_proxy",
|
|
698
|
-
"no_proxy",
|
|
699
|
-
"all_proxy"
|
|
700
|
-
];
|
|
701
|
-
var PI_CHILD_WINDOWS_ENV_NAMES = [
|
|
702
|
-
"SystemRoot",
|
|
703
|
-
"COMSPEC",
|
|
704
|
-
"PATHEXT",
|
|
705
|
-
"windir",
|
|
706
|
-
"SYSTEMDRIVE",
|
|
707
|
-
"PROGRAMFILES",
|
|
708
|
-
"APPDATA",
|
|
709
|
-
"LOCALAPPDATA"
|
|
710
|
-
];
|
|
711
699
|
function parsePiProviderLauncherOptions(args) {
|
|
712
700
|
const separator = args.indexOf("--");
|
|
713
701
|
const ownArgs = separator < 0 ? args : args.slice(0, separator);
|
|
@@ -715,6 +703,11 @@ function parsePiProviderLauncherOptions(args) {
|
|
|
715
703
|
const allowedFlags = /* @__PURE__ */ new Set([
|
|
716
704
|
"--pi-bin",
|
|
717
705
|
"--pi-entry",
|
|
706
|
+
"--launch-binding",
|
|
707
|
+
"--pi-cwd",
|
|
708
|
+
"--pi-fixed-args",
|
|
709
|
+
"--pi-config-digest",
|
|
710
|
+
"--runtime-entry",
|
|
718
711
|
"--profile-db",
|
|
719
712
|
"--provider",
|
|
720
713
|
"--model",
|
|
@@ -745,6 +738,11 @@ function parsePiProviderLauncherOptions(args) {
|
|
|
745
738
|
if (value === void 0) throw new Error(`${flag} requires a value`);
|
|
746
739
|
return value;
|
|
747
740
|
};
|
|
741
|
+
const rawRuntimeEntry = required("--runtime-entry");
|
|
742
|
+
if (!PI_LAUNCHER_RUNTIME_ENTRIES.includes(rawRuntimeEntry)) {
|
|
743
|
+
throw new Error(`--runtime-entry must be one of [${PI_LAUNCHER_RUNTIME_ENTRIES.join(", ")}]`);
|
|
744
|
+
}
|
|
745
|
+
const runtimeEntry = rawRuntimeEntry;
|
|
748
746
|
const rawProfileRef = required("--provider");
|
|
749
747
|
const profileRef = ProviderProfileRefSchema.safeParse(rawProfileRef);
|
|
750
748
|
if (!profileRef.success) {
|
|
@@ -807,9 +805,49 @@ function parsePiProviderLauncherOptions(args) {
|
|
|
807
805
|
if (piEntry !== void 0 && (!path2.isAbsolute(piEntry) || /[\u0000\r\n]/u.test(piEntry))) {
|
|
808
806
|
throw new Error("--pi-entry requires an absolute single-line path");
|
|
809
807
|
}
|
|
808
|
+
let launchBinding;
|
|
809
|
+
let piCwd;
|
|
810
|
+
let piFixedArgs;
|
|
811
|
+
if (!validateOnly || ["--launch-binding", "--pi-cwd", "--pi-fixed-args"].some((flag) => values.has(flag))) {
|
|
812
|
+
let rawBinding;
|
|
813
|
+
let rawFixedArgs;
|
|
814
|
+
try {
|
|
815
|
+
rawBinding = JSON.parse(required("--launch-binding"));
|
|
816
|
+
} catch {
|
|
817
|
+
throw new Error("--launch-binding requires a valid JSON binding");
|
|
818
|
+
}
|
|
819
|
+
launchBinding = parseImplementationSpawnBinding(rawBinding);
|
|
820
|
+
if (launchBinding === void 0) throw new Error("invalid implementation spawn binding");
|
|
821
|
+
piCwd = required("--pi-cwd");
|
|
822
|
+
try {
|
|
823
|
+
rawFixedArgs = JSON.parse(required("--pi-fixed-args"));
|
|
824
|
+
} catch {
|
|
825
|
+
throw new Error("--pi-fixed-args requires a JSON array");
|
|
826
|
+
}
|
|
827
|
+
if (!Array.isArray(rawFixedArgs) || rawFixedArgs.some((arg) => typeof arg !== "string")) {
|
|
828
|
+
throw new Error("--pi-fixed-args requires a JSON array of strings");
|
|
829
|
+
}
|
|
830
|
+
piFixedArgs = rawFixedArgs;
|
|
831
|
+
if (launchBinding.command !== required("--pi-bin") || launchBinding.entry !== piEntry || launchBinding.cwd !== piCwd || JSON.stringify(launchBinding.fixedArgv) !== JSON.stringify(piFixedArgs)) {
|
|
832
|
+
throw new Error("launcher arguments differ from implementation spawn binding");
|
|
833
|
+
}
|
|
834
|
+
if (launchBinding.envCommitments.PI_CODING_AGENT_SESSION_DIR !== sessionDir || launchBinding.envCommitments.PI_CODING_AGENT_DIR === void 0) {
|
|
835
|
+
throw new Error("launcher session/projection directories must match binding commitments");
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
const piConfigDigest = values.get("--pi-config-digest");
|
|
839
|
+
if ((!validateOnly || piConfigDigest !== void 0) && !/^[0-9a-f]{64}$/u.test(piConfigDigest ?? "")) {
|
|
840
|
+
throw new Error("--pi-config-digest requires 64 lowercase hexadecimal characters");
|
|
841
|
+
}
|
|
842
|
+
if (piArgs.some((arg) => arg === "--config-digest" || arg.startsWith("--config-digest="))) {
|
|
843
|
+
throw new Error("delegated --config-digest override is forbidden");
|
|
844
|
+
}
|
|
810
845
|
return {
|
|
846
|
+
...piConfigDigest === void 0 ? {} : { piConfigDigest },
|
|
811
847
|
...piEntry === void 0 ? {} : { piEntry },
|
|
848
|
+
runtimeEntry,
|
|
812
849
|
piBin: required("--pi-bin"),
|
|
850
|
+
...launchBinding === void 0 ? {} : { launchBinding, piCwd, piFixedArgs },
|
|
813
851
|
profileDbPath,
|
|
814
852
|
profileRef: profileRef.data,
|
|
815
853
|
modelId,
|
|
@@ -821,6 +859,20 @@ function parsePiProviderLauncherOptions(args) {
|
|
|
821
859
|
piArgs
|
|
822
860
|
};
|
|
823
861
|
}
|
|
862
|
+
function assertPiPreparedProviderProfile(profile) {
|
|
863
|
+
if (profile.adapter === "anthropic") {
|
|
864
|
+
throw new ByokKeysError(
|
|
865
|
+
"PROVIDER_PROFILE_INVALID",
|
|
866
|
+
`${profile.profile_ref} speaks the anthropic adapter; the prepared runtime entry compiles openai-completions only`
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
if (profile.auth_mode === "none") {
|
|
870
|
+
throw new ByokKeysError(
|
|
871
|
+
"PROVIDER_PROFILE_INVALID",
|
|
872
|
+
`${profile.profile_ref} declares auth_mode "none"; the prepared runtime entry requires a provider credential`
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
824
876
|
async function resolvePiProviderSecret(profile, createStore) {
|
|
825
877
|
if (profile.auth_mode === "none") return void 0;
|
|
826
878
|
const secrets = createStore();
|
|
@@ -840,33 +892,139 @@ async function resolvePiProviderSecret(profile, createStore) {
|
|
|
840
892
|
return secret;
|
|
841
893
|
}
|
|
842
894
|
function buildPiProviderChildEnvironment(options) {
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
const result = {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const isExact = exactNames.has(platformName);
|
|
853
|
-
const isPrefixed = platform === "win32" ? platformName.startsWith("LC_") || platformName.startsWith("XDG_") : name.startsWith("LC_") || name.startsWith("XDG_");
|
|
854
|
-
if (isExact || isPrefixed) result[name] = value;
|
|
855
|
-
}
|
|
856
|
-
const mcpPath = options.ambient.BYOK_PI_MCP_CONFIG_PATH;
|
|
857
|
-
if (mcpPath !== void 0) {
|
|
858
|
-
if (!path2.isAbsolute(mcpPath) || /[\u0000\r\n]/u.test(mcpPath)) throw new Error("BYOK_PI_MCP_CONFIG_PATH must be an absolute single-line path");
|
|
859
|
-
result.BYOK_PI_MCP_CONFIG_PATH = mcpPath;
|
|
860
|
-
}
|
|
861
|
-
const permissionMode = options.ambient.BYOK_PI_PERMISSION_MODE;
|
|
862
|
-
if (permissionMode !== void 0) {
|
|
863
|
-
if (permissionMode !== "auto" && permissionMode !== "readonly") throw new Error("BYOK_PI_PERMISSION_MODE must be auto or readonly");
|
|
864
|
-
result.BYOK_PI_PERMISSION_MODE = permissionMode;
|
|
865
|
-
}
|
|
866
|
-
result.PI_CODING_AGENT_DIR = options.projectionDir;
|
|
867
|
-
result.PI_CODING_AGENT_SESSION_DIR = options.sessionDir;
|
|
895
|
+
const binding = parseImplementationSpawnBinding(options.binding);
|
|
896
|
+
if (binding === void 0) throw new Error("invalid implementation spawn binding");
|
|
897
|
+
if (binding.envCommitments.PI_CODING_AGENT_SESSION_DIR !== options.sessionDir || binding.envCommitments.PI_CODING_AGENT_DIR === void 0) {
|
|
898
|
+
throw new Error("launcher session/projection directories must match binding commitments");
|
|
899
|
+
}
|
|
900
|
+
const result = {
|
|
901
|
+
...projectKeysPiInheritedEnvironment(options.ambient, options.platform),
|
|
902
|
+
...binding.envCommitments
|
|
903
|
+
};
|
|
868
904
|
return result;
|
|
869
905
|
}
|
|
906
|
+
var WINDOWS_PROJECTION_ACL_SCRIPT = String.raw`
|
|
907
|
+
$ErrorActionPreference = 'Stop'
|
|
908
|
+
try {
|
|
909
|
+
$request = [Console]::In.ReadToEnd() | ConvertFrom-Json
|
|
910
|
+
$acl = Get-Acl -LiteralPath ([string]$request.path)
|
|
911
|
+
$sidType = [System.Security.Principal.SecurityIdentifier]
|
|
912
|
+
$rules = @($acl.Access | ForEach-Object {
|
|
913
|
+
$sid = if ($_.IdentityReference -is [System.Security.Principal.SecurityIdentifier]) { $_.IdentityReference.Value } else { try { $_.IdentityReference.Translate($sidType).Value } catch { $null } }
|
|
914
|
+
[ordered]@{
|
|
915
|
+
sid = $sid
|
|
916
|
+
allow = $_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow
|
|
917
|
+
fullControl = ($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::FullControl) -eq [System.Security.AccessControl.FileSystemRights]::FullControl
|
|
918
|
+
inherits = ($_.InheritanceFlags -band 3) -eq 3 -and $_.PropagationFlags -eq [System.Security.AccessControl.PropagationFlags]::None
|
|
919
|
+
}
|
|
920
|
+
})
|
|
921
|
+
[ordered]@{
|
|
922
|
+
reparsePoint = ((Get-Item -LiteralPath ([string]$request.path) -Force).Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0
|
|
923
|
+
owner = $acl.GetOwner($sidType).Value
|
|
924
|
+
currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value
|
|
925
|
+
protected = $acl.AreAccessRulesProtected
|
|
926
|
+
rules = $rules
|
|
927
|
+
} | ConvertTo-Json -Depth 4 -Compress
|
|
928
|
+
} catch {
|
|
929
|
+
[Console]::Error.WriteLine('Pi projection ACL query failed')
|
|
930
|
+
exit 1
|
|
931
|
+
}
|
|
932
|
+
`;
|
|
933
|
+
async function assertWindowsPiProjectionAcl(directory, options = {}) {
|
|
934
|
+
const systemRoot = options.systemRoot ?? process.env.SystemRoot;
|
|
935
|
+
if (systemRoot === void 0 || !path2.win32.isAbsolute(systemRoot) || /[\u0000\r\n]/u.test(systemRoot)) {
|
|
936
|
+
throw new Error("Windows SystemRoot must be an absolute path");
|
|
937
|
+
}
|
|
938
|
+
const result = await (options.run ?? runCommand)(
|
|
939
|
+
path2.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"),
|
|
940
|
+
["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(WINDOWS_PROJECTION_ACL_SCRIPT, "utf16le").toString("base64")],
|
|
941
|
+
JSON.stringify({ path: directory })
|
|
942
|
+
);
|
|
943
|
+
if (result.exitCode !== 0) throw new Error("Pi projection ACL query failed");
|
|
944
|
+
let acl;
|
|
945
|
+
try {
|
|
946
|
+
acl = JSON.parse(result.stdout);
|
|
947
|
+
} catch {
|
|
948
|
+
throw new Error("pi_projection_acl_invalid_json");
|
|
949
|
+
}
|
|
950
|
+
const recordObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
951
|
+
if (!recordObject(acl) || Object.keys(acl).sort().join(",") !== "currentUser,owner,protected,reparsePoint,rules" || typeof acl.owner !== "string" || !/^S-1-[0-9-]+$/u.test(acl.owner) || typeof acl.currentUser !== "string" || !/^S-1-[0-9-]+$/u.test(acl.currentUser) || typeof acl.protected !== "boolean" || typeof acl.reparsePoint !== "boolean" || !Array.isArray(acl.rules)) {
|
|
952
|
+
throw new Error("pi_projection_acl_invalid_shape");
|
|
953
|
+
}
|
|
954
|
+
if (acl.reparsePoint) throw new Error("pi_projection_reparse_point: Pi projection path must be a non-symlink directory");
|
|
955
|
+
if (acl.owner !== acl.currentUser) throw new Error("pi_projection_owner_mismatch: Pi projection directory must be owned by the current user");
|
|
956
|
+
if (!acl.protected) throw new Error("pi_projection_acl_unprotected");
|
|
957
|
+
const principals = /* @__PURE__ */ new Set([acl.owner, "S-1-5-18", "S-1-5-32-544"]);
|
|
958
|
+
let ownerControl = false;
|
|
959
|
+
for (const rule of acl.rules) {
|
|
960
|
+
if (!recordObject(rule) || Object.keys(rule).sort().join(",") !== "allow,fullControl,inherits,sid" || typeof rule.sid !== "string" || !/^S-1-[0-9-]+$/u.test(rule.sid) || typeof rule.allow !== "boolean" || typeof rule.fullControl !== "boolean" || typeof rule.inherits !== "boolean") {
|
|
961
|
+
throw new Error("pi_projection_acl_invalid_ace");
|
|
962
|
+
}
|
|
963
|
+
if (!principals.has(rule.sid) || !rule.allow) throw new Error("pi_projection_acl_unauthorized_ace");
|
|
964
|
+
if (rule.sid === acl.owner && rule.fullControl && rule.inherits) ownerControl = true;
|
|
965
|
+
}
|
|
966
|
+
if (!ownerControl) throw new Error("pi_projection_acl_owner_access_missing");
|
|
967
|
+
}
|
|
968
|
+
async function assertPiProjectionDirectory(projectionDir, expectedDir) {
|
|
969
|
+
if (projectionDir !== expectedDir || !path2.isAbsolute(projectionDir) || path2.normalize(projectionDir) !== projectionDir) {
|
|
970
|
+
throw new Error("pi_projection_path_mismatch: Pi projection directory differs from committed path");
|
|
971
|
+
}
|
|
972
|
+
const stat = await promises.lstat(projectionDir);
|
|
973
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) throw new Error("pi_projection_not_directory_or_symlink: Pi projection path must be a non-symlink directory");
|
|
974
|
+
if (await promises.realpath(projectionDir) !== projectionDir) throw new Error("pi_projection_path_not_canonical: Pi projection directory parents must be canonical, without symlinks");
|
|
975
|
+
if (process.platform === "win32") {
|
|
976
|
+
await assertWindowsPiProjectionAcl(projectionDir);
|
|
977
|
+
} else {
|
|
978
|
+
if (stat.uid !== process.getuid()) throw new Error("pi_projection_owner_mismatch: Pi projection directory must be owned by the current uid");
|
|
979
|
+
if ((stat.mode & 4095) !== 448) throw new Error("pi_projection_mode_mismatch: Pi projection directory must have mode 0700");
|
|
980
|
+
}
|
|
981
|
+
if ((await promises.readdir(projectionDir)).length !== 0) throw new Error("pi_projection_not_empty: Pi projection directory must be empty");
|
|
982
|
+
}
|
|
983
|
+
async function startPiProvider(profile, options, dependencies) {
|
|
984
|
+
const binding = options.launchBinding;
|
|
985
|
+
if (options.validateOnly || binding === void 0 || options.piCwd === void 0 || options.piFixedArgs === void 0 || !/^[0-9a-f]{64}$/u.test(options.piConfigDigest ?? "")) {
|
|
986
|
+
throw new Error("Pi launch requires an explicit spawn binding, cwd and fixed args");
|
|
987
|
+
}
|
|
988
|
+
const projection = buildPiProviderProjection(profile);
|
|
989
|
+
const delegated = options.runtimeEntry === "pi-prepared" ? buildPiPreparedArgs(options.piArgs) : buildPiProviderArgs(profile, options.piArgs);
|
|
990
|
+
const env = buildPiProviderChildEnvironment({
|
|
991
|
+
ambient: dependencies.ambient,
|
|
992
|
+
binding,
|
|
993
|
+
sessionDir: options.sessionDir});
|
|
994
|
+
const actual = { command: options.piBin, entry: options.piEntry, fixedArgv: [...options.piFixedArgs], cwd: options.piCwd, env };
|
|
995
|
+
await assertImplementationSpawnBinding(binding, actual);
|
|
996
|
+
const projectionDir = env.PI_CODING_AGENT_DIR;
|
|
997
|
+
await assertPiProjectionDirectory(projectionDir, binding.envCommitments.PI_CODING_AGENT_DIR);
|
|
998
|
+
await ensurePiSessionDirectory(options.sessionDir);
|
|
999
|
+
const modelsPath = path2.join(projectionDir, "models.json");
|
|
1000
|
+
let created = false;
|
|
1001
|
+
const cleanup = async () => {
|
|
1002
|
+
if (created) {
|
|
1003
|
+
await promises.unlink(modelsPath);
|
|
1004
|
+
created = false;
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
try {
|
|
1008
|
+
const file = await promises.open(modelsPath, "wx", 384);
|
|
1009
|
+
created = true;
|
|
1010
|
+
try {
|
|
1011
|
+
await file.writeFile(`${JSON.stringify(projection)}
|
|
1012
|
+
`);
|
|
1013
|
+
} finally {
|
|
1014
|
+
await file.close();
|
|
1015
|
+
}
|
|
1016
|
+
const secret = await resolvePiProviderSecret(profile, dependencies.createSecretStore);
|
|
1017
|
+
if (secret !== void 0) env[PI_PROJECTED_KEY_ENV] = secret;
|
|
1018
|
+
const childArgs = [...actual.entry === void 0 ? [] : [actual.entry], ...actual.fixedArgv, `--config-digest=${options.piConfigDigest}`, ...delegated];
|
|
1019
|
+
const spawnChild = dependencies.spawn ?? spawn;
|
|
1020
|
+
await assertImplementationSpawnBinding(binding, actual);
|
|
1021
|
+
const child = spawnChild(actual.command, childArgs, { env, cwd: actual.cwd, stdio: "inherit" });
|
|
1022
|
+
return { child, cleanup };
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
await cleanup();
|
|
1025
|
+
throw error;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
870
1028
|
async function ensurePiSessionDirectory(sessionDir) {
|
|
871
1029
|
const firstCreated = await promises.mkdir(sessionDir, { recursive: true, mode: 448 });
|
|
872
1030
|
if (firstCreated !== void 0) {
|
|
@@ -913,19 +1071,19 @@ function loadSqliteModule() {
|
|
|
913
1071
|
);
|
|
914
1072
|
}
|
|
915
1073
|
}
|
|
916
|
-
function openSqliteDatabase(
|
|
1074
|
+
function openSqliteDatabase(path3, options, faults) {
|
|
917
1075
|
const { DatabaseSync } = loadSqliteModule();
|
|
918
1076
|
const readOnly = options?.readOnly === true;
|
|
919
|
-
if (
|
|
920
|
-
mkdirSync(dirname(
|
|
1077
|
+
if (path3 !== ":memory:" && !readOnly) {
|
|
1078
|
+
mkdirSync(dirname(path3), { mode: SECURE_DIR_MODE, recursive: true });
|
|
921
1079
|
}
|
|
922
|
-
const database = new DatabaseSync(
|
|
1080
|
+
const database = new DatabaseSync(path3, {
|
|
923
1081
|
timeout: DEFAULT_BUSY_TIMEOUT_MS,
|
|
924
1082
|
...options
|
|
925
1083
|
});
|
|
926
1084
|
try {
|
|
927
1085
|
faults?.onStep?.("after-open");
|
|
928
|
-
if (
|
|
1086
|
+
if (path3 !== ":memory:" && !readOnly) {
|
|
929
1087
|
database.exec("PRAGMA journal_mode = WAL");
|
|
930
1088
|
faults?.onStep?.("after-wal");
|
|
931
1089
|
database.exec("PRAGMA synchronous = FULL");
|
|
@@ -978,7 +1136,7 @@ CREATE TABLE IF NOT EXISTS provider_profile (
|
|
|
978
1136
|
function normalizeTableDdl(sql) {
|
|
979
1137
|
return sql.replace(/\bIF\s+NOT\s+EXISTS\b/giu, "").replace(/\s+/gu, " ").trim().replace(/;$/u, "").trim();
|
|
980
1138
|
}
|
|
981
|
-
function assertProviderProfileSchemaIsCurrent(database,
|
|
1139
|
+
function assertProviderProfileSchemaIsCurrent(database, path3) {
|
|
982
1140
|
const row = database.prepare(
|
|
983
1141
|
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'provider_profile'"
|
|
984
1142
|
).get();
|
|
@@ -987,7 +1145,7 @@ function assertProviderProfileSchemaIsCurrent(database, path4) {
|
|
|
987
1145
|
if (normalizeTableDdl(stored) === normalizeTableDdl(SCHEMA)) return;
|
|
988
1146
|
throw new ByokKeysError(
|
|
989
1147
|
"PROVIDER_STORE_SCHEMA_STALE",
|
|
990
|
-
`Provider profile store at ${
|
|
1148
|
+
`Provider profile store at ${path3} was created by a different @byok-sdk/keys schema; preserve this store and explicitly provision a separate current-schema store before continuing`
|
|
991
1149
|
);
|
|
992
1150
|
}
|
|
993
1151
|
var ENABLED_INDEX = `
|
|
@@ -1437,7 +1595,7 @@ async function run(options) {
|
|
|
1437
1595
|
path: options.profileDbPath,
|
|
1438
1596
|
readOnly: true
|
|
1439
1597
|
});
|
|
1440
|
-
let
|
|
1598
|
+
let cleanup;
|
|
1441
1599
|
try {
|
|
1442
1600
|
const profile = await profiles.get(options.profileRef);
|
|
1443
1601
|
if (profile === void 0) {
|
|
@@ -1451,34 +1609,15 @@ async function run(options) {
|
|
|
1451
1609
|
if (options.expectedBinding !== void 0) {
|
|
1452
1610
|
assertExactProviderProfileBinding(profile, options.expectedBinding);
|
|
1453
1611
|
}
|
|
1454
|
-
|
|
1612
|
+
if (options.runtimeEntry === "pi-prepared") assertPiPreparedProviderProfile(profile);
|
|
1613
|
+
buildPiProviderProjection(profile);
|
|
1455
1614
|
if (options.validateOnly) return 0;
|
|
1456
|
-
const
|
|
1457
|
-
projectionDir = await promises.mkdtemp(path2.join(os.tmpdir(), "byok-pi-provider-"));
|
|
1458
|
-
await promises.chmod(projectionDir, 448).catch(() => {
|
|
1459
|
-
});
|
|
1460
|
-
await ensurePiSessionDirectory(options.sessionDir);
|
|
1461
|
-
const childEnv = buildPiProviderChildEnvironment({
|
|
1615
|
+
const launched = await startPiProvider(profile, options, {
|
|
1462
1616
|
ambient: process.env,
|
|
1463
|
-
|
|
1464
|
-
sessionDir: options.sessionDir,
|
|
1465
|
-
secret: void 0
|
|
1466
|
-
});
|
|
1467
|
-
const secret = await resolvePiProviderSecret(
|
|
1468
|
-
profile,
|
|
1469
|
-
() => createSecretStore(options.secretServicePrefix, options.macosKeychainPath)
|
|
1470
|
-
);
|
|
1471
|
-
if (secret !== void 0) childEnv[PI_PROJECTED_KEY_ENV] = secret;
|
|
1472
|
-
await promises.writeFile(
|
|
1473
|
-
path2.join(projectionDir, "models.json"),
|
|
1474
|
-
`${JSON.stringify(projection)}
|
|
1475
|
-
`,
|
|
1476
|
-
{ mode: 384 }
|
|
1477
|
-
);
|
|
1478
|
-
const child = spawn(options.piBin, [...options.piEntry === void 0 ? [] : [options.piEntry], ...childArgs], {
|
|
1479
|
-
env: childEnv,
|
|
1480
|
-
stdio: "inherit"
|
|
1617
|
+
createSecretStore: () => createSecretStore(options.secretServicePrefix, options.macosKeychainPath)
|
|
1481
1618
|
});
|
|
1619
|
+
cleanup = launched.cleanup;
|
|
1620
|
+
const child = launched.child;
|
|
1482
1621
|
const forward = (signal) => {
|
|
1483
1622
|
if (!child.killed) child.kill(signal);
|
|
1484
1623
|
};
|
|
@@ -1499,9 +1638,7 @@ async function run(options) {
|
|
|
1499
1638
|
}
|
|
1500
1639
|
} finally {
|
|
1501
1640
|
await profiles.close();
|
|
1502
|
-
|
|
1503
|
-
await promises.rm(projectionDir, { recursive: true, force: true });
|
|
1504
|
-
}
|
|
1641
|
+
await cleanup?.();
|
|
1505
1642
|
}
|
|
1506
1643
|
}
|
|
1507
1644
|
async function main() {
|