@oh-my-pi/pi-coding-agent 16.1.17 → 16.1.18

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.
@@ -78,4 +78,18 @@ export declare function formatUsageBreakdown(reports: UsageReport[], accounts: U
78
78
  * peak-per-bucket sparkline per limit window plus latest/peak percentages.
79
79
  */
80
80
  export declare function formatUsageHistory(entries: UsageHistoryEntry[], sinceMs: number, nowMs: number, redaction?: Map<string, string>): string;
81
+ /**
82
+ * Keep only accounts worth a usage row: those whose provider has a usage
83
+ * provider, so a missing report is a real gap rather than the absence of any
84
+ * usage concept. Providers with no usage endpoint (web-search keys, local /
85
+ * keyless servers, inference providers without a usage API) would only ever
86
+ * render as noise, so they are dropped.
87
+ *
88
+ * `hasUsageProvider` is injected (in practice {@link AuthStorage.usageProviderFor})
89
+ * so custom/broker resolvers stay authoritative — no provider list is duplicated
90
+ * here. An explicit `--provider` request bypasses the cull, so
91
+ * `omp usage --provider xai` can still confirm the stored credential has no
92
+ * usage endpoint.
93
+ */
94
+ export declare function selectReportableAccounts(accounts: UsageAccountIdentity[], hasUsageProvider: (provider: string) => boolean, explicitProvider?: string): UsageAccountIdentity[];
81
95
  export declare function runUsageCommand(cmd: UsageCommandArgs): Promise<void>;
@@ -19,6 +19,15 @@ export default class Token extends Command {
19
19
  description: string;
20
20
  default: boolean;
21
21
  };
22
+ account: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"integer"> & {
23
+ char: string;
24
+ description: string;
25
+ };
26
+ list: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
27
+ char: string;
28
+ description: string;
29
+ default: boolean;
30
+ };
22
31
  };
23
32
  static examples: string[];
24
33
  run(): Promise<void>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Canonical specifier → live module namespace. Keys MUST match the right-hand
3
+ * side of `bundledRegistryVirtualSpecifier(...)` calls in
4
+ * `legacy-pi-compat.ts`; the synthesizer enumerates each namespace's own
5
+ * enumerable exports at extension load time.
6
+ */
7
+ export declare const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
@@ -1,26 +1,16 @@
1
1
  import * as path from "node:path";
2
2
  /**
3
- * Compute the bunfs package root from the compiled binary's `import.meta.dir`
4
- * (or any stand-in supplied by tests). Bun compiled binaries report one of:
5
- *
6
- * - the bunfs mount root itself — `/$bunfs/root` or `<drive>:\~BUN\root` (Bun
7
- * 1.2.x and early 1.3.x). Append `packages` for the canonical layout.
8
- * - the bunfs mount root followed by the binary's basename — `//root/<bin>`
9
- * on POSIX or `<drive>:\~BUN\root\<bin>.exe` on Windows (observed on Bun
10
- * 1.3.14 with the cross-compiled `omp-darwin-arm64` release asset — issue
11
- * #3329). The trailing segment is stripped so the result still lands on
12
- * `<root>/packages`.
13
- * - the module's own source directory if a future Bun release switches to
14
- * module-specific `import.meta.dir` values:
15
- * `<bunfs>/packages/coding-agent/src/extensibility/plugins`.
16
- * The bunfs-root-with-binary branch slices the original `metaDir`, and
17
- * `bunfsPath` uses a matching double-slash-preserving join, so the bunfs-native
18
- * prefix is preserved verbatim — `path.posix.join` collapses `//root` to
19
- * `/root`, but Bun's bunfs lookup is keyed on the exact `//root` form.
20
- *
21
- * Exported for tests; production callers use `BUNFS_PACKAGE_ROOT` below.
3
+ * Test seam: builds the synthetic ES module source for a virtual specifier
4
+ * against an explicit registry. Pure (no globalThis read); the emitted source
5
+ * still routes runtime lookups through `globalThis[BUNDLED_REGISTRY_GLOBAL]`.
22
6
  */
23
- export declare function __computeBunfsPackageRoot(metaDir: string, pathImpl?: typeof path): string;
7
+ export declare function __synthesizeLegacyPiBundledSourceWithRegistry(registryKey: string, registry: Readonly<Record<string, Readonly<Record<string, unknown>>>>): string;
8
+ /**
9
+ * Test seam: returns the globalThis key the synthetic loader reads from. Tests
10
+ * assert that the emitted source addresses the exact stash key the install
11
+ * function writes to, so a rename can't break extension loads silently.
12
+ */
13
+ export declare function __getLegacyPiBundledRegistryGlobal(): string;
24
14
  /**
25
15
  * Compute the package root for the npm prebuilt `dist/cli.js` bundle.
26
16
  *
@@ -31,17 +21,31 @@ export declare function __computeBunfsPackageRoot(metaDir: string, pathImpl?: ty
31
21
  */
32
22
  export declare function __computeBundledSelfPackageRoot(metaDir: string, pathImpl?: typeof path): string;
33
23
  /**
34
- * Join a computed bunfs package root with descendants without collapsing
35
- * Bun's POSIX `//root` mount prefix.
24
+ * Resolve the path the TypeBox compatibility shim ships at, then drop it when
25
+ * the source file is missing.
26
+ *
27
+ * In compiled-binary mode the shim is served through the
28
+ * `omp-legacy-pi-bundled:` virtual namespace (issue #3423) — bunfs paths are
29
+ * unreachable on Bun 1.3.14+, so the virtual specifier is always available and
30
+ * needs no filesystem probe. In dev / source-link / installed-package mode the
31
+ * shim is an on-disk source file; validation mirrors
32
+ * `__validateLegacyPiPackageRootOverrides` (#2168): if the computed candidate
33
+ * doesn't exist (e.g. an install that dropped the source — issue #3414),
34
+ * `resolveTypeBoxSpecifier` returns `undefined` and
35
+ * `rewriteLegacyExtensionSource` leaves bare `typebox` / `@sinclair/typebox`
36
+ * specifiers alone, so Bun falls through to native resolution against the
37
+ * extension's own `node_modules`.
36
38
  *
37
- * Exported for tests; production callers use `bunfsPath` below.
39
+ * Exported for tests; production callers use `TYPEBOX_SHIM_PATH`.
38
40
  */
39
- export declare function __joinBunfsPath(root: string, segments: readonly string[], pathImpl?: typeof path): string;
41
+ export declare function __resolveTypeBoxShimPath(isCompiled: boolean, sourcePath: string, pathExistsSync?: (p: string) => boolean): string | null;
40
42
  /**
41
- * Drop overrides whose targets are missing on disk so they can fall through to
42
- * the canonical-resolution path. Exported for the test seam in #2168.
43
+ * Drop overrides whose filesystem targets are missing so they can fall
44
+ * through to the canonical-resolution path. Virtual `omp-legacy-pi-bundled:`
45
+ * entries always pass — the bundled registry is the source of truth in
46
+ * compiled-binary mode where bunfs paths are unreachable (issue #3423).
43
47
  *
44
- * `pathExistsSync` defaults to `fs.existsSync`; the tests inject a stub to
48
+ * `pathExistsSync` defaults to `fs.existsSync`; tests inject a stub to
45
49
  * simulate the missing-entrypoint failure mode without touching the real FS.
46
50
  */
47
51
  export declare function __validateLegacyPiPackageRootOverrides(candidates: Record<string, string>, pathExistsSync?: (p: string) => boolean): Record<string, string>;
@@ -1,19 +1,29 @@
1
1
  /**
2
- * ExtensionDashboard - Tabbed layout for the Extension Control Center.
2
+ * ExtensionDashboard - Fullscreen alternate-screen control center for extensions.
3
3
  *
4
- * Layout:
5
- * - Top: Horizontal tab bar for provider selection
6
- * - Body: 2-column grid (inventory list | preview panel)
4
+ * Chrome mirrors the `/settings` overlay: a titled rounded box, a shared
5
+ * {@link TabBar} for provider selection, and a two-column body (inventory list |
6
+ * inspector). Both panes are mouse-aware wheel scrolls, hover highlights, and
7
+ * clicks select/activate — routed from a single SGR-mouse handler.
7
8
  *
8
9
  * Navigation:
9
- * - TAB/Shift+TAB: Cycle through provider tabs
10
- * - Up/Down/j/k: Navigate list
11
- * - Space: Toggle selected item (or master switch)
12
- * - Esc: Close dashboard (clears search first if active)
10
+ * - Tab/Shift+Tab or ←/→: switch provider tab
11
+ * - Up/Down/j/k or wheel: move list selection
12
+ * - Space/Enter or click: toggle selected item (or provider master switch)
13
+ * - Wheel over the inspector: scroll the detail pane
14
+ * - Esc: clear search (if active) then close
13
15
  */
14
- import { Container } from "@oh-my-pi/pi-tui";
16
+ import { type Component, type Tab } from "@oh-my-pi/pi-tui";
15
17
  import { Settings } from "../../../config/settings";
16
- export declare class ExtensionDashboard extends Container {
18
+ import type { ProviderTab } from "./types";
19
+ /**
20
+ * Map dashboard provider tabs to {@link TabBar} tabs. Empty *enabled* providers
21
+ * are muted — skipped by keyboard nav and unclickable; disabled providers stay
22
+ * selectable (with a leading disabled glyph) so their master switch can be
23
+ * re-enabled from the list. The "all" tab is never muted or marked.
24
+ */
25
+ export declare function buildTabBarTabs(tabs: ProviderTab[]): Tab[];
26
+ export declare class ExtensionDashboard implements Component {
17
27
  #private;
18
28
  private readonly cwd;
19
29
  private readonly settings;
@@ -22,6 +32,12 @@ export declare class ExtensionDashboard extends Container {
22
32
  onRequestRender?: () => void;
23
33
  private constructor();
24
34
  static create(cwd: string, settings?: Settings | null, terminalHeight?: number): Promise<ExtensionDashboard>;
35
+ /**
36
+ * Fullscreen frame: titled top border, the tab row(s), a divider, the
37
+ * two-column body sized to fill the viewport, a divider, the footer hint, and
38
+ * the bottom border. Records row geometry for mouse hit-testing.
39
+ */
25
40
  render(width: number): readonly string[];
41
+ invalidate(): void;
26
42
  handleInput(data: string): void;
27
43
  }
@@ -35,5 +35,18 @@ export declare class ExtensionList implements Component {
35
35
  clearSearch(): void;
36
36
  invalidate(): void;
37
37
  render(width: number): readonly string[];
38
+ /** Highlight the row under the pointer (null clears). */
39
+ setHoverIndex(index: number | null): void;
40
+ /**
41
+ * Map a 0-based line within this component's render to the absolute list-item
42
+ * index, or null when the line is the search banner, a padding row, or outside
43
+ * the visible window. The first two lines are the search banner and a blank
44
+ * separator; item rows follow, windowed at the current scroll offset.
45
+ */
46
+ hitTest(line: number): number | null;
47
+ /** Wheel notch: move the selection (and the inspector) one row. */
48
+ handleWheel(delta: -1 | 1): void;
49
+ /** Click: select the row under the pointer, or activate it when already selected. */
50
+ handleClick(line: number): void;
38
51
  handleInput(data: string): void;
39
52
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "16.1.17",
4
+ "version": "16.1.18",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -48,17 +48,17 @@
48
48
  "@agentclientprotocol/sdk": "0.25.0",
49
49
  "@babel/parser": "^7.29.7",
50
50
  "@mozilla/readability": "^0.6.0",
51
- "@oh-my-pi/hashline": "16.1.17",
52
- "@oh-my-pi/omp-stats": "16.1.17",
53
- "@oh-my-pi/pi-agent-core": "16.1.17",
54
- "@oh-my-pi/pi-ai": "16.1.17",
55
- "@oh-my-pi/pi-catalog": "16.1.17",
56
- "@oh-my-pi/pi-mnemopi": "16.1.17",
57
- "@oh-my-pi/pi-natives": "16.1.17",
58
- "@oh-my-pi/pi-tui": "16.1.17",
59
- "@oh-my-pi/pi-utils": "16.1.17",
60
- "@oh-my-pi/pi-wire": "16.1.17",
61
- "@oh-my-pi/snapcompact": "16.1.17",
51
+ "@oh-my-pi/hashline": "16.1.18",
52
+ "@oh-my-pi/omp-stats": "16.1.18",
53
+ "@oh-my-pi/pi-agent-core": "16.1.18",
54
+ "@oh-my-pi/pi-ai": "16.1.18",
55
+ "@oh-my-pi/pi-catalog": "16.1.18",
56
+ "@oh-my-pi/pi-mnemopi": "16.1.18",
57
+ "@oh-my-pi/pi-natives": "16.1.18",
58
+ "@oh-my-pi/pi-tui": "16.1.18",
59
+ "@oh-my-pi/pi-utils": "16.1.18",
60
+ "@oh-my-pi/pi-wire": "16.1.18",
61
+ "@oh-my-pi/snapcompact": "16.1.18",
62
62
  "@opentelemetry/api": "^1.9.1",
63
63
  "@opentelemetry/context-async-hooks": "^2.7.1",
64
64
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -82,22 +82,15 @@ async function main(): Promise<void> {
82
82
  "--root",
83
83
  ".",
84
84
  "./packages/coding-agent/src/cli.ts",
85
- // Legacy pi-* extension compat entrypoints served by
86
- // `legacy-pi-compat.ts`. These are reached via computed bunfs paths
87
- // (which `--compile`'s static analyzer cannot trace), so each must be
88
- // listed here to land in bunfs at
89
- // `/$bunfs/root/packages/<pkg>/<entry>.js`. The coding-agent's own
90
- // `./src/index.ts` is intentionally NOT listed: bun --compile silently
91
- // breaks the CLI entry when the same package's barrel appears as an
92
- // extra entrypoint (issue #1474), so legacy `pi-coding-agent` imports
93
- // resolve through `legacy-pi-coding-agent-shim.ts` instead.
94
- "./packages/agent/src/index.ts",
95
- "./packages/natives/native/index.js",
96
- "./packages/tui/src/index.ts",
97
- "./packages/utils/src/index.ts",
98
- "./packages/coding-agent/src/extensibility/typebox.ts",
99
- "./packages/coding-agent/src/extensibility/legacy-pi-ai-shim.ts",
100
- "./packages/coding-agent/src/extensibility/legacy-pi-coding-agent-shim.ts",
85
+ // Legacy pi-* extension compat surfaces (host packages + shims)
86
+ // were previously listed as explicit `--compile` entries so the
87
+ // rewrite path could emit `/$bunfs/root/...` URLs against them.
88
+ // Bun 1.3.14 made bunfs files unreachable at runtime (issue
89
+ // #3423), so `legacy-pi-compat.ts` now serves them through a
90
+ // virtual namespace backed by `legacy-pi-bundled-registry.ts`,
91
+ // which static-imports each surface the bundler already
92
+ // includes them via the main module graph, so no `--compile`
93
+ // extras are required.
101
94
  "--outfile",
102
95
  `packages/coding-agent/dist/${outName}`,
103
96
  ],
@@ -650,6 +650,28 @@ function collectStoredAccounts(authStorage: AuthStorage): UsageAccountIdentity[]
650
650
  return accounts;
651
651
  }
652
652
 
653
+ /**
654
+ * Keep only accounts worth a usage row: those whose provider has a usage
655
+ * provider, so a missing report is a real gap rather than the absence of any
656
+ * usage concept. Providers with no usage endpoint (web-search keys, local /
657
+ * keyless servers, inference providers without a usage API) would only ever
658
+ * render as noise, so they are dropped.
659
+ *
660
+ * `hasUsageProvider` is injected (in practice {@link AuthStorage.usageProviderFor})
661
+ * so custom/broker resolvers stay authoritative — no provider list is duplicated
662
+ * here. An explicit `--provider` request bypasses the cull, so
663
+ * `omp usage --provider xai` can still confirm the stored credential has no
664
+ * usage endpoint.
665
+ */
666
+ export function selectReportableAccounts(
667
+ accounts: UsageAccountIdentity[],
668
+ hasUsageProvider: (provider: string) => boolean,
669
+ explicitProvider?: string,
670
+ ): UsageAccountIdentity[] {
671
+ if (explicitProvider) return accounts;
672
+ return accounts.filter(account => hasUsageProvider(account.provider));
673
+ }
674
+
653
675
  /** Apply a redaction mask to an optional identity field. */
654
676
  function maskIdentity(redaction: Map<string, string>, value: string | undefined): string | undefined {
655
677
  return value === undefined ? undefined : (redaction.get(value) ?? value);
@@ -721,7 +743,12 @@ export async function runUsageCommand(cmd: UsageCommandArgs): Promise<void> {
721
743
  (await authStorage.fetchUsageReports({
722
744
  baseUrlResolver: provider => modelRegistry.getProviderBaseUrl(provider),
723
745
  })) ?? [];
724
- let accounts = collectStoredAccounts(authStorage);
746
+ const storedAccounts = collectStoredAccounts(authStorage);
747
+ let accounts = selectReportableAccounts(
748
+ storedAccounts,
749
+ provider => authStorage.usageProviderFor(provider) !== undefined,
750
+ cmd.provider,
751
+ );
725
752
  let filteredReports = reports;
726
753
  if (cmd.provider) {
727
754
  const wanted = cmd.provider.toLowerCase();
@@ -764,9 +791,13 @@ export async function runUsageCommand(cmd: UsageCommandArgs): Promise<void> {
764
791
 
765
792
  if (filteredReports.length === 0 && accounts.length === 0) {
766
793
  const scope = cmd.provider ? ` for provider "${cmd.provider}"` : "";
767
- process.stderr.write(
768
- chalk.yellow(`No credentials found${scope}. Run \`omp\` and use /login to add accounts.\n`),
769
- );
794
+ // Credentials exist but every one is for a provider without a usage
795
+ // endpoint say so rather than implying nothing is logged in.
796
+ const message =
797
+ storedAccounts.length > 0
798
+ ? `No usage data${scope}. Stored credentials are for providers without a usage endpoint.\n`
799
+ : `No credentials found${scope}. Run \`omp\` and use /login to add accounts.\n`;
800
+ process.stderr.write(chalk.yellow(message));
770
801
  process.exitCode = 1;
771
802
  return;
772
803
  }
@@ -28,12 +28,23 @@ export default class Token extends Command {
28
28
  description: "Force refresh the OAuth token even if it has not expired",
29
29
  default: false,
30
30
  }),
31
+ account: Flags.integer({
32
+ char: "a",
33
+ description: "Select the Nth OAuth account (1-based) in stored order instead of the round-robin default",
34
+ }),
35
+ list: Flags.boolean({
36
+ char: "l",
37
+ description: "List the provider's OAuth accounts (index + identity) and exit",
38
+ default: false,
39
+ }),
31
40
  };
32
41
 
33
42
  static examples = [
34
43
  "# Get API key for Anthropic\n omp token anthropic",
35
44
  "# Get raw Copilot credential JSON\n omp token github-copilot --raw",
36
45
  "# Force refresh and get Gemini CLI token\n omp token google-gemini-cli --force-refresh",
46
+ "# List Anthropic OAuth accounts\n omp token anthropic --list",
47
+ "# Get the 2nd Anthropic OAuth account's token\n omp token anthropic --account 2",
37
48
  ];
38
49
 
39
50
  async run(): Promise<void> {
@@ -43,6 +54,49 @@ export default class Token extends Command {
43
54
 
44
55
  const authStorage = await discoverAuthStorage();
45
56
  try {
57
+ if (flags.list || flags.account !== undefined) {
58
+ const accounts = authStorage.listOAuthAccounts(provider);
59
+ if (accounts.length === 0) {
60
+ process.stderr.write(`${chalk.red(`No OAuth accounts found for provider "${providerName}".`)}\n`);
61
+ process.stderr.write("--account/--list select among OAuth accounts; this provider has none stored.\n");
62
+ process.exitCode = 1;
63
+ return;
64
+ }
65
+ if (flags.list) {
66
+ for (const acct of accounts) {
67
+ const label =
68
+ acct.email ??
69
+ acct.accountId ??
70
+ acct.projectId ??
71
+ acct.enterpriseUrl ??
72
+ `credential #${acct.credentialId}`;
73
+ process.stdout.write(`${acct.position + 1}. ${label}\n`);
74
+ }
75
+ return;
76
+ }
77
+ const n = flags.account;
78
+ if (n === undefined || n < 1 || n > accounts.length) {
79
+ process.stderr.write(
80
+ `${chalk.red(`Invalid --account ${n ?? "(missing)"}.`)} Provider "${providerName}" has ${accounts.length} OAuth account(s) (1-${accounts.length}).\n`,
81
+ );
82
+ process.exitCode = 1;
83
+ return;
84
+ }
85
+ const resolution = await authStorage.getOAuthAccessAt(provider, n - 1, {
86
+ forceRefresh: flags["force-refresh"],
87
+ });
88
+ if (!resolution?.ok) {
89
+ const reason = resolution && !resolution.ok ? resolution.error : "no OAuth credential available";
90
+ process.stderr.write(
91
+ `${chalk.red(`Could not get token for account ${n} of "${providerName}": ${reason}`)}\n`,
92
+ );
93
+ process.exitCode = 1;
94
+ return;
95
+ }
96
+ process.stdout.write(`${resolution.accessToken}\n`);
97
+ return;
98
+ }
99
+
46
100
  const modelRegistry = new ModelRegistry(authStorage);
47
101
 
48
102
  // Resolve the API key / token
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Static handles on every bundled `@oh-my-pi/pi-*` surface a legacy extension
3
+ * may import. Loaded lazily by `legacy-pi-compat.ts` in compiled-binary mode
4
+ * (issue #3423) and re-exported through the `omp-legacy-pi-bundled:` virtual
5
+ * namespace — bunfs paths cannot be resolved at runtime on Bun 1.3.14+, so
6
+ * the only way to re-route extension imports onto the host's in-process copy
7
+ * is via live module references captured at compile time.
8
+ *
9
+ * This module is split out from `legacy-pi-compat.ts` so dev/test runs that
10
+ * touch the compat layer never trigger the cascade through
11
+ * `legacy-pi-coding-agent-shim.ts → ../index → export/html/...` (which
12
+ * requires generated artifacts that only exist after a `bun run build`).
13
+ *
14
+ * The bundler reaches every entry below via standard static-import analysis,
15
+ * so the matching `--compile` extras can be dropped from
16
+ * `scripts/build-binary.ts`.
17
+ */
18
+ import * as bundledPiAgentCore from "@oh-my-pi/pi-agent-core";
19
+ import * as bundledPiNatives from "@oh-my-pi/pi-natives";
20
+ import * as bundledPiTui from "@oh-my-pi/pi-tui";
21
+ import * as bundledPiUtils from "@oh-my-pi/pi-utils";
22
+ import * as bundledLegacyPiAiShim from "../legacy-pi-ai-shim";
23
+ import * as bundledLegacyPiCodingAgentShim from "../legacy-pi-coding-agent-shim";
24
+ import * as bundledTypeBoxShim from "../typebox";
25
+
26
+ /**
27
+ * Canonical specifier → live module namespace. Keys MUST match the right-hand
28
+ * side of `bundledRegistryVirtualSpecifier(...)` calls in
29
+ * `legacy-pi-compat.ts`; the synthesizer enumerates each namespace's own
30
+ * enumerable exports at extension load time.
31
+ */
32
+ export const BUNDLED_PI_REGISTRY: Readonly<Record<string, Readonly<Record<string, unknown>>>> = {
33
+ "@oh-my-pi/pi-agent-core": bundledPiAgentCore,
34
+ "@oh-my-pi/pi-ai": bundledLegacyPiAiShim,
35
+ "@oh-my-pi/pi-coding-agent": bundledLegacyPiCodingAgentShim,
36
+ "@oh-my-pi/pi-natives": bundledPiNatives,
37
+ "@oh-my-pi/pi-tui": bundledPiTui,
38
+ "@oh-my-pi/pi-utils": bundledPiUtils,
39
+ typebox: bundledTypeBoxShim,
40
+ };