@cjhyy/code-shell-capability-coding 0.9.5 → 0.9.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/external-runtimes/codex/app-server-client.d.ts +1 -1
- package/dist/external-runtimes/codex/app-server-client.js +19 -5
- package/dist/external-runtimes/codex/model-discovery.d.ts +14 -0
- package/dist/external-runtimes/codex/model-discovery.js +76 -0
- package/dist/external-runtimes/index.d.ts +2 -0
- package/dist/external-runtimes/index.js +1 -0
- package/dist/quota/index.d.ts +20 -4
- package/dist/quota/index.js +72 -14
- package/dist/quota/types.d.ts +19 -3
- package/dist/tools/check-quota.js +4 -2
- package/package.json +2 -2
|
@@ -61,6 +61,6 @@ export declare class CodexAppServerClient {
|
|
|
61
61
|
private write;
|
|
62
62
|
private failAll;
|
|
63
63
|
get isClosed(): boolean;
|
|
64
|
-
/**
|
|
64
|
+
/** Stop via stdin EOF, then SIGTERM and SIGKILL if the server does not exit. */
|
|
65
65
|
close(): Promise<void>;
|
|
66
66
|
}
|
|
@@ -219,12 +219,14 @@ export class CodexAppServerClient {
|
|
|
219
219
|
get isClosed() {
|
|
220
220
|
return this.closed;
|
|
221
221
|
}
|
|
222
|
-
/**
|
|
222
|
+
/** Stop via stdin EOF, then SIGTERM and SIGKILL if the server does not exit. */
|
|
223
223
|
async close() {
|
|
224
224
|
const child = this.child;
|
|
225
225
|
this.failAll("app-server client closed");
|
|
226
226
|
this.lines?.close();
|
|
227
|
-
|
|
227
|
+
// Failed spawns have no pid and never emit `exit`. A process already killed
|
|
228
|
+
// by a signal likewise has no numeric exitCode and will not emit it again.
|
|
229
|
+
if (!child || !child.pid || child.exitCode !== null || child.signalCode !== null)
|
|
228
230
|
return;
|
|
229
231
|
try {
|
|
230
232
|
child.stdin.end();
|
|
@@ -237,8 +239,20 @@ export class CodexAppServerClient {
|
|
|
237
239
|
return resolve();
|
|
238
240
|
child.once("exit", () => resolve());
|
|
239
241
|
});
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
let killTimer;
|
|
243
|
+
const terminateTimer = setTimeout(() => {
|
|
244
|
+
child.kill("SIGTERM");
|
|
245
|
+
// Cleanup must finish even when an unresponsive server ignores SIGTERM.
|
|
246
|
+
// Keep awaiting its actual exit so callers never leave an orphan behind.
|
|
247
|
+
killTimer = setTimeout(() => child.kill("SIGKILL"), 500);
|
|
248
|
+
}, 2_000);
|
|
249
|
+
try {
|
|
250
|
+
await exited;
|
|
251
|
+
}
|
|
252
|
+
finally {
|
|
253
|
+
clearTimeout(terminateTimer);
|
|
254
|
+
if (killTimer)
|
|
255
|
+
clearTimeout(killTimer);
|
|
256
|
+
}
|
|
243
257
|
}
|
|
244
258
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type AppServerClientOptions } from "./app-server-client.js";
|
|
2
|
+
export interface CodexDiscoveredModel {
|
|
3
|
+
model: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
isDefault: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Read the installed Codex CLI's available models without starting a thread or
|
|
9
|
+
* turn. The deadline covers initialization and every page together. Callers own
|
|
10
|
+
* caching and fallback policy; a valid empty catalog is distinct from failure.
|
|
11
|
+
*/
|
|
12
|
+
export declare function discoverCodexModels(options?: AppServerClientOptions & {
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
}): Promise<CodexDiscoveredModel[]>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { CodexAppServerClient } from "./app-server-client.js";
|
|
2
|
+
import { buildRuntimeSpawnEnv } from "../shared/spawn-env.js";
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 8_000;
|
|
4
|
+
const MAX_PAGES = 100;
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function nonemptyString(value) {
|
|
9
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Read the installed Codex CLI's available models without starting a thread or
|
|
13
|
+
* turn. The deadline covers initialization and every page together. Callers own
|
|
14
|
+
* caching and fallback policy; a valid empty catalog is distinct from failure.
|
|
15
|
+
*/
|
|
16
|
+
export async function discoverCodexModels(options = {}) {
|
|
17
|
+
const { timeoutMs = DEFAULT_TIMEOUT_MS, ...clientOptions } = options;
|
|
18
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
19
|
+
throw new Error("Codex model discovery requires a positive timeout");
|
|
20
|
+
}
|
|
21
|
+
const deadline = performance.now() + timeoutMs;
|
|
22
|
+
const remainingMs = () => {
|
|
23
|
+
const remaining = deadline - performance.now();
|
|
24
|
+
if (remaining <= 0)
|
|
25
|
+
throw new Error("Codex model discovery timed out");
|
|
26
|
+
return Math.ceil(remaining);
|
|
27
|
+
};
|
|
28
|
+
const client = new CodexAppServerClient({
|
|
29
|
+
...clientOptions,
|
|
30
|
+
env: buildRuntimeSpawnEnv({ base: options.env }),
|
|
31
|
+
});
|
|
32
|
+
client.onNotification(() => { });
|
|
33
|
+
client.onServerRequest(() => undefined);
|
|
34
|
+
try {
|
|
35
|
+
client.start();
|
|
36
|
+
await client.request("initialize", { clientInfo: { name: "codeshell", title: "CodeShell", version: "1" } }, remainingMs());
|
|
37
|
+
client.notify("initialized");
|
|
38
|
+
const models = new Map();
|
|
39
|
+
const cursors = new Set();
|
|
40
|
+
let cursor;
|
|
41
|
+
for (let page = 0; page < MAX_PAGES; page++) {
|
|
42
|
+
const result = await client.request("model/list", { includeHidden: false, limit: 100, ...(cursor ? { cursor } : {}) }, remainingMs());
|
|
43
|
+
if (!isRecord(result) || !Array.isArray(result.data)) {
|
|
44
|
+
throw new Error("Invalid Codex model/list response");
|
|
45
|
+
}
|
|
46
|
+
for (const entry of result.data) {
|
|
47
|
+
if (!isRecord(entry) ||
|
|
48
|
+
!nonemptyString(entry.model) ||
|
|
49
|
+
!nonemptyString(entry.displayName) ||
|
|
50
|
+
(entry.isDefault !== undefined && typeof entry.isDefault !== "boolean") ||
|
|
51
|
+
(entry.hidden !== undefined && typeof entry.hidden !== "boolean")) {
|
|
52
|
+
throw new Error("Invalid Codex model/list entry");
|
|
53
|
+
}
|
|
54
|
+
if (entry.hidden === true || models.has(entry.model))
|
|
55
|
+
continue;
|
|
56
|
+
models.set(entry.model, {
|
|
57
|
+
model: entry.model,
|
|
58
|
+
displayName: entry.displayName,
|
|
59
|
+
isDefault: entry.isDefault === true,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (result.nextCursor === null || result.nextCursor === undefined) {
|
|
63
|
+
return [...models.values()];
|
|
64
|
+
}
|
|
65
|
+
if (!nonemptyString(result.nextCursor) || cursors.has(result.nextCursor)) {
|
|
66
|
+
throw new Error("Invalid Codex model/list pagination cursor");
|
|
67
|
+
}
|
|
68
|
+
cursor = result.nextCursor;
|
|
69
|
+
cursors.add(cursor);
|
|
70
|
+
}
|
|
71
|
+
throw new Error("Codex model/list exceeded the pagination limit");
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
await client.close();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -25,6 +25,8 @@ export type { ExternalRuntimeAttachment, ExternalRuntimeTurnInput } from "./turn
|
|
|
25
25
|
export { CodexEventTranslator } from "./codex/event-translator.js";
|
|
26
26
|
export { CodexAppServerClient } from "./codex/app-server-client.js";
|
|
27
27
|
export type { AppServerClientOptions } from "./codex/app-server-client.js";
|
|
28
|
+
export { discoverCodexModels } from "./codex/model-discovery.js";
|
|
29
|
+
export type { CodexDiscoveredModel } from "./codex/model-discovery.js";
|
|
28
30
|
export { CodexRuntime } from "./codex/runtime.js";
|
|
29
31
|
export type { CodexRuntimeOptions, CodexRuntimeHooks, CodexTurnHandle, NativeApprovalDecision, } from "./codex/runtime.js";
|
|
30
32
|
export { buildClaudeMcpConfig, claudeAllowedToolNames, claudeBridgeArgs, CLAUDE_MCP_SERVER_NAME, } from "./claude-code/mcp-config.js";
|
|
@@ -20,6 +20,7 @@ export { buildRuntimeSpawnEnv } from "./shared/spawn-env.js";
|
|
|
20
20
|
export { textWithAttachmentReferences } from "./turn-input.js";
|
|
21
21
|
export { CodexEventTranslator } from "./codex/event-translator.js";
|
|
22
22
|
export { CodexAppServerClient } from "./codex/app-server-client.js";
|
|
23
|
+
export { discoverCodexModels } from "./codex/model-discovery.js";
|
|
23
24
|
export { CodexRuntime } from "./codex/runtime.js";
|
|
24
25
|
export { buildClaudeMcpConfig, claudeAllowedToolNames, claudeBridgeArgs, CLAUDE_MCP_SERVER_NAME, } from "./claude-code/mcp-config.js";
|
|
25
26
|
export { writeClaudeMcpConfigFile } from "./claude-code/mcp-config.js";
|
package/dist/quota/index.d.ts
CHANGED
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
* rate_limit.{primary_window,secondary_window}.{used_percent,reset_at}.
|
|
7
7
|
* Zero cost (no message sent).
|
|
8
8
|
* - Claude: POST /v1/messages (max_tokens:1) → response headers
|
|
9
|
-
* anthropic-ratelimit-unified
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* anthropic-ratelimit-unified-<window>-{utilization,reset}, where
|
|
10
|
+
* <window> is discovered from the headers (5h / 7d / overage / …)
|
|
11
|
+
* rather than assumed — see parseClaudeWindows (re-verified
|
|
12
|
+
* 2026-09-06). Costs ~1 output token (Claude exposes quota only via
|
|
13
|
+
* response headers — there is no standalone usage endpoint).
|
|
12
14
|
*
|
|
13
15
|
* The `fetch` and credentials are injected so this is unit-testable offline and
|
|
14
16
|
* so the host owns secret resolution (see types.ts boundary note).
|
|
15
17
|
*/
|
|
16
|
-
import type { ProviderQuota, QuotaCredentials, QuotaResult } from "./types.js";
|
|
18
|
+
import type { ProviderQuota, QuotaCredentials, QuotaResult, QuotaWindow } from "./types.js";
|
|
17
19
|
type FetchLike = typeof fetch;
|
|
18
20
|
export interface CheckQuotaOptions {
|
|
19
21
|
creds: QuotaCredentials;
|
|
@@ -29,6 +31,20 @@ export interface CheckQuotaOptions {
|
|
|
29
31
|
export declare function queryCodexQuota(creds: QuotaCredentials, fetchImpl: FetchLike, signal: AbortSignal): Promise<ProviderQuota>;
|
|
30
32
|
/** Claude: POST a 1-token probe and read the unified rate-limit headers. */
|
|
31
33
|
export declare function queryClaudeQuota(creds: QuotaCredentials, fetchImpl: FetchLike, signal: AbortSignal): Promise<ProviderQuota>;
|
|
34
|
+
/**
|
|
35
|
+
* Discover every rate-limit window from the unified headers.
|
|
36
|
+
*
|
|
37
|
+
* Windows are found by PREFIX, not from a hardcoded list, because which ones
|
|
38
|
+
* the API sends depends on the account. A normal subscription reports 5h + 7d;
|
|
39
|
+
* an account on overage reports `overage` and omits 5h/7d entirely. Matching a
|
|
40
|
+
* fixed list is what silently broke this lookup before (see types.ts).
|
|
41
|
+
*
|
|
42
|
+
* Each window contributes `<prefix><name>-utilization` (0–1) and an optional
|
|
43
|
+
* `<prefix><name>-reset` (epoch seconds). Bare `<prefix>reset` / `<prefix>status`
|
|
44
|
+
* are envelope fields, not windows, so anything without a `-utilization` suffix
|
|
45
|
+
* is skipped.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseClaudeWindows(h: Headers): QuotaWindow[];
|
|
32
48
|
/** Query both providers (or the subset requested), concurrently. */
|
|
33
49
|
export declare function checkQuota(opts: CheckQuotaOptions): Promise<QuotaResult>;
|
|
34
50
|
/** Render a QuotaResult as a compact human/agent-readable summary. */
|
package/dist/quota/index.js
CHANGED
|
@@ -101,21 +101,68 @@ export async function queryClaudeQuota(creds, fetchImpl, signal) {
|
|
|
101
101
|
error: `HTTP ${resp.status}${resp.status === 401 ? " (token 可能已过期)" : ""}`,
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
-
const
|
|
104
|
+
const windows = parseClaudeWindows(resp.headers);
|
|
105
|
+
if (windows.length === 0)
|
|
106
|
+
return { provider: "claude", error: "响应头无 rate-limit 字段" };
|
|
107
|
+
return { provider: "claude", windows };
|
|
108
|
+
}
|
|
109
|
+
const UNIFIED_PREFIX = "anthropic-ratelimit-unified-";
|
|
110
|
+
/**
|
|
111
|
+
* Map `representative-claim` values onto the window names used in the headers.
|
|
112
|
+
* The claim spells a window out ("five_hour"); the window headers abbreviate it
|
|
113
|
+
* ("5h"). An unlisted claim value falls through to an exact `kind` match, which
|
|
114
|
+
* is how "overage" already lines up.
|
|
115
|
+
*/
|
|
116
|
+
const CLAIM_TO_KIND = {
|
|
117
|
+
five_hour: "5h",
|
|
118
|
+
seven_day: "7d",
|
|
119
|
+
seven_day_sonnet: "7d_sonnet",
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Discover every rate-limit window from the unified headers.
|
|
123
|
+
*
|
|
124
|
+
* Windows are found by PREFIX, not from a hardcoded list, because which ones
|
|
125
|
+
* the API sends depends on the account. A normal subscription reports 5h + 7d;
|
|
126
|
+
* an account on overage reports `overage` and omits 5h/7d entirely. Matching a
|
|
127
|
+
* fixed list is what silently broke this lookup before (see types.ts).
|
|
128
|
+
*
|
|
129
|
+
* Each window contributes `<prefix><name>-utilization` (0–1) and an optional
|
|
130
|
+
* `<prefix><name>-reset` (epoch seconds). Bare `<prefix>reset` / `<prefix>status`
|
|
131
|
+
* are envelope fields, not windows, so anything without a `-utilization` suffix
|
|
132
|
+
* is skipped.
|
|
133
|
+
*/
|
|
134
|
+
export function parseClaudeWindows(h) {
|
|
105
135
|
const windows = [];
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
136
|
+
for (const [rawKey, rawVal] of h.entries()) {
|
|
137
|
+
const key = rawKey.toLowerCase();
|
|
138
|
+
if (!key.startsWith(UNIFIED_PREFIX) || !key.endsWith("-utilization"))
|
|
139
|
+
continue;
|
|
140
|
+
const kind = key.slice(UNIFIED_PREFIX.length, -"-utilization".length);
|
|
141
|
+
if (!kind)
|
|
142
|
+
continue; // guard a bare `<prefix>utilization`
|
|
143
|
+
const util = num(rawVal); // 0–1
|
|
112
144
|
if (util == null)
|
|
113
145
|
continue;
|
|
114
|
-
windows.push({
|
|
146
|
+
windows.push({
|
|
147
|
+
// Round to 4dp: `0.07 * 100` is 7.000000000000001 in binary float, which
|
|
148
|
+
// leaks into equality checks and any raw (unformatted) display.
|
|
149
|
+
kind,
|
|
150
|
+
usedPercent: Math.round(util * 100 * 1e4) / 1e4,
|
|
151
|
+
resetsAt: num(h.get(`${UNIFIED_PREFIX}${kind}-reset`)),
|
|
152
|
+
});
|
|
115
153
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
154
|
+
// Stable order so output does not shuffle between identical probes.
|
|
155
|
+
windows.sort((a, b) => a.kind.localeCompare(b.kind));
|
|
156
|
+
// Flag the binding window. A request is throttled on this one, so it is what
|
|
157
|
+
// an orchestrator should plan against when windows disagree.
|
|
158
|
+
const claim = h.get(`${UNIFIED_PREFIX}representative-claim`)?.trim().toLowerCase();
|
|
159
|
+
if (claim) {
|
|
160
|
+
const want = CLAIM_TO_KIND[claim] ?? claim;
|
|
161
|
+
const hit = windows.find((w) => w.kind === want);
|
|
162
|
+
if (hit)
|
|
163
|
+
hit.representative = true;
|
|
164
|
+
}
|
|
165
|
+
return windows;
|
|
119
166
|
}
|
|
120
167
|
/** Query both providers (or the subset requested), concurrently. */
|
|
121
168
|
export async function checkQuota(opts) {
|
|
@@ -145,17 +192,28 @@ export function formatQuota(result, nowSec) {
|
|
|
145
192
|
const plan = pq.planType ? ` [${pq.planType}]` : "";
|
|
146
193
|
const parts = pq.windows.map((w) => {
|
|
147
194
|
const reset = w.resetsAt != null ? ` (重置 ${formatReset(w.resetsAt - nowSec)})` : "";
|
|
148
|
-
|
|
195
|
+
// Star the binding window so a reader/agent knows which one throttles.
|
|
196
|
+
const star = w.representative ? "*" : "";
|
|
197
|
+
return `${w.kind}${star} 用了 ${w.usedPercent.toFixed(0)}%${reset}`;
|
|
149
198
|
});
|
|
150
199
|
lines.push(`${name}${plan}: ${parts.join(",")}`);
|
|
151
200
|
}
|
|
152
201
|
return lines.length ? lines.join("\n") : "(无可用额度信息)";
|
|
153
202
|
}
|
|
154
|
-
/**
|
|
203
|
+
/**
|
|
204
|
+
* "3d2h" / "2h13m" / "45m" / "已重置" from a seconds delta.
|
|
205
|
+
*
|
|
206
|
+
* The day unit matters: this only ever had to render 5h/7d windows, but an
|
|
207
|
+
* overage window can reset weeks out, and "606h0m 后" is not a readable way to
|
|
208
|
+
* say 25 days.
|
|
209
|
+
*/
|
|
155
210
|
function formatReset(deltaSec) {
|
|
156
211
|
if (deltaSec <= 0)
|
|
157
212
|
return "已重置";
|
|
158
|
-
const
|
|
213
|
+
const d = Math.floor(deltaSec / 86400);
|
|
214
|
+
const h = Math.floor((deltaSec % 86400) / 3600);
|
|
159
215
|
const m = Math.floor((deltaSec % 3600) / 60);
|
|
216
|
+
if (d > 0)
|
|
217
|
+
return `${d}d${h}h 后`;
|
|
160
218
|
return h > 0 ? `${h}h${m}m 后` : `${m}m 后`;
|
|
161
219
|
}
|
package/dist/quota/types.d.ts
CHANGED
|
@@ -10,14 +10,30 @@
|
|
|
10
10
|
* it from the rest of core. Nothing outside this module should know about
|
|
11
11
|
* Keychain / wham endpoints / `anthropic-ratelimit-*` header names.
|
|
12
12
|
*/
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* A single rolling limit window.
|
|
15
|
+
*
|
|
16
|
+
* `kind` is NOT a closed set. Claude reports whichever windows apply to the
|
|
17
|
+
* account: usually "5h" and "7d", but an account running on overage reports an
|
|
18
|
+
* "overage" window INSTEAD of those (verified 2026-09-06 against a team /
|
|
19
|
+
* default_claude_max_5x account). New window names appear without notice, so
|
|
20
|
+
* the parser discovers them from the header prefix rather than matching a
|
|
21
|
+
* hardcoded list. Renderers must treat `kind` as an opaque label.
|
|
22
|
+
*/
|
|
14
23
|
export interface QuotaWindow {
|
|
15
|
-
/** Which window this is. */
|
|
16
|
-
kind:
|
|
24
|
+
/** Which window this is: "5h" | "7d" | "overage" | any future name. */
|
|
25
|
+
kind: string;
|
|
17
26
|
/** Percent of the window's limit already used, 0–100. */
|
|
18
27
|
usedPercent: number;
|
|
19
28
|
/** Unix epoch seconds when this window resets, or null if unknown. */
|
|
20
29
|
resetsAt: number | null;
|
|
30
|
+
/**
|
|
31
|
+
* True for the window the API named as the binding constraint via
|
|
32
|
+
* `anthropic-ratelimit-unified-representative-claim`. Claude only; a request
|
|
33
|
+
* is throttled on THIS window, so it is the one to act on when several
|
|
34
|
+
* windows disagree.
|
|
35
|
+
*/
|
|
36
|
+
representative?: boolean;
|
|
21
37
|
}
|
|
22
38
|
/** Quota for one provider (claude | codex). */
|
|
23
39
|
export interface ProviderQuota {
|
|
@@ -3,9 +3,11 @@ import { resolveQuotaCredentials } from "../quota/credentials.js";
|
|
|
3
3
|
export const checkQuotaToolDef = {
|
|
4
4
|
name: "CheckQuota",
|
|
5
5
|
description: "Check remaining usage/rate-limit quota for the external coding-agent CLIs (Claude Code and/or " +
|
|
6
|
-
"Codex) — the same
|
|
6
|
+
"Codex) — the same subscription windows their status lines show. Use before or during " +
|
|
7
7
|
"orchestration (DriveAgent) to plan how much work to hand off, whether to wait for a reset, or " +
|
|
8
|
-
"which provider to use. Returns each
|
|
8
|
+
"which provider to use. Returns each window's used-% and reset time. Codex reports 5h/7d; " +
|
|
9
|
+
"Claude reports whichever windows apply to the account (5h/7d normally, 'overage' when the " +
|
|
10
|
+
"account is running on overage), and marks the currently binding window with '*'. " +
|
|
9
11
|
"COST: 'codex' is free (reads a usage endpoint). 'claude' costs ~1 token (Anthropic exposes " +
|
|
10
12
|
"quota only via a response header, so this sends a 1-token probe). Pass `provider` to query " +
|
|
11
13
|
"just one and avoid the other's cost/latency.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cjhyy/code-shell-capability-coding",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.7",
|
|
4
4
|
"description": "Coding capability pack for the generic code-shell agent core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\""
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@cjhyy/code-shell-core": "0.9.
|
|
42
|
+
"@cjhyy/code-shell-core": "0.9.7"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=20.10"
|