@mtayfur/opencode-codex-fast 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/fast-status.d.ts +6 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.js +153 -0
- package/dist/state.d.ts +8 -0
- package/dist/tui.d.ts +6 -0
- package/dist/tui.js +170 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# OpenCode Codex Fast
|
|
2
|
+
|
|
3
|
+
`@mtayfur/opencode-codex-fast` adds a global Fast Mode toggle for ChatGPT Codex. When enabled, matching HTTP
|
|
4
|
+
requests include:
|
|
5
|
+
|
|
6
|
+
```json
|
|
7
|
+
{
|
|
8
|
+
"service_tier": "priority"
|
|
9
|
+
}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Other providers and endpoints are unaffected.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### OpenCode installer
|
|
17
|
+
|
|
18
|
+
Install both plugin targets with OpenCode:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
opencode plugin --global @mtayfur/opencode-codex-fast
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The package uses separate server and TUI entry points. The installer registers both targets.
|
|
25
|
+
|
|
26
|
+
### Manual configuration
|
|
27
|
+
|
|
28
|
+
Add the package to `~/.config/opencode/opencode.jsonc` (`opencode.json` is also supported):
|
|
29
|
+
|
|
30
|
+
```jsonc
|
|
31
|
+
{
|
|
32
|
+
"plugin": ["@mtayfur/opencode-codex-fast"]
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Add the same package to `~/.config/opencode/tui.json`:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"plugin": ["@mtayfur/opencode-codex-fast"]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Restart OpenCode after installation or configuration changes.
|
|
45
|
+
|
|
46
|
+
### Local checkout
|
|
47
|
+
|
|
48
|
+
For a local checkout, run `bun run --cwd packages/codex-fast setup`. Use `setup:uninstall` to remove both local
|
|
49
|
+
registrations.
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
Run `/fast` or select `codex.fast.toggle` from the command palette. The command updates the global state and shows a
|
|
54
|
+
toast; it does not create a session message or call a model.
|
|
55
|
+
|
|
56
|
+
- `⚡` — Fast Mode is enabled.
|
|
57
|
+
- `🐢` — Fast Mode is disabled.
|
|
58
|
+
|
|
59
|
+
The icon appears only in sessions using the `openai` provider. A model change is reflected after the first prompt sent
|
|
60
|
+
with that model.
|
|
61
|
+
|
|
62
|
+
## Behavior
|
|
63
|
+
|
|
64
|
+
Fast Mode applies to primary agents and sub-agents that use the ChatGPT Codex HTTP endpoint:
|
|
65
|
+
|
|
66
|
+
- Protocol: `https:`
|
|
67
|
+
- Hostname: `chatgpt.com`
|
|
68
|
+
- Pathname: `/backend-api/codex/responses`
|
|
69
|
+
|
|
70
|
+
The state is read before every matching request. Experimental WebSocket transports may bypass `globalThis.fetch` and
|
|
71
|
+
are not supported.
|
|
72
|
+
|
|
73
|
+
## State
|
|
74
|
+
|
|
75
|
+
The state file contains only the `enabled` boolean. Its location is:
|
|
76
|
+
|
|
77
|
+
- `$XDG_CONFIG_HOME/opencode/codex-fast.json`
|
|
78
|
+
- `%APPDATA%\opencode\codex-fast.json` on Windows
|
|
79
|
+
- `~/.config/opencode/codex-fast.json` otherwise
|
|
80
|
+
|
|
81
|
+
Missing or invalid state means disabled. Writes are atomic.
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
bun install --frozen-lockfile
|
|
87
|
+
bun run --filter @mtayfur/opencode-codex-fast typecheck
|
|
88
|
+
bun run --filter @mtayfur/opencode-codex-fast build
|
|
89
|
+
npm pack ./packages/codex-fast --dry-run
|
|
90
|
+
```
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
|
+
type ReadEnabled = () => Promise<boolean>;
|
|
3
|
+
export declare function installFetchInterceptor(readEnabled?: ReadEnabled): () => void;
|
|
4
|
+
declare const _default: {
|
|
5
|
+
id: string;
|
|
6
|
+
server: Plugin;
|
|
7
|
+
};
|
|
8
|
+
export default _default;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/state.ts
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
|
+
import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
import { basename, dirname, join } from "path";
|
|
7
|
+
var STATE_FILE_NAME = "codex-fast.json";
|
|
8
|
+
function resolveStatePath(options = {}) {
|
|
9
|
+
const env = options.env ?? process.env;
|
|
10
|
+
const home = options.home ?? homedir();
|
|
11
|
+
const platform = options.platform ?? process.platform;
|
|
12
|
+
const xdgConfigHome = nonEmpty(env.XDG_CONFIG_HOME);
|
|
13
|
+
const appData = nonEmpty(env.APPDATA);
|
|
14
|
+
const configRoot = xdgConfigHome ?? (platform === "win32" ? appData : undefined) ?? join(home, ".config");
|
|
15
|
+
return join(configRoot, "opencode", STATE_FILE_NAME);
|
|
16
|
+
}
|
|
17
|
+
async function readFastMode(filePath = resolveStatePath()) {
|
|
18
|
+
try {
|
|
19
|
+
const parsed = JSON.parse(await readFile(filePath, "utf8"));
|
|
20
|
+
return isRecord(parsed) && parsed.enabled === true;
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function writeFastMode(enabled, filePath = resolveStatePath()) {
|
|
26
|
+
const directory = dirname(filePath);
|
|
27
|
+
const temporaryPath = join(directory, `.${basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
|
|
28
|
+
await mkdir(directory, { recursive: true });
|
|
29
|
+
try {
|
|
30
|
+
await writeFile(temporaryPath, `${JSON.stringify({ enabled }, null, 2)}
|
|
31
|
+
`, {
|
|
32
|
+
encoding: "utf8",
|
|
33
|
+
flag: "wx",
|
|
34
|
+
mode: 384
|
|
35
|
+
});
|
|
36
|
+
await rename(temporaryPath, filePath);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
await rm(temporaryPath, { force: true }).catch(() => {
|
|
39
|
+
return;
|
|
40
|
+
});
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function nonEmpty(value) {
|
|
45
|
+
const trimmed = value?.trim();
|
|
46
|
+
return trimmed ? trimmed : undefined;
|
|
47
|
+
}
|
|
48
|
+
function isRecord(value) {
|
|
49
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/server.ts
|
|
53
|
+
var PLUGIN_ID = "mtayfur.codex-fast";
|
|
54
|
+
var FETCH_RUNTIME_SYMBOL = Symbol.for("@mtayfur/opencode-codex-fast.fetch-runtime.v1");
|
|
55
|
+
function installFetchInterceptor(readEnabled = readFastMode) {
|
|
56
|
+
const host = globalThis;
|
|
57
|
+
const current = host[FETCH_RUNTIME_SYMBOL];
|
|
58
|
+
const existing = isFetchRuntime(current) ? current : undefined;
|
|
59
|
+
const runtime = existing ?? createFetchRuntime(globalThis.fetch, readEnabled);
|
|
60
|
+
if (existing) {
|
|
61
|
+
const wasInactive = runtime.references === 0;
|
|
62
|
+
runtime.references += 1;
|
|
63
|
+
if (wasInactive && globalThis.fetch === runtime.original)
|
|
64
|
+
globalThis.fetch = runtime.wrapper;
|
|
65
|
+
} else {
|
|
66
|
+
host[FETCH_RUNTIME_SYMBOL] = runtime;
|
|
67
|
+
globalThis.fetch = runtime.wrapper;
|
|
68
|
+
}
|
|
69
|
+
let disposed = false;
|
|
70
|
+
return () => {
|
|
71
|
+
if (disposed)
|
|
72
|
+
return;
|
|
73
|
+
disposed = true;
|
|
74
|
+
runtime.references = Math.max(0, runtime.references - 1);
|
|
75
|
+
if (runtime.references !== 0 || globalThis.fetch !== runtime.wrapper)
|
|
76
|
+
return;
|
|
77
|
+
globalThis.fetch = runtime.original;
|
|
78
|
+
if (host[FETCH_RUNTIME_SYMBOL] === runtime)
|
|
79
|
+
delete host[FETCH_RUNTIME_SYMBOL];
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function createFetchRuntime(original, readEnabled) {
|
|
83
|
+
let runtime;
|
|
84
|
+
const wrapper = Object.assign(async (input, init) => {
|
|
85
|
+
if (runtime.references === 0 || !isCodexEndpoint(input)) {
|
|
86
|
+
return original.call(globalThis, input, init);
|
|
87
|
+
}
|
|
88
|
+
const enabled = await safelyReadEnabled(readEnabled);
|
|
89
|
+
if (!enabled || typeof init?.body !== "string") {
|
|
90
|
+
return original.call(globalThis, input, init);
|
|
91
|
+
}
|
|
92
|
+
const body = parseObject(init.body);
|
|
93
|
+
if (!body || body.service_tier === "priority") {
|
|
94
|
+
return original.call(globalThis, input, init);
|
|
95
|
+
}
|
|
96
|
+
return original.call(globalThis, input, {
|
|
97
|
+
...init,
|
|
98
|
+
body: JSON.stringify({ ...body, service_tier: "priority" })
|
|
99
|
+
});
|
|
100
|
+
}, { preconnect: original.preconnect });
|
|
101
|
+
runtime = { original, wrapper, references: 1 };
|
|
102
|
+
return runtime;
|
|
103
|
+
}
|
|
104
|
+
function isCodexEndpoint(input) {
|
|
105
|
+
try {
|
|
106
|
+
const url = new URL(requestUrl(input));
|
|
107
|
+
return url.protocol === "https:" && url.hostname === "chatgpt.com" && url.pathname === "/backend-api/codex/responses";
|
|
108
|
+
} catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function requestUrl(input) {
|
|
113
|
+
if (typeof input === "string")
|
|
114
|
+
return input;
|
|
115
|
+
if (input instanceof URL)
|
|
116
|
+
return input.href;
|
|
117
|
+
return input.url;
|
|
118
|
+
}
|
|
119
|
+
async function safelyReadEnabled(readEnabled) {
|
|
120
|
+
try {
|
|
121
|
+
return await readEnabled();
|
|
122
|
+
} catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function parseObject(body) {
|
|
127
|
+
try {
|
|
128
|
+
const parsed = JSON.parse(body);
|
|
129
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : undefined;
|
|
130
|
+
} catch {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function isFetchRuntime(value) {
|
|
135
|
+
if (typeof value !== "object" || value === null)
|
|
136
|
+
return false;
|
|
137
|
+
const candidate = value;
|
|
138
|
+
return typeof candidate.original === "function" && typeof candidate.wrapper === "function" && typeof candidate.references === "number";
|
|
139
|
+
}
|
|
140
|
+
var server = async () => {
|
|
141
|
+
const dispose = installFetchInterceptor();
|
|
142
|
+
return {
|
|
143
|
+
dispose: async () => dispose()
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
var server_default = {
|
|
147
|
+
id: PLUGIN_ID,
|
|
148
|
+
server
|
|
149
|
+
};
|
|
150
|
+
export {
|
|
151
|
+
installFetchInterceptor,
|
|
152
|
+
server_default as default
|
|
153
|
+
};
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type StatePathOptions = {
|
|
2
|
+
env?: Readonly<Record<string, string | undefined>>;
|
|
3
|
+
home?: string;
|
|
4
|
+
platform?: NodeJS.Platform;
|
|
5
|
+
};
|
|
6
|
+
export declare function resolveStatePath(options?: StatePathOptions): string;
|
|
7
|
+
export declare function readFastMode(filePath?: string): Promise<boolean>;
|
|
8
|
+
export declare function writeFastMode(enabled: boolean, filePath?: string): Promise<void>;
|
package/dist/tui.d.ts
ADDED
package/dist/tui.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/tui.ts
|
|
3
|
+
import { watch } from "fs";
|
|
4
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
5
|
+
import { basename as basename2, dirname as dirname2 } from "path";
|
|
6
|
+
import { createComponent, createSignal } from "solid-js";
|
|
7
|
+
|
|
8
|
+
// src/fast-status.tsx
|
|
9
|
+
import { effect as _$effect } from "@opentui/solid";
|
|
10
|
+
import { insertNode as _$insertNode } from "@opentui/solid";
|
|
11
|
+
import { insert as _$insert } from "@opentui/solid";
|
|
12
|
+
import { memo as _$memo } from "@opentui/solid";
|
|
13
|
+
import { setProp as _$setProp } from "@opentui/solid";
|
|
14
|
+
import { createElement as _$createElement } from "@opentui/solid";
|
|
15
|
+
function FastStatus(props) {
|
|
16
|
+
return (() => {
|
|
17
|
+
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("span");
|
|
18
|
+
_$insertNode(_el$, _el$2);
|
|
19
|
+
_$setProp(_el$, "paddingRight", 1);
|
|
20
|
+
_$insertNode(_el$2, _el$3);
|
|
21
|
+
_$insert(_el$3, () => props.enabled() ? "\u26A1" : "\uD83D\uDC22");
|
|
22
|
+
_$effect((_$p) => _$setProp(_el$, "visible", props.providerID() === "openai", _$p));
|
|
23
|
+
return _el$;
|
|
24
|
+
})();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/state.ts
|
|
28
|
+
import { randomUUID } from "crypto";
|
|
29
|
+
import { mkdir, readFile, rename, rm, writeFile } from "fs/promises";
|
|
30
|
+
import { homedir } from "os";
|
|
31
|
+
import { basename, dirname, join } from "path";
|
|
32
|
+
var STATE_FILE_NAME = "codex-fast.json";
|
|
33
|
+
function resolveStatePath(options = {}) {
|
|
34
|
+
const env = options.env ?? process.env;
|
|
35
|
+
const home = options.home ?? homedir();
|
|
36
|
+
const platform = options.platform ?? process.platform;
|
|
37
|
+
const xdgConfigHome = nonEmpty(env.XDG_CONFIG_HOME);
|
|
38
|
+
const appData = nonEmpty(env.APPDATA);
|
|
39
|
+
const configRoot = xdgConfigHome ?? (platform === "win32" ? appData : undefined) ?? join(home, ".config");
|
|
40
|
+
return join(configRoot, "opencode", STATE_FILE_NAME);
|
|
41
|
+
}
|
|
42
|
+
async function readFastMode(filePath = resolveStatePath()) {
|
|
43
|
+
try {
|
|
44
|
+
const parsed = JSON.parse(await readFile(filePath, "utf8"));
|
|
45
|
+
return isRecord(parsed) && parsed.enabled === true;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function writeFastMode(enabled, filePath = resolveStatePath()) {
|
|
51
|
+
const directory = dirname(filePath);
|
|
52
|
+
const temporaryPath = join(directory, `.${basename(filePath)}.${process.pid}.${randomUUID()}.tmp`);
|
|
53
|
+
await mkdir(directory, { recursive: true });
|
|
54
|
+
try {
|
|
55
|
+
await writeFile(temporaryPath, `${JSON.stringify({ enabled }, null, 2)}
|
|
56
|
+
`, {
|
|
57
|
+
encoding: "utf8",
|
|
58
|
+
flag: "wx",
|
|
59
|
+
mode: 384
|
|
60
|
+
});
|
|
61
|
+
await rename(temporaryPath, filePath);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
await rm(temporaryPath, { force: true }).catch(() => {
|
|
64
|
+
return;
|
|
65
|
+
});
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function nonEmpty(value) {
|
|
70
|
+
const trimmed = value?.trim();
|
|
71
|
+
return trimmed ? trimmed : undefined;
|
|
72
|
+
}
|
|
73
|
+
function isRecord(value) {
|
|
74
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/tui.ts
|
|
78
|
+
var PLUGIN_ID = "mtayfur.codex-fast";
|
|
79
|
+
var TOAST_TITLE = "Codex Fast";
|
|
80
|
+
function registerFastModeCommands(api, setEnabled) {
|
|
81
|
+
let toggles = Promise.resolve();
|
|
82
|
+
const disposeCommands = api.keymap.registerLayer({
|
|
83
|
+
commands: [
|
|
84
|
+
{
|
|
85
|
+
namespace: "palette",
|
|
86
|
+
name: "codex.fast.toggle",
|
|
87
|
+
title: "Toggle Codex Fast Mode",
|
|
88
|
+
desc: "Toggle priority service tier for ChatGPT Codex requests",
|
|
89
|
+
category: TOAST_TITLE,
|
|
90
|
+
slashName: "fast",
|
|
91
|
+
run: () => {
|
|
92
|
+
toggles = toggles.then(() => toggleFastMode(api, setEnabled));
|
|
93
|
+
return toggles;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
],
|
|
97
|
+
bindings: []
|
|
98
|
+
});
|
|
99
|
+
api.lifecycle.onDispose(disposeCommands);
|
|
100
|
+
}
|
|
101
|
+
async function toggleFastMode(api, setEnabled) {
|
|
102
|
+
await setFastMode(api, setEnabled, !await readFastMode());
|
|
103
|
+
}
|
|
104
|
+
async function setFastMode(api, setEnabled, enabled) {
|
|
105
|
+
try {
|
|
106
|
+
await writeFastMode(enabled);
|
|
107
|
+
setEnabled(enabled);
|
|
108
|
+
showStateToast(api, enabled);
|
|
109
|
+
} catch {
|
|
110
|
+
api.ui.toast({
|
|
111
|
+
title: TOAST_TITLE,
|
|
112
|
+
message: "Fast mode state could not be updated.",
|
|
113
|
+
variant: "error"
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function showStateToast(api, enabled) {
|
|
118
|
+
api.ui.toast({
|
|
119
|
+
title: TOAST_TITLE,
|
|
120
|
+
message: `Fast mode is now ${enabled ? "ON" : "OFF"}.`,
|
|
121
|
+
variant: "success"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async function watchFastMode(setEnabled) {
|
|
125
|
+
const stateFile = resolveStatePath();
|
|
126
|
+
try {
|
|
127
|
+
await mkdir2(dirname2(stateFile), { recursive: true });
|
|
128
|
+
const watcher = watch(dirname2(stateFile), (_, filename) => {
|
|
129
|
+
if (filename && basename2(String(filename)) !== basename2(stateFile))
|
|
130
|
+
return;
|
|
131
|
+
readFastMode(stateFile).then(setEnabled);
|
|
132
|
+
});
|
|
133
|
+
watcher.on("error", () => watcher.close());
|
|
134
|
+
return () => watcher.close();
|
|
135
|
+
} catch {
|
|
136
|
+
return () => {
|
|
137
|
+
return;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function sessionProvider(api, sessionID) {
|
|
142
|
+
const session = api.state.session.get(sessionID);
|
|
143
|
+
if (session?.model?.providerID)
|
|
144
|
+
return session.model.providerID;
|
|
145
|
+
const message = api.state.session.messages(sessionID).findLast((item) => item.role === "user");
|
|
146
|
+
return message?.model.providerID;
|
|
147
|
+
}
|
|
148
|
+
var tui = async (api) => {
|
|
149
|
+
const [enabled, setEnabled] = createSignal(await readFastMode());
|
|
150
|
+
registerFastModeCommands(api, setEnabled);
|
|
151
|
+
api.lifecycle.onDispose(await watchFastMode(setEnabled));
|
|
152
|
+
api.slots.register({
|
|
153
|
+
order: 55,
|
|
154
|
+
slots: {
|
|
155
|
+
session_prompt_right(_, props) {
|
|
156
|
+
return createComponent(FastStatus, {
|
|
157
|
+
enabled,
|
|
158
|
+
providerID: () => sessionProvider(api, props.session_id)
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
};
|
|
164
|
+
var tui_default = {
|
|
165
|
+
id: PLUGIN_ID,
|
|
166
|
+
tui
|
|
167
|
+
};
|
|
168
|
+
export {
|
|
169
|
+
tui_default as default
|
|
170
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "@mtayfur/opencode-codex-fast",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"description": "Toggle ChatGPT Codex priority service tier from the OpenCode TUI.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/mtayfur/opencode-plugins.git",
|
|
10
|
+
"directory": "packages/codex-fast"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/mtayfur/opencode-plugins/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/mtayfur/opencode-plugins/tree/main/packages/codex-fast#readme",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"sideEffects": false,
|
|
21
|
+
"exports": {
|
|
22
|
+
"./server": {
|
|
23
|
+
"types": "./dist/server.d.ts",
|
|
24
|
+
"import": "./dist/server.js"
|
|
25
|
+
},
|
|
26
|
+
"./tui": {
|
|
27
|
+
"types": "./dist/tui.d.ts",
|
|
28
|
+
"import": "./dist/tui.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "bun run scripts/build.ts",
|
|
36
|
+
"setup": "bash ./install.sh",
|
|
37
|
+
"setup:uninstall": "bash ./install.sh --uninstall",
|
|
38
|
+
"typecheck": "bun x tsc -p tsconfig.json",
|
|
39
|
+
"prepack": "bun run build"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"solid-js": "^1.9.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"@opencode-ai/plugin": ">=1.18.21 <2",
|
|
46
|
+
"@opentui/core": ">=0.5.1",
|
|
47
|
+
"@opentui/solid": ">=0.5.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@opencode-ai/plugin": "1.18.21",
|
|
51
|
+
"@opentui/core": "0.5.1",
|
|
52
|
+
"@opentui/keymap": "0.5.1",
|
|
53
|
+
"@opentui/solid": "0.5.1",
|
|
54
|
+
"@types/bun": "1.3.14",
|
|
55
|
+
"jsonc-parser": "^3.3.1",
|
|
56
|
+
"typescript": "^5.9.3"
|
|
57
|
+
},
|
|
58
|
+
"engines": {
|
|
59
|
+
"bun": ">=1.3.14",
|
|
60
|
+
"opencode": "^1.18.21"
|
|
61
|
+
},
|
|
62
|
+
"keywords": [
|
|
63
|
+
"opencode",
|
|
64
|
+
"plugin",
|
|
65
|
+
"codex",
|
|
66
|
+
"fast-mode",
|
|
67
|
+
"priority"
|
|
68
|
+
],
|
|
69
|
+
"packageManager": "bun@1.3.14"
|
|
70
|
+
}
|