@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.
- package/CHANGELOG.md +19 -0
- package/dist/cli.js +16753 -16738
- package/dist/types/cli/usage-cli.d.ts +14 -0
- package/dist/types/commands/token.d.ts +9 -0
- package/dist/types/extensibility/plugins/legacy-pi-bundled-registry.d.ts +7 -0
- package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +31 -27
- package/dist/types/modes/components/extensions/extension-dashboard.d.ts +26 -10
- package/dist/types/modes/components/extensions/extension-list.d.ts +13 -0
- package/package.json +12 -12
- package/scripts/build-binary.ts +9 -16
- package/src/cli/usage-cli.ts +35 -4
- package/src/commands/token.ts +54 -0
- package/src/extensibility/plugins/legacy-pi-bundled-registry.ts +40 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +240 -122
- package/src/modes/components/extensions/extension-dashboard.ts +221 -165
- package/src/modes/components/extensions/extension-list.ts +66 -33
- package/src/modes/controllers/selector-controller.ts +4 -0
|
@@ -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
|
-
*
|
|
4
|
-
*
|
|
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
|
|
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
|
-
*
|
|
35
|
-
*
|
|
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 `
|
|
39
|
+
* Exported for tests; production callers use `TYPEBOX_SHIM_PATH`.
|
|
38
40
|
*/
|
|
39
|
-
export declare function
|
|
41
|
+
export declare function __resolveTypeBoxShimPath(isCompiled: boolean, sourcePath: string, pathExistsSync?: (p: string) => boolean): string | null;
|
|
40
42
|
/**
|
|
41
|
-
* Drop overrides whose targets are missing
|
|
42
|
-
* the canonical-resolution path.
|
|
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`;
|
|
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 -
|
|
2
|
+
* ExtensionDashboard - Fullscreen alternate-screen control center for extensions.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
-
* -
|
|
10
|
-
* - Up/Down/j/k:
|
|
11
|
-
* - Space:
|
|
12
|
-
* -
|
|
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 {
|
|
16
|
+
import { type Component, type Tab } from "@oh-my-pi/pi-tui";
|
|
15
17
|
import { Settings } from "../../../config/settings";
|
|
16
|
-
|
|
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.
|
|
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.
|
|
52
|
-
"@oh-my-pi/omp-stats": "16.1.
|
|
53
|
-
"@oh-my-pi/pi-agent-core": "16.1.
|
|
54
|
-
"@oh-my-pi/pi-ai": "16.1.
|
|
55
|
-
"@oh-my-pi/pi-catalog": "16.1.
|
|
56
|
-
"@oh-my-pi/pi-mnemopi": "16.1.
|
|
57
|
-
"@oh-my-pi/pi-natives": "16.1.
|
|
58
|
-
"@oh-my-pi/pi-tui": "16.1.
|
|
59
|
-
"@oh-my-pi/pi-utils": "16.1.
|
|
60
|
-
"@oh-my-pi/pi-wire": "16.1.
|
|
61
|
-
"@oh-my-pi/snapcompact": "16.1.
|
|
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",
|
package/scripts/build-binary.ts
CHANGED
|
@@ -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
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
//
|
|
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
|
],
|
package/src/cli/usage-cli.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
768
|
-
|
|
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
|
}
|
package/src/commands/token.ts
CHANGED
|
@@ -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
|
+
};
|