@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,6 +1,6 @@
1
1
  # @byok-sdk/keys
2
2
 
3
- Pi launcher configuration in the unpublished 0.5.0 candidate is explicit.
3
+ Pi launcher configuration is explicit, from the published 0.5.0 onward.
4
4
  Set `pi_model` on `ProviderRegistry.configure` for profiles used by Pi:
5
5
 
6
6
  ```ts
@@ -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 platform = options.platform ?? process.platform;
844
- const exactNames = new Set([
845
- ...PI_CHILD_BASE_ENV_NAMES,
846
- ...platform === "win32" ? PI_CHILD_WINDOWS_ENV_NAMES : []
847
- ].map((name) => platform === "win32" ? name.toUpperCase() : name));
848
- const result = {};
849
- for (const [name, value] of Object.entries(options.ambient)) {
850
- if (value === void 0) continue;
851
- const platformName = platform === "win32" ? name.toUpperCase() : name;
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(path4, options, faults) {
1074
+ function openSqliteDatabase(path3, options, faults) {
917
1075
  const { DatabaseSync } = loadSqliteModule();
918
1076
  const readOnly = options?.readOnly === true;
919
- if (path4 !== ":memory:" && !readOnly) {
920
- mkdirSync(dirname(path4), { mode: SECURE_DIR_MODE, recursive: true });
1077
+ if (path3 !== ":memory:" && !readOnly) {
1078
+ mkdirSync(dirname(path3), { mode: SECURE_DIR_MODE, recursive: true });
921
1079
  }
922
- const database = new DatabaseSync(path4, {
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 (path4 !== ":memory:" && !readOnly) {
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, path4) {
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 ${path4} was created by a different @byok-sdk/keys schema; preserve this store and explicitly provision a separate current-schema store before continuing`
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 projectionDir;
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
- const projection = buildPiProviderProjection(profile);
1612
+ if (options.runtimeEntry === "pi-prepared") assertPiPreparedProviderProfile(profile);
1613
+ buildPiProviderProjection(profile);
1455
1614
  if (options.validateOnly) return 0;
1456
- const childArgs = buildPiProviderArgs(profile, options.piArgs);
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
- projectionDir,
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
- if (projectionDir) {
1503
- await promises.rm(projectionDir, { recursive: true, force: true });
1504
- }
1641
+ await cleanup?.();
1505
1642
  }
1506
1643
  }
1507
1644
  async function main() {