mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
* fix: 修复 Bun 的 polyfill 问题 * fix: 类型修复完成 * feat: 统一所有包的类型文件 * fix: 修复构建问题
This commit is contained in:
@@ -55,6 +55,8 @@ bun run health
|
||||
# Check unused exports
|
||||
bun run check:unused
|
||||
|
||||
bun run typecheck
|
||||
|
||||
# Remote Control Server
|
||||
bun run rcs
|
||||
|
||||
|
||||
62
build.ts
62
build.ts
@@ -88,8 +88,27 @@ for (const file of files) {
|
||||
}
|
||||
}
|
||||
|
||||
// Also patch unguarded globalThis.Bun destructuring from third-party deps
|
||||
// (e.g. @anthropic-ai/sandbox-runtime) so Node.js doesn't crash at import time.
|
||||
let bunPatched = 0
|
||||
const BUN_DESTRUCTURE = /var \{([^}]+)\} = globalThis\.Bun;?/g
|
||||
const BUN_DESTRUCTURE_SAFE = 'var {$1} = typeof globalThis.Bun !== "undefined" ? globalThis.Bun : {};'
|
||||
for (const file of files) {
|
||||
if (!file.endsWith('.js')) continue
|
||||
const filePath = join(outdir, file)
|
||||
const content = await readFile(filePath, 'utf-8')
|
||||
if (BUN_DESTRUCTURE.test(content)) {
|
||||
await writeFile(
|
||||
filePath,
|
||||
content.replace(BUN_DESTRUCTURE, BUN_DESTRUCTURE_SAFE),
|
||||
)
|
||||
bunPatched++
|
||||
}
|
||||
}
|
||||
BUN_DESTRUCTURE.lastIndex = 0
|
||||
|
||||
console.log(
|
||||
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for Node.js compat)`,
|
||||
`Bundled ${result.outputs.length} files to ${outdir}/ (patched ${patched} for import.meta.require, ${bunPatched} for Bun destructure)`,
|
||||
)
|
||||
|
||||
// Step 4: Copy native .node addon files (audio-capture)
|
||||
@@ -119,46 +138,7 @@ const cliNode = join(outdir, 'cli-node.js')
|
||||
|
||||
await writeFile(cliBun, '#!/usr/bin/env bun\nimport "./cli.js"\n')
|
||||
|
||||
// Node.js entry needs a Bun API polyfill because Bun.build({ target: 'bun' })
|
||||
// emits globalThis.Bun references (e.g. Bun.$ shell tag in computer-use-input,
|
||||
// Bun.which in chunk-ys6smqg9) that crash at import time under plain Node.js.
|
||||
const NODE_BUN_POLYFILL = `#!/usr/bin/env node
|
||||
// Bun API polyfill for Node.js runtime
|
||||
if (typeof globalThis.Bun === "undefined") {
|
||||
const { execFileSync } = await import("child_process");
|
||||
const { resolve, delimiter } = await import("path");
|
||||
const { accessSync, constants: { X_OK } } = await import("fs");
|
||||
function which(bin) {
|
||||
const isWin = process.platform === "win32";
|
||||
const pathExt = isWin ? (process.env.PATHEXT || ".EXE").split(";") : [""];
|
||||
for (const dir of (process.env.PATH || "").split(delimiter)) {
|
||||
for (const ext of pathExt) {
|
||||
const candidate = resolve(dir, bin + ext);
|
||||
try { accessSync(candidate, X_OK); return candidate; } catch {}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Bun.$ is the shell template tag (e.g. $\`osascript ...\`). Only used by
|
||||
// computer-use-input/darwin — stub it so the top-level destructuring
|
||||
// \`var { $ } = globalThis.Bun\` doesn't crash.
|
||||
function $(parts, ...args) {
|
||||
throw new Error("Bun.$ shell API is not available in Node.js. Use Bun runtime for this feature.");
|
||||
}
|
||||
function hash(data, seed) {
|
||||
let h = ((seed || 0) ^ 0x811c9dc5) >>> 0;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
h ^= data.charCodeAt(i);
|
||||
h = Math.imul(h, 0x01000193) >>> 0;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
globalThis.Bun = { which, $, hash };
|
||||
}
|
||||
import "./cli.js"
|
||||
`
|
||||
await writeFile(cliNode, NODE_BUN_POLYFILL)
|
||||
// NOTE: when new Bun-specific globals appear in bundled output, add them here.
|
||||
await writeFile(cliNode, '#!/usr/bin/env node\nimport "./cli.js"\n')
|
||||
|
||||
// Make both executable
|
||||
const { chmodSync } = await import('fs')
|
||||
|
||||
3
bun.lock
3
bun.lock
@@ -58,10 +58,11 @@
|
||||
"@sentry/node": "^10.47.0",
|
||||
"@smithy/core": "^3.23.13",
|
||||
"@smithy/node-http-handler": "^4.5.1",
|
||||
"@types/bun": "^1.3.11",
|
||||
"@types/bun": "^1.3.12",
|
||||
"@types/cacache": "^20.0.1",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/picomatch": "^4.0.3",
|
||||
"@types/plist": "^3.0.5",
|
||||
"@types/proper-lockfile": "^4.1.4",
|
||||
|
||||
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-code-best",
|
||||
"version": "1.3.6",
|
||||
"version": "1.3.7",
|
||||
"description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal",
|
||||
"type": "module",
|
||||
"author": "claude-code-best <claude-code-best@proton.me>",
|
||||
@@ -52,6 +52,7 @@
|
||||
"health": "bun run scripts/health-check.ts",
|
||||
"postinstall": "node scripts/postinstall.cjs && node scripts/setup-chrome-mcp.mjs",
|
||||
"docs:dev": "npx mintlify dev",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"rcs": "bun run scripts/rcs.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -59,10 +60,6 @@
|
||||
"@claude-code-best/mcp-chrome-bridge": "^2.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/he": "^1.2.3",
|
||||
"@langfuse/otel": "^5.1.0",
|
||||
"@langfuse/tracing": "^5.1.0",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@alcalzone/ansi-tokenize": "^0.3.0",
|
||||
"@ant/claude-for-chrome-mcp": "workspace:*",
|
||||
"@ant/computer-use-input": "workspace:*",
|
||||
@@ -76,9 +73,6 @@
|
||||
"@anthropic-ai/sdk": "^0.80.0",
|
||||
"@anthropic-ai/vertex-sdk": "^0.14.4",
|
||||
"@anthropic/ink": "workspace:*",
|
||||
"@claude-code-best/builtin-tools": "workspace:*",
|
||||
"@claude-code-best/agent-tools": "workspace:*",
|
||||
"@claude-code-best/mcp-client": "workspace:*",
|
||||
"@aws-sdk/client-bedrock": "^3.1020.0",
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.1020.0",
|
||||
"@aws-sdk/client-sts": "^3.1020.0",
|
||||
@@ -86,8 +80,13 @@
|
||||
"@aws-sdk/credential-providers": "^3.1020.0",
|
||||
"@azure/identity": "^4.13.1",
|
||||
"@biomejs/biome": "^2.4.10",
|
||||
"@claude-code-best/agent-tools": "workspace:*",
|
||||
"@claude-code-best/builtin-tools": "workspace:*",
|
||||
"@claude-code-best/mcp-client": "workspace:*",
|
||||
"@commander-js/extra-typings": "^14.0.0",
|
||||
"@growthbook/growthbook": "^1.6.5",
|
||||
"@langfuse/otel": "^5.1.0",
|
||||
"@langfuse/tracing": "^5.1.0",
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"@opentelemetry/api": "^1.9.1",
|
||||
"@opentelemetry/api-logs": "^0.214.0",
|
||||
@@ -110,8 +109,11 @@
|
||||
"@sentry/node": "^10.47.0",
|
||||
"@smithy/core": "^3.23.13",
|
||||
"@smithy/node-http-handler": "^4.5.1",
|
||||
"@types/bun": "^1.3.11",
|
||||
"@types/bun": "^1.3.12",
|
||||
"@types/cacache": "^20.0.1",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/picomatch": "^4.0.3",
|
||||
"@types/plist": "^3.0.5",
|
||||
"@types/proper-lockfile": "^4.1.4",
|
||||
|
||||
5
packages/@ant/claude-for-chrome-mcp/tsconfig.json
Normal file
5
packages/@ant/claude-for-chrome-mcp/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -5,9 +5,12 @@
|
||||
* mouse and keyboard via CoreGraphics events and System Events.
|
||||
*/
|
||||
|
||||
import { $ } from 'bun'
|
||||
import { execFile, execFileSync } from 'child_process'
|
||||
import { promisify } from 'util'
|
||||
import type { FrontmostAppInfo, InputBackend } from '../types.js'
|
||||
|
||||
const execFileAsync = promisify(execFile)
|
||||
|
||||
const KEY_MAP: Record<string, number> = {
|
||||
return: 36, enter: 36, tab: 48, space: 49, delete: 51, backspace: 51,
|
||||
escape: 53, esc: 53,
|
||||
@@ -25,13 +28,17 @@ const MODIFIER_MAP: Record<string, string> = {
|
||||
}
|
||||
|
||||
async function osascript(script: string): Promise<string> {
|
||||
const result = await $`osascript -e ${script}`.quiet().nothrow().text()
|
||||
return result.trim()
|
||||
const { stdout } = await execFileAsync('osascript', ['-e', script], {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
async function jxa(script: string): Promise<string> {
|
||||
const result = await $`osascript -l JavaScript -e ${script}`.quiet().nothrow().text()
|
||||
return result.trim()
|
||||
const { stdout } = await execFileAsync('osascript', ['-l', 'JavaScript', '-e', script], {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
function buildMouseJxa(eventType: string, x: number, y: number, btn: number, clickState?: number): string {
|
||||
@@ -115,19 +122,14 @@ export const typeText: InputBackend['typeText'] = async (text) => {
|
||||
|
||||
export const getFrontmostAppInfo: InputBackend['getFrontmostAppInfo'] = () => {
|
||||
try {
|
||||
const result = Bun.spawnSync({
|
||||
cmd: ['osascript', '-e', `
|
||||
tell application "System Events"
|
||||
set frontApp to first application process whose frontmost is true
|
||||
set appName to name of frontApp
|
||||
set bundleId to bundle identifier of frontApp
|
||||
return bundleId & "|" & appName
|
||||
end tell
|
||||
`],
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
})
|
||||
const output = new TextDecoder().decode(result.stdout).trim()
|
||||
const output = execFileSync('osascript', ['-e', `
|
||||
tell application "System Events"
|
||||
set frontApp to first application process whose frontmost is true
|
||||
set appName to name of frontApp
|
||||
set bundleId to bundle identifier of frontApp
|
||||
return bundleId & "|" & appName
|
||||
end tell
|
||||
`], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] }).trim()
|
||||
if (!output || !output.includes('|')) return null
|
||||
const [bundleId, appName] = output.split('|', 2)
|
||||
return { bundleId: bundleId!, appName: appName! }
|
||||
|
||||
5
packages/@ant/computer-use-input/tsconfig.json
Normal file
5
packages/@ant/computer-use-input/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/@ant/computer-use-mcp/tsconfig.json
Normal file
5
packages/@ant/computer-use-mcp/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -274,4 +274,9 @@ export const screenshot: ScreenshotAPI = {
|
||||
if (displayId !== undefined) args.push('-D', String(displayId))
|
||||
return captureScreenToBase64(args)
|
||||
},
|
||||
|
||||
captureWindowTarget(_titleOrHwnd: string | number): ScreenshotResult | null {
|
||||
// Window capture not supported on macOS via this backend
|
||||
return null
|
||||
},
|
||||
}
|
||||
|
||||
@@ -275,4 +275,9 @@ export const screenshot: ScreenshotAPI = {
|
||||
return { base64: '', width: 0, height: 0 }
|
||||
}
|
||||
},
|
||||
|
||||
captureWindowTarget(_titleOrHwnd: string | number): ScreenshotResult | null {
|
||||
// Window capture not supported on Linux via this backend
|
||||
return null
|
||||
},
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ export interface ScreenshotAPI {
|
||||
x: number, y: number, w: number, h: number,
|
||||
outW: number, outH: number, quality: number, displayId?: number,
|
||||
): Promise<ScreenshotResult>
|
||||
captureWindowTarget(titleOrHwnd: string | number): ScreenshotResult | null
|
||||
}
|
||||
|
||||
export interface SwiftBackend {
|
||||
|
||||
5
packages/@ant/computer-use-swift/tsconfig.json
Normal file
5
packages/@ant/computer-use-swift/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/@ant/ink/tsconfig.json
Normal file
5
packages/@ant/ink/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from 'bun:test'
|
||||
import type { CoreTool, Tool, Tools, AnyObject, ToolResult, ValidationResult, PermissionResult } from '@claude-code-best/agent-tools'
|
||||
import type { Tool as HostTool } from '../../src/Tool.js'
|
||||
import type { Tool as HostTool } from '../../../../src/Tool.js'
|
||||
|
||||
describe('agent-tools compatibility', () => {
|
||||
test('CoreTool structural compatibility with host Tool', () => {
|
||||
@@ -27,7 +27,7 @@ describe('agent-tools compatibility', () => {
|
||||
}
|
||||
|
||||
// This assignment should work if HostTool structurally extends CoreTool
|
||||
const coreTool: CoreTool = mockHostTool as CoreTool
|
||||
const coreTool: CoreTool = mockHostTool as unknown as CoreTool
|
||||
expect(coreTool.name).toBe('test')
|
||||
expect(coreTool.isEnabled()).toBe(true)
|
||||
})
|
||||
|
||||
5
packages/agent-tools/tsconfig.json
Normal file
5
packages/agent-tools/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/audio-capture-napi/tsconfig.json
Normal file
5
packages/audio-capture-napi/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/builtin-tools/tsconfig.json
Normal file
5
packages/builtin-tools/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -72,18 +72,18 @@ describe("detectColorMode", () => {
|
||||
|
||||
describe("detectLanguage", () => {
|
||||
test("detects language from file extension", () => {
|
||||
expect(detectLanguage("index.ts")).toBe("ts");
|
||||
expect(detectLanguage("main.py")).toBe("py");
|
||||
expect(detectLanguage("style.css")).toBe("css");
|
||||
expect(detectLanguage("index.ts", null)).toBe("ts");
|
||||
expect(detectLanguage("main.py", null)).toBe("py");
|
||||
expect(detectLanguage("style.css", null)).toBe("css");
|
||||
});
|
||||
|
||||
test("detects language from known filenames", () => {
|
||||
expect(detectLanguage("Makefile")).toBe("makefile");
|
||||
expect(detectLanguage("Dockerfile")).toBe("dockerfile");
|
||||
expect(detectLanguage("Makefile", null)).toBe("makefile");
|
||||
expect(detectLanguage("Dockerfile", null)).toBe("dockerfile");
|
||||
});
|
||||
|
||||
test("returns null for unknown extensions", () => {
|
||||
expect(detectLanguage("file.xyz123")).toBeNull();
|
||||
expect(detectLanguage("file.xyz123", null)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
5
packages/color-diff-napi/tsconfig.json
Normal file
5
packages/color-diff-napi/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/image-processor-napi/tsconfig.json
Normal file
5
packages/image-processor-napi/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -38,7 +38,7 @@ describe('InProcessTransport', () => {
|
||||
let received: JSONRPCMessage | null = null
|
||||
client.onmessage = (msg) => { received = msg }
|
||||
|
||||
await server.send({ jsonrpc: '2.0', result: 42, id: 1 })
|
||||
await server.send({ jsonrpc: '2.0', result: 42, id: 1 } as any)
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
|
||||
|
||||
@@ -57,9 +57,9 @@ describe('discoverTools', () => {
|
||||
expect(tool.name).toBe('mcp__my-server__search')
|
||||
expect(tool.mcpInfo).toEqual({ serverName: 'my-server', toolName: 'search' })
|
||||
expect(tool.isMcp).toBe(true)
|
||||
expect(tool.isReadOnly()).toBe(true)
|
||||
expect(tool.userFacingName()).toBe('Search Items')
|
||||
expect(await tool.description()).toBe('Search for items')
|
||||
expect(tool.isReadOnly({} as any)).toBe(true)
|
||||
expect(tool.userFacingName(undefined)).toBe('Search Items')
|
||||
expect(await tool.description({} as any, { isNonInteractiveSession: false, toolPermissionContext: {}, tools: [] })).toBe('Search for items')
|
||||
})
|
||||
|
||||
test('respects skipPrefix option', async () => {
|
||||
|
||||
@@ -65,7 +65,7 @@ describe('createMcpManager', () => {
|
||||
|
||||
const result = await manager.connect('test-server', { command: 'npx', args: [] })
|
||||
expect(result.type).toBe('connected')
|
||||
expect(connectedEvent).toBe('test-server')
|
||||
expect(connectedEvent as unknown as string).toBe('test-server')
|
||||
})
|
||||
|
||||
test('disconnect calls cleanup and emits disconnected', async () => {
|
||||
|
||||
5
packages/mcp-client/tsconfig.json
Normal file
5
packages/mcp-client/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
5
packages/modifiers-napi/tsconfig.json
Normal file
5
packages/modifiers-napi/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -75,7 +75,7 @@ describe("Disconnect Monitor Logic", () => {
|
||||
});
|
||||
|
||||
test("session becomes inactive when updatedAt is too old", () => {
|
||||
const session = storeCreateSession({ status: "idle" });
|
||||
const session = storeCreateSession({});
|
||||
storeUpdateSession(session.id, { status: "running" });
|
||||
const timeoutMs = 300 * 1000 * 2; // 2x disconnect timeout
|
||||
|
||||
|
||||
@@ -14,14 +14,14 @@ app.post("/bridge", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
|
||||
/** DELETE /v1/environments/bridge/:id — Deregister */
|
||||
app.delete("/bridge/:id", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const envId = c.req.param("id");
|
||||
const envId = c.req.param("id")!;
|
||||
deregisterEnvironment(envId);
|
||||
return c.json({ status: "ok" }, 200);
|
||||
});
|
||||
|
||||
/** POST /v1/environments/:id/bridge/reconnect — Reconnect */
|
||||
app.post("/:id/bridge/reconnect", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const envId = c.req.param("id");
|
||||
const envId = c.req.param("id")!;
|
||||
reconnectEnvironment(envId);
|
||||
const { reconnectWorkForEnvironment } = await import("../../services/work-dispatch");
|
||||
await reconnectWorkForEnvironment(envId);
|
||||
|
||||
@@ -7,7 +7,7 @@ const app = new Hono();
|
||||
|
||||
/** GET /v1/environments/:id/work/poll — Long-poll for work */
|
||||
app.get("/:id/work/poll", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const envId = c.req.param("id");
|
||||
const envId = c.req.param("id")!;
|
||||
updatePollTime(envId);
|
||||
const result = await pollWork(envId);
|
||||
if (!result) {
|
||||
@@ -19,21 +19,21 @@ app.get("/:id/work/poll", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
|
||||
/** POST /v1/environments/:id/work/:workId/ack — Acknowledge work */
|
||||
app.post("/:id/work/:workId/ack", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const workId = c.req.param("workId");
|
||||
const workId = c.req.param("workId")!;
|
||||
ackWork(workId);
|
||||
return c.json({ status: "ok" }, 200);
|
||||
});
|
||||
|
||||
/** POST /v1/environments/:id/work/:workId/stop — Stop work */
|
||||
app.post("/:id/work/:workId/stop", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const workId = c.req.param("workId");
|
||||
const workId = c.req.param("workId")!;
|
||||
stopWork(workId);
|
||||
return c.json({ status: "ok" }, 200);
|
||||
});
|
||||
|
||||
/** POST /v1/environments/:id/work/:workId/heartbeat — Heartbeat */
|
||||
app.post("/:id/work/:workId/heartbeat", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const workId = c.req.param("workId");
|
||||
const workId = c.req.param("workId")!;
|
||||
const result = heartbeatWork(workId);
|
||||
return c.json(result, 200);
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ app.post("/", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
|
||||
/** GET /v1/sessions/:id — Get session */
|
||||
app.get("/:id", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const session = getSession(c.req.param("id"));
|
||||
const session = getSession(c.req.param("id")!);
|
||||
if (!session) {
|
||||
return c.json({ error: { type: "not_found", message: "Session not found" } }, 404);
|
||||
}
|
||||
@@ -49,16 +49,16 @@ app.get("/:id", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
app.patch("/:id", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const body = await c.req.json();
|
||||
if (body.title) {
|
||||
updateSessionTitle(c.req.param("id"), body.title);
|
||||
updateSessionTitle(c.req.param("id")!, body.title);
|
||||
}
|
||||
const session = getSession(c.req.param("id"));
|
||||
const session = getSession(c.req.param("id")!);
|
||||
return c.json(session, 200);
|
||||
});
|
||||
|
||||
/** POST /v1/sessions/:id/archive — Archive session */
|
||||
app.post("/:id/archive", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
try {
|
||||
archiveSession(c.req.param("id"));
|
||||
archiveSession(c.req.param("id")!);
|
||||
} catch {
|
||||
return c.json({ status: "ok" }, 409);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ app.post("/:id/archive", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
|
||||
/** POST /v1/sessions/:id/events — Send event to session */
|
||||
app.post("/:id/events", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const body = await c.req.json();
|
||||
|
||||
const events = body.events
|
||||
|
||||
@@ -15,7 +15,7 @@ app.post("/", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
|
||||
/** POST /v1/code/sessions/:id/bridge — Get connection info + worker JWT */
|
||||
app.post("/:id/bridge", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const session = getSession(sessionId);
|
||||
if (!session) {
|
||||
return c.json({ error: { type: "not_found", message: "Session not found" } }, 404);
|
||||
|
||||
@@ -7,7 +7,7 @@ const app = new Hono();
|
||||
|
||||
/** SSE /v1/code/sessions/:id/worker/events/stream — SSE event stream */
|
||||
app.get("/:id/worker/events/stream", acceptCliHeaders, sessionIngressAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const session = getSession(sessionId);
|
||||
if (!session) {
|
||||
return c.json({ error: { type: "not_found", message: "Session not found" } }, 404);
|
||||
|
||||
@@ -7,7 +7,7 @@ const app = new Hono();
|
||||
|
||||
/** POST /v1/code/sessions/:id/worker/events — Write events */
|
||||
app.post("/:id/worker/events", acceptCliHeaders, sessionIngressAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const body = await c.req.json();
|
||||
|
||||
const events = Array.isArray(body) ? body : [body];
|
||||
@@ -22,7 +22,7 @@ app.post("/:id/worker/events", acceptCliHeaders, sessionIngressAuth, async (c) =
|
||||
|
||||
/** PUT /v1/code/sessions/:id/worker/state — Report worker state */
|
||||
app.put("/:id/worker/state", acceptCliHeaders, sessionIngressAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const body = await c.req.json();
|
||||
|
||||
if (body.status) {
|
||||
|
||||
@@ -6,7 +6,7 @@ const app = new Hono();
|
||||
|
||||
/** POST /v1/code/sessions/:id/worker/register — Register worker */
|
||||
app.post("/:id/worker/register", acceptCliHeaders, apiKeyAuth, async (c) => {
|
||||
const sessionId = c.req.param("id");
|
||||
const sessionId = c.req.param("id")!;
|
||||
const session = getSession(sessionId);
|
||||
if (!session) {
|
||||
return c.json({ error: { type: "not_found", message: "Session not found" } }, 404);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { storeIsSessionOwner } from "../../store";
|
||||
const app = new Hono();
|
||||
|
||||
function checkOwnership(c: { get: (key: string) => string | undefined }, sessionId: string) {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
if (!storeIsSessionOwner(sessionId, uuid)) {
|
||||
return { error: true, session: null };
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const app = new Hono();
|
||||
|
||||
/** POST /web/sessions — Create a session from web UI */
|
||||
app.post("/sessions", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const body = await c.req.json();
|
||||
const session = createSession({
|
||||
environment_id: body.environment_id || null,
|
||||
@@ -37,21 +37,21 @@ app.post("/sessions", uuidAuth, async (c) => {
|
||||
|
||||
/** GET /web/sessions — List sessions owned by the requesting UUID */
|
||||
app.get("/sessions", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const sessions = storeListSessionsByOwnerUuid(uuid);
|
||||
return c.json(sessions, 200);
|
||||
});
|
||||
|
||||
/** GET /web/sessions/all — List sessions owned by the requesting UUID (unowned sessions excluded) */
|
||||
app.get("/sessions/all", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const sessions = listSessionSummariesByOwnerUuid(uuid);
|
||||
return c.json(sessions, 200);
|
||||
});
|
||||
|
||||
/** GET /web/sessions/:id — Session detail */
|
||||
app.get("/sessions/:id", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const sessionId = c.req.param("id")!;
|
||||
if (!storeIsSessionOwner(sessionId, uuid)) {
|
||||
return c.json({ error: { type: "forbidden", message: "Not your session" } }, 403);
|
||||
@@ -65,7 +65,7 @@ app.get("/sessions/:id", uuidAuth, async (c) => {
|
||||
|
||||
/** GET /web/sessions/:id/history — Historical events for session */
|
||||
app.get("/sessions/:id/history", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const sessionId = c.req.param("id")!;
|
||||
if (!storeIsSessionOwner(sessionId, uuid)) {
|
||||
return c.json({ error: { type: "forbidden", message: "Not your session" } }, 403);
|
||||
@@ -82,7 +82,7 @@ app.get("/sessions/:id/history", uuidAuth, async (c) => {
|
||||
|
||||
/** SSE /web/sessions/:id/events — Real-time event stream */
|
||||
app.get("/sessions/:id/events", uuidAuth, async (c) => {
|
||||
const uuid = c.get("uuid");
|
||||
const uuid = c.get("uuid")!;
|
||||
const sessionId = c.req.param("id")!;
|
||||
if (!storeIsSessionOwner(sessionId, uuid)) {
|
||||
return c.json({ error: { type: "forbidden", message: "Not your session" } }, 403);
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": ".",
|
||||
"declaration": true,
|
||||
"resolveJsonModule": true,
|
||||
"types": ["bun-types"]
|
||||
},
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist", "web"]
|
||||
}
|
||||
|
||||
5
packages/url-handler-napi/tsconfig.json
Normal file
5
packages/url-handler-napi/tsconfig.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
15
tsconfig.base.json
Normal file
15
tsconfig.base.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"jsx": "react-jsx",
|
||||
"types": ["bun", "@types/node"]
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,12 @@
|
||||
{
|
||||
"extends": "./tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true,
|
||||
"types": ["bun"],
|
||||
"paths": {
|
||||
"src/*": ["./src/*"],
|
||||
"@claude-code-best/builtin-tools/*": ["./packages/builtin-tools/src/*"],
|
||||
"@claude-code-best/builtin-tools": ["./packages/builtin-tools/src/index.ts"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "packages/builtin-tools/src/**/*.ts", "packages/builtin-tools/src/**/*.tsx"],
|
||||
"include": ["src/**/*.ts", "src/**/*.tsx", "packages/**/*.ts", "packages/**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user