oc-codex-multi-auth 6.21.0 → 6.22.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/LICENSE +21 -21
- package/README.md +729 -571
- package/assets/icon.svg +7 -7
- package/assets/opencode-logo-ornate-dark.svg +18 -18
- package/assets/readme-hero.svg +31 -31
- package/config/README.md +177 -177
- package/config/minimal-opencode.json +14 -14
- package/config/opencode-legacy.json +1496 -1496
- package/config/opencode-modern.json +555 -555
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +291 -53
- package/dist/index.js.map +1 -1
- package/dist/lib/account-display.d.ts +46 -0
- package/dist/lib/account-display.d.ts.map +1 -1
- package/dist/lib/account-display.js +260 -0
- package/dist/lib/account-display.js.map +1 -1
- package/dist/lib/accounts.d.ts +4 -0
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +20 -15
- package/dist/lib/accounts.js.map +1 -1
- package/dist/lib/auth/login-runner.d.ts.map +1 -1
- package/dist/lib/auth/login-runner.js +79 -2
- package/dist/lib/auth/login-runner.js.map +1 -1
- package/dist/lib/auto-update-checker.d.ts +17 -1
- package/dist/lib/auto-update-checker.d.ts.map +1 -1
- package/dist/lib/auto-update-checker.js +49 -3
- package/dist/lib/auto-update-checker.js.map +1 -1
- package/dist/lib/cli.d.ts +1 -0
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +9 -3
- package/dist/lib/cli.js.map +1 -1
- package/dist/lib/codex-usage.d.ts +4 -3
- package/dist/lib/codex-usage.d.ts.map +1 -1
- package/dist/lib/codex-usage.js +13 -11
- package/dist/lib/codex-usage.js.map +1 -1
- package/dist/lib/config.d.ts +75 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +152 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/desktop-notifications.js +6 -6
- package/dist/lib/oauth-success.js +202 -202
- package/dist/lib/plan-allotment.d.ts +72 -0
- package/dist/lib/plan-allotment.d.ts.map +1 -0
- package/dist/lib/plan-allotment.js +142 -0
- package/dist/lib/plan-allotment.js.map +1 -0
- package/dist/lib/plugin-origin.d.ts +77 -0
- package/dist/lib/plugin-origin.d.ts.map +1 -0
- package/dist/lib/plugin-origin.js +301 -0
- package/dist/lib/plugin-origin.js.map +1 -0
- package/dist/lib/prompts/codex-opencode-bridge.js +67 -67
- package/dist/lib/prompts/codex.js +75 -75
- package/dist/lib/quota-display.d.ts +40 -0
- package/dist/lib/quota-display.d.ts.map +1 -0
- package/dist/lib/quota-display.js +45 -0
- package/dist/lib/quota-display.js.map +1 -0
- package/dist/lib/quota-notifications.d.ts +2 -1
- package/dist/lib/quota-notifications.d.ts.map +1 -1
- package/dist/lib/quota-notifications.js +34 -14
- package/dist/lib/quota-notifications.js.map +1 -1
- package/dist/lib/quota-overview.d.ts +253 -0
- package/dist/lib/quota-overview.d.ts.map +1 -0
- package/dist/lib/quota-overview.js +707 -0
- package/dist/lib/quota-overview.js.map +1 -0
- package/dist/lib/request/retry-budget.d.ts +26 -0
- package/dist/lib/request/retry-budget.d.ts.map +1 -1
- package/dist/lib/request/retry-budget.js +43 -0
- package/dist/lib/request/retry-budget.js.map +1 -1
- package/dist/lib/schemas.d.ts +67 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +53 -0
- package/dist/lib/schemas.js.map +1 -1
- package/dist/lib/storage/backup.d.ts +33 -0
- package/dist/lib/storage/backup.d.ts.map +1 -1
- package/dist/lib/storage/backup.js +43 -7
- package/dist/lib/storage/backup.js.map +1 -1
- package/dist/lib/storage/credential-snapshots.d.ts +78 -0
- package/dist/lib/storage/credential-snapshots.d.ts.map +1 -0
- package/dist/lib/storage/credential-snapshots.js +302 -0
- package/dist/lib/storage/credential-snapshots.js.map +1 -0
- package/dist/lib/storage/export-import.d.ts.map +1 -1
- package/dist/lib/storage/export-import.js +7 -0
- package/dist/lib/storage/export-import.js.map +1 -1
- package/dist/lib/storage/flagged.d.ts.map +1 -1
- package/dist/lib/storage/flagged.js +23 -1
- package/dist/lib/storage/flagged.js.map +1 -1
- package/dist/lib/storage/load-save.d.ts +4 -0
- package/dist/lib/storage/load-save.d.ts.map +1 -1
- package/dist/lib/storage/load-save.js +50 -0
- package/dist/lib/storage/load-save.js.map +1 -1
- package/dist/lib/storage/paths.d.ts +1 -0
- package/dist/lib/storage/paths.d.ts.map +1 -1
- package/dist/lib/storage/paths.js +1 -1
- package/dist/lib/storage/paths.js.map +1 -1
- package/dist/lib/storage/test-home-guard.d.ts +35 -0
- package/dist/lib/storage/test-home-guard.d.ts.map +1 -0
- package/dist/lib/storage/test-home-guard.js +59 -0
- package/dist/lib/storage/test-home-guard.js.map +1 -0
- package/dist/lib/tools/codex-dashboard.d.ts.map +1 -1
- package/dist/lib/tools/codex-dashboard.js +3 -2
- package/dist/lib/tools/codex-dashboard.js.map +1 -1
- package/dist/lib/tools/codex-doctor.d.ts.map +1 -1
- package/dist/lib/tools/codex-doctor.js +16 -0
- package/dist/lib/tools/codex-doctor.js.map +1 -1
- package/dist/lib/tools/codex-health.d.ts.map +1 -1
- package/dist/lib/tools/codex-health.js +10 -2
- package/dist/lib/tools/codex-health.js.map +1 -1
- package/dist/lib/tools/codex-label.d.ts.map +1 -1
- package/dist/lib/tools/codex-label.js +1 -0
- package/dist/lib/tools/codex-label.js.map +1 -1
- package/dist/lib/tools/codex-limits.d.ts.map +1 -1
- package/dist/lib/tools/codex-limits.js +13 -9
- package/dist/lib/tools/codex-limits.js.map +1 -1
- package/dist/lib/tools/codex-list.d.ts.map +1 -1
- package/dist/lib/tools/codex-list.js +28 -3
- package/dist/lib/tools/codex-list.js.map +1 -1
- package/dist/lib/tools/codex-note.d.ts.map +1 -1
- package/dist/lib/tools/codex-note.js +4 -1
- package/dist/lib/tools/codex-note.js.map +1 -1
- package/dist/lib/tools/codex-pool.d.ts.map +1 -1
- package/dist/lib/tools/codex-pool.js +6 -2
- package/dist/lib/tools/codex-pool.js.map +1 -1
- package/dist/lib/tools/codex-refresh.d.ts.map +1 -1
- package/dist/lib/tools/codex-refresh.js +4 -1
- package/dist/lib/tools/codex-refresh.js.map +1 -1
- package/dist/lib/tools/codex-remove.d.ts.map +1 -1
- package/dist/lib/tools/codex-remove.js +1 -0
- package/dist/lib/tools/codex-remove.js.map +1 -1
- package/dist/lib/tools/codex-reset.d.ts.map +1 -1
- package/dist/lib/tools/codex-reset.js +13 -7
- package/dist/lib/tools/codex-reset.js.map +1 -1
- package/dist/lib/tools/codex-status.d.ts.map +1 -1
- package/dist/lib/tools/codex-status.js +25 -2
- package/dist/lib/tools/codex-status.js.map +1 -1
- package/dist/lib/tools/codex-switch.d.ts.map +1 -1
- package/dist/lib/tools/codex-switch.js +1 -0
- package/dist/lib/tools/codex-switch.js.map +1 -1
- package/dist/lib/tools/codex-tag.d.ts.map +1 -1
- package/dist/lib/tools/codex-tag.js +4 -1
- package/dist/lib/tools/codex-tag.js.map +1 -1
- package/dist/lib/tools/codex-warm.d.ts.map +1 -1
- package/dist/lib/tools/codex-warm.js +1 -0
- package/dist/lib/tools/codex-warm.js.map +1 -1
- package/dist/lib/tools/index.d.ts +9 -0
- package/dist/lib/tools/index.d.ts.map +1 -1
- package/dist/lib/tools/index.js.map +1 -1
- package/dist/lib/tui-quota-cache.d.ts +35 -0
- package/dist/lib/tui-quota-cache.d.ts.map +1 -1
- package/dist/lib/tui-quota-cache.js +76 -11
- package/dist/lib/tui-quota-cache.js.map +1 -1
- package/dist/lib/tui-quota-overview.d.ts +55 -0
- package/dist/lib/tui-quota-overview.d.ts.map +1 -0
- package/dist/lib/tui-quota-overview.js +209 -0
- package/dist/lib/tui-quota-overview.js.map +1 -0
- package/dist/lib/tui-status.d.ts +55 -0
- package/dist/lib/tui-status.d.ts.map +1 -1
- package/dist/lib/tui-status.js +155 -14
- package/dist/lib/tui-status.js.map +1 -1
- package/dist/lib/ui/auth-menu.d.ts +2 -0
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +10 -6
- package/dist/lib/ui/auth-menu.js.map +1 -1
- package/dist/tui.d.ts +55 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +511 -29
- package/dist/tui.js.map +1 -1
- package/package.json +155 -155
- package/scripts/audit-dev-allowlist.js +114 -114
- package/scripts/clean-dist.js +27 -27
- package/scripts/copy-oauth-success.js +47 -47
- package/scripts/install-oc-codex-multi-auth-core.js +2003 -1499
- package/scripts/install-oc-codex-multi-auth.js +37 -37
- package/scripts/test-all-models.sh +260 -260
- package/scripts/validate-model-map.sh +97 -97
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where this plugin is running from, and where it has run from before.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode can load the plugin from the published package or from a checkout
|
|
5
|
+
* a developer points it at, and the two are indistinguishable at runtime
|
|
6
|
+
* unless the plugin asks. Knowing which one is live decides whether offering
|
|
7
|
+
* an update makes sense, and a record of previous origins is what turns "my
|
|
8
|
+
* edits stopped taking effect" into a diagnosable event.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The origin history file name, shared with the installer.
|
|
12
|
+
*
|
|
13
|
+
* The installer is plain JS that must run before anything is built, so it
|
|
14
|
+
* cannot import this module and declares the same name itself. A test pins the
|
|
15
|
+
* two together, because a silent disagreement would leave each side reporting
|
|
16
|
+
* confidently about a file the other never writes.
|
|
17
|
+
*/
|
|
18
|
+
export declare const HISTORY_FILE_NAME = "oc-codex-multi-auth-origin.json";
|
|
19
|
+
export interface PluginOrigin {
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
root: string;
|
|
23
|
+
isLocalCheckout: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface PluginOriginSighting extends PluginOrigin {
|
|
26
|
+
firstSeen: string;
|
|
27
|
+
lastSeen: string;
|
|
28
|
+
}
|
|
29
|
+
export interface PluginOriginHistory {
|
|
30
|
+
version: number;
|
|
31
|
+
sightings: PluginOriginSighting[];
|
|
32
|
+
}
|
|
33
|
+
/** Built output lives inside the package, so the root is at or above it. */
|
|
34
|
+
export declare function findPackageRoot(startDirectory: string): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* A root a package manager chose, as opposed to one a human did. The version
|
|
37
|
+
* suffix is what separates OpenCode's plugin cache from a monorepo that merely
|
|
38
|
+
* keeps its packages in a `packages/` directory.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isPackageManagerRoot(root: string, platform?: NodeJS.Platform, cacheDirectory?: string): boolean;
|
|
41
|
+
export declare function resolvePluginOrigin(moduleUrl: string): PluginOrigin | null;
|
|
42
|
+
/** The origin of this running build. Fixed for the life of the process. */
|
|
43
|
+
export declare function getPluginOrigin(): PluginOrigin | null;
|
|
44
|
+
export declare function getPluginOriginHistoryPath(home?: string): string;
|
|
45
|
+
export declare function readPluginOriginHistory(historyPath?: string): PluginOriginHistory;
|
|
46
|
+
/**
|
|
47
|
+
* History is appended to rather than overwritten, so one origin replacing
|
|
48
|
+
* another leaves both on record. A last-writer-wins marker would instead
|
|
49
|
+
* confirm whatever state a clobber left behind.
|
|
50
|
+
*/
|
|
51
|
+
export declare function withSighting(history: PluginOriginHistory, origin: PluginOrigin, seenAt: string, platform?: NodeJS.Platform): PluginOriginHistory;
|
|
52
|
+
/**
|
|
53
|
+
* Records this origin without dropping anybody else's.
|
|
54
|
+
*
|
|
55
|
+
* Every OpenCode process records at startup, and a machine running many of
|
|
56
|
+
* them starts several at once, so read-modify-write on a shared file is a real
|
|
57
|
+
* race rather than a theoretical one. The reader that matters here asks which
|
|
58
|
+
* origins have been seen, so a lost sighting is a lost answer: the very
|
|
59
|
+
* handover this file exists to report - a checkout replaced by the installed
|
|
60
|
+
* package - is two different origins written at close to the same time.
|
|
61
|
+
*
|
|
62
|
+
* The history is therefore re-read INSIDE the lease, so each writer merges
|
|
63
|
+
* into what is actually on disk. A writer that cannot take the lease records
|
|
64
|
+
* nothing rather than overwriting blind; it is about to be started again, and
|
|
65
|
+
* a missing sighting costs a later startup while a clobbered one costs the
|
|
66
|
+
* only evidence there was. A lease reclaimed mid-write is the same situation
|
|
67
|
+
* arriving later, and is answered the same way.
|
|
68
|
+
*/
|
|
69
|
+
export declare function recordPluginOrigin(origin: PluginOrigin, historyPath?: string, now?: () => Date): Promise<PluginOriginHistory>;
|
|
70
|
+
/**
|
|
71
|
+
* The checkout this plugin used to run from and no longer does. Reported only
|
|
72
|
+
* when the current origin is package-manager output, since a move between two
|
|
73
|
+
* checkouts is an ordinary thing to do deliberately.
|
|
74
|
+
*/
|
|
75
|
+
export declare function findReplacedLocalCheckout(origin: PluginOrigin, history: PluginOriginHistory, platform?: NodeJS.Platform): PluginOriginSighting | null;
|
|
76
|
+
export declare function describePluginOrigin(origin: PluginOrigin | null): string;
|
|
77
|
+
//# sourceMappingURL=plugin-origin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-origin.d.ts","sourceRoot":"","sources":["../../lib/plugin-origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,oCAAoC,CAAC;AA0BnE,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CAClC;AA0BD,4EAA4E;AAC5E,wBAAgB,eAAe,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASrE;AAkCD;;;;GAIG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,cAAc,GAAE,MAAgC,GAC9C,OAAO,CAYT;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAiB1E;AAID,2EAA2E;AAC3E,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAGrD;AAED,wBAAgB,0BAA0B,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAE3E;AAeD,wBAAgB,uBAAuB,CACtC,WAAW,GAAE,MAAqC,GAChD,mBAAmB,CAUrB;AAMD;;;;GAIG;AACH,wBAAgB,YAAY,CAC3B,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC1C,mBAAmB,CAiBrB;AA6BD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,kBAAkB,CACvC,MAAM,EAAE,YAAY,EACpB,WAAW,GAAE,MAAqC,EAClD,GAAG,GAAE,MAAM,IAAuB,GAChC,OAAO,CAAC,mBAAmB,CAAC,CA4C9B;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC1C,oBAAoB,GAAG,IAAI,CAc7B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,MAAM,CAKxE"}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where this plugin is running from, and where it has run from before.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode can load the plugin from the published package or from a checkout
|
|
5
|
+
* a developer points it at, and the two are indistinguishable at runtime
|
|
6
|
+
* unless the plugin asks. Knowing which one is live decides whether offering
|
|
7
|
+
* an update makes sense, and a record of previous origins is what turns "my
|
|
8
|
+
* edits stopped taking effect" into a diagnosable event.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { lock } from "proper-lockfile";
|
|
16
|
+
import { createLogger } from "./logger.js";
|
|
17
|
+
import { renameWithWindowsRetry } from "./storage/atomic-write.js";
|
|
18
|
+
const log = createLogger("plugin-origin");
|
|
19
|
+
/**
|
|
20
|
+
* The origin history file name, shared with the installer.
|
|
21
|
+
*
|
|
22
|
+
* The installer is plain JS that must run before anything is built, so it
|
|
23
|
+
* cannot import this module and declares the same name itself. A test pins the
|
|
24
|
+
* two together, because a silent disagreement would leave each side reporting
|
|
25
|
+
* confidently about a file the other never writes.
|
|
26
|
+
*/
|
|
27
|
+
export const HISTORY_FILE_NAME = "oc-codex-multi-auth-origin.json";
|
|
28
|
+
const HISTORY_VERSION = 1;
|
|
29
|
+
const MAX_SIGHTINGS = 10;
|
|
30
|
+
const PACKAGE_ROOT_LOOKUP_DEPTH = 3;
|
|
31
|
+
/** The lease covers one small read and one small write, so it is short. */
|
|
32
|
+
const HISTORY_LOCK_STALE_MS = 10_000;
|
|
33
|
+
const HISTORY_LOCK_UPDATE_MS = 2_000;
|
|
34
|
+
const HISTORY_LOCK_RETRIES = {
|
|
35
|
+
retries: 10,
|
|
36
|
+
factor: 1.8,
|
|
37
|
+
minTimeout: 50,
|
|
38
|
+
maxTimeout: 500,
|
|
39
|
+
randomize: true,
|
|
40
|
+
};
|
|
41
|
+
const MANAGED_PACKAGE_NAMES = new Set(["oc-codex-multi-auth", "oc-chatgpt-multi-auth"]);
|
|
42
|
+
function isManagedPackageName(name) {
|
|
43
|
+
return MANAGED_PACKAGE_NAMES.has(name.toLowerCase());
|
|
44
|
+
}
|
|
45
|
+
function defaultCacheDirectory(home = homedir()) {
|
|
46
|
+
return join(home, ".cache", "opencode");
|
|
47
|
+
}
|
|
48
|
+
function emptyHistory() {
|
|
49
|
+
return { version: HISTORY_VERSION, sightings: [] };
|
|
50
|
+
}
|
|
51
|
+
function readPackageManifest(directory) {
|
|
52
|
+
try {
|
|
53
|
+
const parsed = JSON.parse(readFileSync(join(directory, "package.json"), "utf8"));
|
|
54
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
55
|
+
return null;
|
|
56
|
+
return parsed;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function manifestName(manifest) {
|
|
63
|
+
const name = manifest?.name;
|
|
64
|
+
return typeof name === "string" && name.trim() ? name.trim() : null;
|
|
65
|
+
}
|
|
66
|
+
/** Built output lives inside the package, so the root is at or above it. */
|
|
67
|
+
export function findPackageRoot(startDirectory) {
|
|
68
|
+
let current = resolve(startDirectory);
|
|
69
|
+
for (let depth = 0; depth <= PACKAGE_ROOT_LOOKUP_DEPTH; depth += 1) {
|
|
70
|
+
if (manifestName(readPackageManifest(current)))
|
|
71
|
+
return current;
|
|
72
|
+
const parent = dirname(current);
|
|
73
|
+
if (parent === current)
|
|
74
|
+
return null;
|
|
75
|
+
current = parent;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function pathSegments(path) {
|
|
80
|
+
return path.replaceAll("\\", "/").replace(/\/+$/, "").split("/").filter(Boolean);
|
|
81
|
+
}
|
|
82
|
+
function foldPathCase(value, platform) {
|
|
83
|
+
return platform === "win32" || platform === "darwin" ? value.toLowerCase() : value;
|
|
84
|
+
}
|
|
85
|
+
function isInsideDirectory(candidate, directory, platform) {
|
|
86
|
+
const relativePath = relative(foldPathCase(resolve(directory), platform), foldPathCase(resolve(candidate), platform));
|
|
87
|
+
return relativePath !== "" && !relativePath.startsWith("..") && !isAbsolute(relativePath);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* How two spellings of a root are told apart. Windows reaches one directory
|
|
91
|
+
* under several of them, and so does a default-case-insensitive APFS volume,
|
|
92
|
+
* so comparing verbatim there would let `C:\Repo` and `c:\repo` - or `/Repo`
|
|
93
|
+
* and `/repo` - occupy two slots in a bounded history and evict a genuinely
|
|
94
|
+
* different origin between them.
|
|
95
|
+
*/
|
|
96
|
+
function rootComparisonKey(root, platform = process.platform) {
|
|
97
|
+
const normalized = root.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
98
|
+
return foldPathCase(normalized, platform);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A root a package manager chose, as opposed to one a human did. The version
|
|
102
|
+
* suffix is what separates OpenCode's plugin cache from a monorepo that merely
|
|
103
|
+
* keeps its packages in a `packages/` directory.
|
|
104
|
+
*/
|
|
105
|
+
export function isPackageManagerRoot(root, platform = process.platform, cacheDirectory = defaultCacheDirectory()) {
|
|
106
|
+
const segments = pathSegments(root).map((segment) => foldPathCase(segment, platform));
|
|
107
|
+
if (segments.some((segment, index) => segment === "node_modules" ||
|
|
108
|
+
(segments[index - 1] === "packages" && segment.includes("@")))) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
return isInsideDirectory(root, cacheDirectory, platform);
|
|
112
|
+
}
|
|
113
|
+
export function resolvePluginOrigin(moduleUrl) {
|
|
114
|
+
let moduleDirectory;
|
|
115
|
+
try {
|
|
116
|
+
moduleDirectory = dirname(fileURLToPath(moduleUrl));
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const root = findPackageRoot(moduleDirectory);
|
|
122
|
+
if (!root)
|
|
123
|
+
return null;
|
|
124
|
+
const manifest = readPackageManifest(root);
|
|
125
|
+
const name = manifestName(manifest);
|
|
126
|
+
if (!name || !isManagedPackageName(name))
|
|
127
|
+
return null;
|
|
128
|
+
const version = typeof manifest?.version === "string" ? manifest.version : "0.0.0";
|
|
129
|
+
return { name, version, root, isLocalCheckout: !isPackageManagerRoot(root) };
|
|
130
|
+
}
|
|
131
|
+
let cachedOrigin;
|
|
132
|
+
/** The origin of this running build. Fixed for the life of the process. */
|
|
133
|
+
export function getPluginOrigin() {
|
|
134
|
+
if (cachedOrigin === undefined)
|
|
135
|
+
cachedOrigin = resolvePluginOrigin(import.meta.url);
|
|
136
|
+
return cachedOrigin;
|
|
137
|
+
}
|
|
138
|
+
export function getPluginOriginHistoryPath(home = homedir()) {
|
|
139
|
+
return join(home, ".opencode", HISTORY_FILE_NAME);
|
|
140
|
+
}
|
|
141
|
+
function isSighting(value) {
|
|
142
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
143
|
+
return false;
|
|
144
|
+
const candidate = value;
|
|
145
|
+
return (typeof candidate.name === "string" &&
|
|
146
|
+
typeof candidate.version === "string" &&
|
|
147
|
+
typeof candidate.root === "string" &&
|
|
148
|
+
typeof candidate.isLocalCheckout === "boolean" &&
|
|
149
|
+
typeof candidate.firstSeen === "string" &&
|
|
150
|
+
typeof candidate.lastSeen === "string");
|
|
151
|
+
}
|
|
152
|
+
export function readPluginOriginHistory(historyPath = getPluginOriginHistoryPath()) {
|
|
153
|
+
try {
|
|
154
|
+
const parsed = JSON.parse(readFileSync(historyPath, "utf8"));
|
|
155
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
156
|
+
return emptyHistory();
|
|
157
|
+
const sightings = parsed.sightings;
|
|
158
|
+
if (!Array.isArray(sightings))
|
|
159
|
+
return emptyHistory();
|
|
160
|
+
return { version: HISTORY_VERSION, sightings: sightings.filter(isSighting) };
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
return emptyHistory();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function byLastSeen(left, right) {
|
|
167
|
+
return (Date.parse(left.lastSeen) || 0) - (Date.parse(right.lastSeen) || 0);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* History is appended to rather than overwritten, so one origin replacing
|
|
171
|
+
* another leaves both on record. A last-writer-wins marker would instead
|
|
172
|
+
* confirm whatever state a clobber left behind.
|
|
173
|
+
*/
|
|
174
|
+
export function withSighting(history, origin, seenAt, platform = process.platform) {
|
|
175
|
+
// Matched on the comparison key, recorded as the origin spells it: a reader
|
|
176
|
+
// is shown the path they configured, not a folded version of it.
|
|
177
|
+
const key = rootComparisonKey(origin.root, platform);
|
|
178
|
+
const sameRoot = (sighting) => rootComparisonKey(sighting.root, platform) === key;
|
|
179
|
+
const previous = history.sightings.find(sameRoot);
|
|
180
|
+
const others = history.sightings.filter((sighting) => !sameRoot(sighting));
|
|
181
|
+
const current = {
|
|
182
|
+
...origin,
|
|
183
|
+
firstSeen: previous?.firstSeen ?? seenAt,
|
|
184
|
+
lastSeen: seenAt,
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
version: HISTORY_VERSION,
|
|
188
|
+
sightings: [...others, current].slice(-MAX_SIGHTINGS),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Replaces the history, unless ownership was lost while the new copy was being
|
|
193
|
+
* written. Only the rename is visible to anybody else, so that is where the
|
|
194
|
+
* question has to be asked: checking earlier leaves the whole of `writeFile`
|
|
195
|
+
* as a window in which the lease can be reclaimed and newer history written,
|
|
196
|
+
* which this rename would then replace with an older snapshot.
|
|
197
|
+
*
|
|
198
|
+
* Returns whether the replacement happened.
|
|
199
|
+
*/
|
|
200
|
+
async function writeHistory(historyPath, history, stillOwned) {
|
|
201
|
+
const temporaryPath = `${historyPath}.${process.pid}.tmp`;
|
|
202
|
+
await writeFile(temporaryPath, `${JSON.stringify(history, null, 2)}\n`, "utf-8");
|
|
203
|
+
try {
|
|
204
|
+
if (!stillOwned())
|
|
205
|
+
return false;
|
|
206
|
+
await renameWithWindowsRetry(temporaryPath, historyPath);
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
if (existsSync(temporaryPath)) {
|
|
211
|
+
await rm(temporaryPath, { force: true }).catch(() => undefined);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Records this origin without dropping anybody else's.
|
|
217
|
+
*
|
|
218
|
+
* Every OpenCode process records at startup, and a machine running many of
|
|
219
|
+
* them starts several at once, so read-modify-write on a shared file is a real
|
|
220
|
+
* race rather than a theoretical one. The reader that matters here asks which
|
|
221
|
+
* origins have been seen, so a lost sighting is a lost answer: the very
|
|
222
|
+
* handover this file exists to report - a checkout replaced by the installed
|
|
223
|
+
* package - is two different origins written at close to the same time.
|
|
224
|
+
*
|
|
225
|
+
* The history is therefore re-read INSIDE the lease, so each writer merges
|
|
226
|
+
* into what is actually on disk. A writer that cannot take the lease records
|
|
227
|
+
* nothing rather than overwriting blind; it is about to be started again, and
|
|
228
|
+
* a missing sighting costs a later startup while a clobbered one costs the
|
|
229
|
+
* only evidence there was. A lease reclaimed mid-write is the same situation
|
|
230
|
+
* arriving later, and is answered the same way.
|
|
231
|
+
*/
|
|
232
|
+
export async function recordPluginOrigin(origin, historyPath = getPluginOriginHistoryPath(), now = () => new Date()) {
|
|
233
|
+
await mkdir(dirname(historyPath), { recursive: true });
|
|
234
|
+
let compromised;
|
|
235
|
+
let release = null;
|
|
236
|
+
try {
|
|
237
|
+
release = await lock(historyPath, {
|
|
238
|
+
realpath: false,
|
|
239
|
+
lockfilePath: `${historyPath}.lock`,
|
|
240
|
+
stale: HISTORY_LOCK_STALE_MS,
|
|
241
|
+
update: HISTORY_LOCK_UPDATE_MS,
|
|
242
|
+
retries: HISTORY_LOCK_RETRIES,
|
|
243
|
+
// proper-lockfile's default rethrows from the timer that refreshes the
|
|
244
|
+
// lease, so it lands outside every promise chain and ends the process
|
|
245
|
+
// hosting this plugin. A stalled event loop is enough to trigger it.
|
|
246
|
+
// Nothing here is worth an editor closing, so the loss is recorded and
|
|
247
|
+
// the write is abandoned instead.
|
|
248
|
+
onCompromised: (error) => {
|
|
249
|
+
compromised = error;
|
|
250
|
+
log.warn("The plugin origin history lease was reclaimed", {
|
|
251
|
+
path: `${historyPath}.lock`,
|
|
252
|
+
error: error.message,
|
|
253
|
+
});
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
log.debug("Skipped recording the plugin origin; another process holds the history", {
|
|
259
|
+
error: error instanceof Error ? error.message : String(error),
|
|
260
|
+
});
|
|
261
|
+
return readPluginOriginHistory(historyPath);
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
const next = withSighting(readPluginOriginHistory(historyPath), origin, now().toISOString());
|
|
265
|
+
// Whoever reclaimed the lease owns the file now, so writing what we read
|
|
266
|
+
// before they did would drop their sighting - the clobber the lease
|
|
267
|
+
// exists to prevent. Asked again at the rename, since the lease can be
|
|
268
|
+
// lost at any point up to it.
|
|
269
|
+
if (compromised)
|
|
270
|
+
return readPluginOriginHistory(historyPath);
|
|
271
|
+
const written = await writeHistory(historyPath, next, () => !compromised);
|
|
272
|
+
return written ? next : readPluginOriginHistory(historyPath);
|
|
273
|
+
}
|
|
274
|
+
finally {
|
|
275
|
+
await release().catch(() => undefined);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The checkout this plugin used to run from and no longer does. Reported only
|
|
280
|
+
* when the current origin is package-manager output, since a move between two
|
|
281
|
+
* checkouts is an ordinary thing to do deliberately.
|
|
282
|
+
*/
|
|
283
|
+
export function findReplacedLocalCheckout(origin, history, platform = process.platform) {
|
|
284
|
+
if (origin.isLocalCheckout)
|
|
285
|
+
return null;
|
|
286
|
+
const currentKey = rootComparisonKey(origin.root, platform);
|
|
287
|
+
return (history.sightings
|
|
288
|
+
.filter((sighting) => isManagedPackageName(sighting.name) &&
|
|
289
|
+
sighting.isLocalCheckout &&
|
|
290
|
+
rootComparisonKey(sighting.root, platform) !== currentKey)
|
|
291
|
+
.sort(byLastSeen)
|
|
292
|
+
.at(-1) ?? null);
|
|
293
|
+
}
|
|
294
|
+
export function describePluginOrigin(origin) {
|
|
295
|
+
if (!origin)
|
|
296
|
+
return "unknown";
|
|
297
|
+
return origin.isLocalCheckout
|
|
298
|
+
? `local checkout at ${origin.root} (v${origin.version})`
|
|
299
|
+
: `installed package v${origin.version}`;
|
|
300
|
+
}
|
|
301
|
+
//# sourceMappingURL=plugin-origin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-origin.js","sourceRoot":"","sources":["../../lib/plugin-origin.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,73 +7,73 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Token Count: ~450 tokens (~90% reduction vs full OpenCode prompt)
|
|
9
9
|
*/
|
|
10
|
-
export const CODEX_OPENCODE_BRIDGE = `# Codex Running in OpenCode
|
|
11
|
-
|
|
12
|
-
You are running Codex through OpenCode, an open-source terminal coding assistant.
|
|
13
|
-
|
|
14
|
-
## Runtime Tooling Rule (Highest Priority)
|
|
15
|
-
|
|
16
|
-
<critical_rule priority="0">
|
|
17
|
-
Treat the runtime tool manifest as the only authoritative tool list.
|
|
18
|
-
- Call ONLY tool names listed in that manifest.
|
|
19
|
-
- Do NOT translate, alias, or rename tool names.
|
|
20
|
-
- If a base instruction references a tool name that is not listed, ignore that alias and use the listed names only.
|
|
21
|
-
</critical_rule>
|
|
22
|
-
|
|
23
|
-
## Tool-Call Guardrails
|
|
24
|
-
|
|
25
|
-
- Follow the current tool schema exactly for parameters.
|
|
26
|
-
- Do not invent wrapper namespaces unless they are explicitly listed as tools.
|
|
27
|
-
- If no explicit parallel helper tool is listed, run calls sequentially.
|
|
28
|
-
- If a tool call fails validation, correct arguments to match schema and retry.
|
|
29
|
-
|
|
30
|
-
## Planning & Modes
|
|
31
|
-
|
|
32
|
-
- Never call \`update_plan\`, \`read_plan\`, or similarly named aliases.
|
|
33
|
-
- Use planning tools only if they are explicitly listed in the runtime manifest.
|
|
34
|
-
- \`request_user_input\` is Plan-mode only; never call it in Default mode.
|
|
35
|
-
|
|
36
|
-
## Path & Execution Discipline
|
|
37
|
-
|
|
38
|
-
- Follow per-tool path conventions from the active schema; do not assume absolute/relative behavior.
|
|
39
|
-
- Prefer specialized tools over shell when an equivalent listed tool exists.
|
|
40
|
-
- Use non-destructive checks before destructive commands.
|
|
41
|
-
|
|
42
|
-
## Verification Checklist
|
|
43
|
-
|
|
44
|
-
Before each tool call:
|
|
45
|
-
1. Is the tool name exactly listed in the runtime manifest?
|
|
46
|
-
2. Do arguments match the listed schema?
|
|
47
|
-
3. Am I avoiding unlisted aliases and wrapper namespaces?
|
|
48
|
-
4. Am I following mode/path constraints for this environment?
|
|
49
|
-
|
|
50
|
-
If any answer is NO, correct it before proceeding.
|
|
51
|
-
|
|
52
|
-
## OpenCode Working Style
|
|
53
|
-
|
|
54
|
-
**Communication:**
|
|
55
|
-
- Send brief preambles before tool calls.
|
|
56
|
-
- Provide concise progress updates during longer tasks.
|
|
57
|
-
|
|
58
|
-
**Execution:**
|
|
59
|
-
- Continue working until the user request is fully resolved.
|
|
60
|
-
- Do not return partial solutions unless blocked.
|
|
61
|
-
|
|
62
|
-
**Code Approach:**
|
|
63
|
-
- New projects: be creative and deliberate.
|
|
64
|
-
- Existing codebases: make precise, minimal changes aligned to request.
|
|
65
|
-
|
|
66
|
-
**Testing:**
|
|
67
|
-
- If tests exist, run focused tests first, then broader validation.
|
|
68
|
-
|
|
69
|
-
## What Remains from Codex
|
|
70
|
-
|
|
71
|
-
Sandbox policies, approvals, final formatting, git protocols, and file reference formats still follow Codex instructions.
|
|
72
|
-
|
|
73
|
-
## Approvals & Safety
|
|
74
|
-
|
|
75
|
-
- Treat destructive commands (for example \`rm\`, \`git reset --hard\`) as requiring explicit user request or approval.
|
|
76
|
-
- Never run \`git reset --hard\`, \`git checkout --\`, or force deletes unless explicitly requested.
|
|
10
|
+
export const CODEX_OPENCODE_BRIDGE = `# Codex Running in OpenCode
|
|
11
|
+
|
|
12
|
+
You are running Codex through OpenCode, an open-source terminal coding assistant.
|
|
13
|
+
|
|
14
|
+
## Runtime Tooling Rule (Highest Priority)
|
|
15
|
+
|
|
16
|
+
<critical_rule priority="0">
|
|
17
|
+
Treat the runtime tool manifest as the only authoritative tool list.
|
|
18
|
+
- Call ONLY tool names listed in that manifest.
|
|
19
|
+
- Do NOT translate, alias, or rename tool names.
|
|
20
|
+
- If a base instruction references a tool name that is not listed, ignore that alias and use the listed names only.
|
|
21
|
+
</critical_rule>
|
|
22
|
+
|
|
23
|
+
## Tool-Call Guardrails
|
|
24
|
+
|
|
25
|
+
- Follow the current tool schema exactly for parameters.
|
|
26
|
+
- Do not invent wrapper namespaces unless they are explicitly listed as tools.
|
|
27
|
+
- If no explicit parallel helper tool is listed, run calls sequentially.
|
|
28
|
+
- If a tool call fails validation, correct arguments to match schema and retry.
|
|
29
|
+
|
|
30
|
+
## Planning & Modes
|
|
31
|
+
|
|
32
|
+
- Never call \`update_plan\`, \`read_plan\`, or similarly named aliases.
|
|
33
|
+
- Use planning tools only if they are explicitly listed in the runtime manifest.
|
|
34
|
+
- \`request_user_input\` is Plan-mode only; never call it in Default mode.
|
|
35
|
+
|
|
36
|
+
## Path & Execution Discipline
|
|
37
|
+
|
|
38
|
+
- Follow per-tool path conventions from the active schema; do not assume absolute/relative behavior.
|
|
39
|
+
- Prefer specialized tools over shell when an equivalent listed tool exists.
|
|
40
|
+
- Use non-destructive checks before destructive commands.
|
|
41
|
+
|
|
42
|
+
## Verification Checklist
|
|
43
|
+
|
|
44
|
+
Before each tool call:
|
|
45
|
+
1. Is the tool name exactly listed in the runtime manifest?
|
|
46
|
+
2. Do arguments match the listed schema?
|
|
47
|
+
3. Am I avoiding unlisted aliases and wrapper namespaces?
|
|
48
|
+
4. Am I following mode/path constraints for this environment?
|
|
49
|
+
|
|
50
|
+
If any answer is NO, correct it before proceeding.
|
|
51
|
+
|
|
52
|
+
## OpenCode Working Style
|
|
53
|
+
|
|
54
|
+
**Communication:**
|
|
55
|
+
- Send brief preambles before tool calls.
|
|
56
|
+
- Provide concise progress updates during longer tasks.
|
|
57
|
+
|
|
58
|
+
**Execution:**
|
|
59
|
+
- Continue working until the user request is fully resolved.
|
|
60
|
+
- Do not return partial solutions unless blocked.
|
|
61
|
+
|
|
62
|
+
**Code Approach:**
|
|
63
|
+
- New projects: be creative and deliberate.
|
|
64
|
+
- Existing codebases: make precise, minimal changes aligned to request.
|
|
65
|
+
|
|
66
|
+
**Testing:**
|
|
67
|
+
- If tests exist, run focused tests first, then broader validation.
|
|
68
|
+
|
|
69
|
+
## What Remains from Codex
|
|
70
|
+
|
|
71
|
+
Sandbox policies, approvals, final formatting, git protocols, and file reference formats still follow Codex instructions.
|
|
72
|
+
|
|
73
|
+
## Approvals & Safety
|
|
74
|
+
|
|
75
|
+
- Treat destructive commands (for example \`rm\`, \`git reset --hard\`) as requiring explicit user request or approval.
|
|
76
|
+
- Never run \`git reset --hard\`, \`git checkout --\`, or force deletes unless explicitly requested.
|
|
77
77
|
- When uncertain, prefer non-destructive verification first.`;
|
|
78
78
|
const MAX_MANIFEST_TOOLS = 32;
|
|
79
79
|
const normalizeRuntimeToolNames = (toolNames) => {
|