@byok-sdk/client 0.1.0 → 0.2.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/dist/index.js CHANGED
@@ -684,7 +684,7 @@ function readPackageJson(dir) {
684
684
  function resolvePiBin() {
685
685
  const override = process.env.BYOK_PI_BIN;
686
686
  if (override) {
687
- return { command: override, source: "path" };
687
+ return { command: override, source: "env" };
688
688
  }
689
689
  try {
690
690
  const mainEntryUrl = import.meta.resolve(PI_PACKAGE_NAME);
@@ -702,14 +702,19 @@ function resolvePiBin() {
702
702
  if (parent === dir) break;
703
703
  dir = parent;
704
704
  }
705
- } catch {
705
+ } catch (cause) {
706
+ throw new Error(
707
+ `Required ${PI_PACKAGE_NAME} could not be resolved; install @byok-sdk/client dependencies or set BYOK_PI_BIN to a Node 22.19+ pi sidecar`,
708
+ { cause }
709
+ );
706
710
  }
707
- return { command: "pi", source: "path" };
711
+ throw new Error(
712
+ `Required ${PI_PACKAGE_NAME} does not expose the pi CLI; reinstall the pinned dependency or set BYOK_PI_BIN to a Node 22.19+ pi sidecar`
713
+ );
708
714
  }
709
715
 
710
716
  // src/adapters/pi/permission-mapping.ts
711
717
  var READONLY_TOOLS = ["read", "grep", "find", "ls"];
712
- var DEFAULT_ACTIVE_TOOLS = ["read", "bash", "edit", "write"];
713
718
  function mapPermissionPolicyToPiArgs(policy) {
714
719
  if (policy.network === false) {
715
720
  return {
@@ -728,22 +733,18 @@ function mapPermissionPolicyToPiArgs(policy) {
728
733
  const denyTools = policy.denyTools ?? [];
729
734
  if (policy.mode === "readonly") {
730
735
  const base = policy.allowTools ? policy.allowTools.filter((tool) => READONLY_TOOLS.includes(tool)) : [...READONLY_TOOLS];
731
- const effective = subtractDenied(base, denyTools);
732
- return { ok: true, args: effective.length === 0 ? ["--no-tools"] : ["--tools", effective.join(",")] };
733
- }
734
- if (denyTools.length > 0) {
735
- const base = policy.allowTools && policy.allowTools.length > 0 ? policy.allowTools : [...DEFAULT_ACTIVE_TOOLS];
736
- const effective = subtractDenied(base, denyTools);
737
- return { ok: true, args: effective.length === 0 ? ["--no-tools"] : ["--tools", effective.join(",")] };
736
+ if (base.length === 0) return { ok: true, args: ["--no-tools"] };
737
+ return {
738
+ ok: true,
739
+ args: ["--tools", base.join(","), ...denyTools.length > 0 ? ["--exclude-tools", denyTools.join(",")] : []]
740
+ };
738
741
  }
742
+ const args = [];
739
743
  if (policy.allowTools && policy.allowTools.length > 0) {
740
- return { ok: true, args: ["--tools", policy.allowTools.join(",")] };
744
+ args.push("--tools", policy.allowTools.join(","));
741
745
  }
742
- return { ok: true, args: [] };
743
- }
744
- function subtractDenied(tools, denyTools) {
745
- const denied = new Set(denyTools);
746
- return tools.filter((tool) => !denied.has(tool));
746
+ if (denyTools.length > 0) args.push("--exclude-tools", denyTools.join(","));
747
+ return { ok: true, args };
747
748
  }
748
749
 
749
750
  // src/adapters/pi/events.ts
@@ -768,7 +769,7 @@ function mapPiMessageToAgentEvent(msg) {
768
769
  output: { result: msg.result, isError: msg.isError === true }
769
770
  };
770
771
  }
771
- case "agent_end":
772
+ case "agent_settled":
772
773
  return { type: "turn_end" };
773
774
  /**
774
775
  * `artifact` is NOT a real pi RPC message — pi's own `write` tool only
@@ -804,16 +805,22 @@ function mapPiMessageToAgentEvent(msg) {
804
805
  // `recordUnmappedFrame`) can tell "known, expected, silently ignored"
805
806
  // apart from "genuinely never seen before" (falls to `default` below).
806
807
  case "agent_start":
808
+ case "agent_end":
809
+ // one low-level run; `agent_settled` is BYOK completion
807
810
  case "turn_start":
808
811
  case "turn_end":
809
- // pi's own per-LLM-turn boundary, not ours — see `agent_end` above
812
+ // pi's own per-LLM-turn boundary, not ours
810
813
  case "message_start":
811
814
  case "message_end":
815
+ case "bash_execution_update":
812
816
  case "tool_execution_update":
813
817
  case "queue_update":
814
818
  case "compaction_start":
815
819
  case "compaction_end":
816
820
  case "auto_retry_start":
821
+ case "summarization_retry_scheduled":
822
+ case "summarization_retry_attempt_start":
823
+ case "summarization_retry_finished":
817
824
  case "session_info_changed":
818
825
  case "thinking_level_changed":
819
826
  return void 0;
@@ -823,15 +830,20 @@ function mapPiMessageToAgentEvent(msg) {
823
830
  }
824
831
  var ROUTINE_PI_EVENT_TYPES = /* @__PURE__ */ new Set([
825
832
  "agent_start",
833
+ "agent_end",
826
834
  "turn_start",
827
835
  "turn_end",
828
836
  "message_start",
829
837
  "message_end",
838
+ "bash_execution_update",
830
839
  "tool_execution_update",
831
840
  "queue_update",
832
841
  "compaction_start",
833
842
  "compaction_end",
834
843
  "auto_retry_start",
844
+ "summarization_retry_scheduled",
845
+ "summarization_retry_attempt_start",
846
+ "summarization_retry_finished",
835
847
  "session_info_changed",
836
848
  "thinking_level_changed"
837
849
  ]);
@@ -965,10 +977,7 @@ var PiRpcClient = class {
965
977
  * traffic. Logs once per distinct type (not per occurrence, so a
966
978
  * repeating unmapped type can't spam stdout); the running tally is also
967
979
  * folded into this client's exit-time error message (`buildExitError`) so
968
- * a post-mortem on a failed/hung task has it without needing separate log
969
- * scraping. This is the exact mechanism that would have turned this
970
- * task's root-cause hang (`agent_end` arriving with no mapping) into a
971
- * one-line, immediate warning instead of a silent stall.
980
+ * a post-mortem on a failed/hung task has it without separate log scraping.
972
981
  */
973
982
  recordUnmappedFrame(type) {
974
983
  const next = (this.unmappedFrameCounts.get(type) ?? 0) + 1;
@@ -1109,8 +1118,8 @@ var PiAdapter = class {
1109
1118
  options;
1110
1119
  id = "pi";
1111
1120
  async detect() {
1112
- const bin = this.resolveBin();
1113
1121
  try {
1122
+ const bin = this.resolveBin();
1114
1123
  const { stdout, stderr } = await execFileAsync(bin.command, ["--version"], { timeout: DETECT_TIMEOUT_MS });
1115
1124
  const version = stdout.trim() || stderr.trim();
1116
1125
  const authPresent = KNOWN_PROVIDER_ENV_VARS.some((name) => process.env[name] !== void 0);
@@ -1287,7 +1296,7 @@ function mapPermissionPolicyToClaudeArgs(policy) {
1287
1296
  }
1288
1297
  if (policy.mode === "readonly") {
1289
1298
  const base = policy.allowTools ? policy.allowTools.filter((tool) => READONLY_TOOLS2.includes(tool)) : [...READONLY_TOOLS2];
1290
- const effective = subtractDenied2(base, denyTools);
1299
+ const effective = subtractDenied(base, denyTools);
1291
1300
  return { ok: true, args: ["--permission-mode", "default", "--tools", effective.join(",")] };
1292
1301
  }
1293
1302
  if (denyTools.length > 0) {
@@ -1304,7 +1313,7 @@ function mapPermissionPolicyToClaudeArgs(policy) {
1304
1313
  }
1305
1314
  return { ok: true, args };
1306
1315
  }
1307
- function subtractDenied2(tools, denyTools) {
1316
+ function subtractDenied(tools, denyTools) {
1308
1317
  const denied = new Set(denyTools);
1309
1318
  return tools.filter((tool) => !denied.has(tool));
1310
1319
  }
@@ -2244,9 +2253,10 @@ var CodexAdapter = class {
2244
2253
  * Two independently-verified channel gotchas apply here, the "pi lesson"
2245
2254
  * yet again:
2246
2255
  * - `codex login status`'s human-readable "Logged in using ChatGPT"
2247
- * message prints on STDERR, not stdout (the opposite-channel
2248
- * counterpart of pi's own `--version`-goes-to-stderr surprise) both
2249
- * streams are checked here for exactly that reason.
2256
+ * message prints on STDERR, not stdout both streams are checked
2257
+ * here for exactly that reason. pi's `--version` is the same class of
2258
+ * hazard from the other direction: its channel has moved between pi
2259
+ * releases (see ../pi/pi-adapter.ts), so neither stream is assumed.
2250
2260
  * - The NOT-logged-in message/exit-code shape was deliberately never
2251
2261
  * empirically tested: this machine has a real, live ChatGPT login, and
2252
2262
  * running `codex logout` to observe the negative case would have