@covro/covro 0.1.1-dev.2 → 0.1.1-dev.4
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 +2 -0
- package/README.zh-CN.md +2 -0
- package/dist/codex/adapter.js +109 -3
- package/dist/codex/adapter.js.map +2 -2
- package/dist/codex/transport.js +2 -2
- package/dist/codex/transport.js.map +2 -2
- package/dist/server/auth.js +1 -1
- package/dist/server/auth.js.map +2 -2
- package/dist/server/http.js +45 -0
- package/dist/server/http.js.map +2 -2
- package/dist/server/service.js +37 -3
- package/dist/server/service.js.map +2 -2
- package/dist/server/shell.js +128 -0
- package/dist/server/shell.js.map +7 -0
- package/dist/shared/shell.js +15 -0
- package/dist/shared/shell.js.map +7 -0
- package/dist/web/assets/index-CPPzmGTu.js +138 -0
- package/dist/web/assets/index-DQaJoWt3.css +1 -0
- package/dist/web/index.html +2 -2
- package/package.json +3 -3
- package/dist/web/assets/index-CqF7PUia.css +0 -1
- package/dist/web/assets/index-Cx57Ezk2.js +0 -84
package/dist/server/auth.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/server/auth.ts"],
|
|
4
|
-
"sourcesContent": ["import { createRemoteJWKSet, jwtVerify, type JWTVerifyGetKey } from 'jose';\nimport type { AppConfig } from './config.js';\nimport { AppError } from '../shared/errors.js';\nexport interface Identity {\n expiresAt?: number;\n}\nexport function createAuthenticator(\n config: AppConfig,\n testKey?: JWTVerifyGetKey | CryptoKey | Uint8Array,\n) {\n const access = config.auth.mode === 'cloudflare-access' ? config.auth : undefined;\n const key = access\n ? (testKey ?? createRemoteJWKSet(new URL('/cdn-cgi/access/certs', access.issuer)))\n : undefined;\n const origins = new Set([...config.publicOrigin, ...config.developmentOrigins]);\n const hosts = new Set([...origins].map((value) => new URL(value).host));\n return async function authenticate(request: Request, websocket = false): Promise<Identity> {\n // Host is checked in both modes; forwarded headers never grant identity.\n const host = request.headers.get('host') ?? new URL(request.url).host;\n if (!hosts.has(host))\n throw new AppError('INVALID_HOST', 'Request Host does not match a configured origin', 403);\n const requestOrigin = request.headers.get('origin');\n const mutating = !['GET', 'HEAD', 'OPTIONS'].includes(request.method);\n if ((websocket || mutating) && (!requestOrigin || !origins.has(requestOrigin)))\n throw new AppError(\n 'INVALID_ORIGIN',\n 'Request Origin does not match a configured origin',\n 403,\n );\n if (requestOrigin && !origins.has(requestOrigin))\n throw new AppError(\n 'INVALID_ORIGIN',\n 'Request Origin does not match a configured origin',\n 403,\n );\n if (\n mutating &&\n request.headers.get('content-type')?.split(';')[0]?.trim().toLowerCase() !==\n 'application/json'\n )\n throw new AppError('INVALID_CONTENT_TYPE', 'Expected application/json', 415);\n if (!access || !key) return {};\n const token = request.headers.get('cf-access-jwt-assertion');\n if (!token) throw new AppError('UNAUTHENTICATED', 'Cloudflare Access login is required', 401);\n try {\n const { payload } = await jwtVerify(token, key as JWTVerifyGetKey, {\n issuer: access.issuer,\n audience: access.audience,\n algorithms: ['RS256'],\n requiredClaims: ['exp', 'iss', 'aud', 'sub'],\n });\n return { expiresAt: payload.exp! * 1000 };\n } catch {\n throw new AppError('UNAUTHENTICATED', 'Cloudflare Access login is invalid or expired', 401);\n }\n };\n}\nexport type Authenticator = ReturnType<typeof createAuthenticator>;\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB,iBAAuC;AAEpE,SAAS,gBAAgB;
|
|
4
|
+
"sourcesContent": ["import { createRemoteJWKSet, jwtVerify, type JWTVerifyGetKey } from 'jose';\nimport type { AppConfig } from './config.js';\nimport { AppError } from '../shared/errors.js';\nexport interface Identity {\n subject?: string;\n expiresAt?: number;\n}\nexport function createAuthenticator(\n config: AppConfig,\n testKey?: JWTVerifyGetKey | CryptoKey | Uint8Array,\n) {\n const access = config.auth.mode === 'cloudflare-access' ? config.auth : undefined;\n const key = access\n ? (testKey ?? createRemoteJWKSet(new URL('/cdn-cgi/access/certs', access.issuer)))\n : undefined;\n const origins = new Set([...config.publicOrigin, ...config.developmentOrigins]);\n const hosts = new Set([...origins].map((value) => new URL(value).host));\n return async function authenticate(request: Request, websocket = false): Promise<Identity> {\n // Host is checked in both modes; forwarded headers never grant identity.\n const host = request.headers.get('host') ?? new URL(request.url).host;\n if (!hosts.has(host))\n throw new AppError('INVALID_HOST', 'Request Host does not match a configured origin', 403);\n const requestOrigin = request.headers.get('origin');\n const mutating = !['GET', 'HEAD', 'OPTIONS'].includes(request.method);\n if ((websocket || mutating) && (!requestOrigin || !origins.has(requestOrigin)))\n throw new AppError(\n 'INVALID_ORIGIN',\n 'Request Origin does not match a configured origin',\n 403,\n );\n if (requestOrigin && !origins.has(requestOrigin))\n throw new AppError(\n 'INVALID_ORIGIN',\n 'Request Origin does not match a configured origin',\n 403,\n );\n if (\n mutating &&\n request.headers.get('content-type')?.split(';')[0]?.trim().toLowerCase() !==\n 'application/json'\n )\n throw new AppError('INVALID_CONTENT_TYPE', 'Expected application/json', 415);\n if (!access || !key) return {};\n const token = request.headers.get('cf-access-jwt-assertion');\n if (!token) throw new AppError('UNAUTHENTICATED', 'Cloudflare Access login is required', 401);\n try {\n const { payload } = await jwtVerify(token, key as JWTVerifyGetKey, {\n issuer: access.issuer,\n audience: access.audience,\n algorithms: ['RS256'],\n requiredClaims: ['exp', 'iss', 'aud', 'sub'],\n });\n return { subject: payload.sub!, expiresAt: payload.exp! * 1000 };\n } catch {\n throw new AppError('UNAUTHENTICATED', 'Cloudflare Access login is invalid or expired', 401);\n }\n };\n}\nexport type Authenticator = ReturnType<typeof createAuthenticator>;\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB,iBAAuC;AAEpE,SAAS,gBAAgB;AAKlB,SAAS,oBACd,QACA,SACA;AACA,QAAM,SAAS,OAAO,KAAK,SAAS,sBAAsB,OAAO,OAAO;AACxE,QAAM,MAAM,SACP,WAAW,mBAAmB,IAAI,IAAI,yBAAyB,OAAO,MAAM,CAAC,IAC9E;AACJ,QAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,cAAc,GAAG,OAAO,kBAAkB,CAAC;AAC9E,QAAM,QAAQ,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC;AACtE,SAAO,eAAe,aAAa,SAAkB,YAAY,OAA0B;AAEzF,UAAM,OAAO,QAAQ,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,QAAQ,GAAG,EAAE;AACjE,QAAI,CAAC,MAAM,IAAI,IAAI;AACjB,YAAM,IAAI,SAAS,gBAAgB,mDAAmD,GAAG;AAC3F,UAAM,gBAAgB,QAAQ,QAAQ,IAAI,QAAQ;AAClD,UAAM,WAAW,CAAC,CAAC,OAAO,QAAQ,SAAS,EAAE,SAAS,QAAQ,MAAM;AACpE,SAAK,aAAa,cAAc,CAAC,iBAAiB,CAAC,QAAQ,IAAI,aAAa;AAC1E,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACF,QAAI,iBAAiB,CAAC,QAAQ,IAAI,aAAa;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACF,QACE,YACA,QAAQ,QAAQ,IAAI,cAAc,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,EAAE,YAAY,MACrE;AAEF,YAAM,IAAI,SAAS,wBAAwB,6BAA6B,GAAG;AAC7E,QAAI,CAAC,UAAU,CAAC,IAAK,QAAO,CAAC;AAC7B,UAAM,QAAQ,QAAQ,QAAQ,IAAI,yBAAyB;AAC3D,QAAI,CAAC,MAAO,OAAM,IAAI,SAAS,mBAAmB,uCAAuC,GAAG;AAC5F,QAAI;AACF,YAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,KAAwB;AAAA,QACjE,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,QACjB,YAAY,CAAC,OAAO;AAAA,QACpB,gBAAgB,CAAC,OAAO,OAAO,OAAO,KAAK;AAAA,MAC7C,CAAC;AACD,aAAO,EAAE,SAAS,QAAQ,KAAM,WAAW,QAAQ,MAAO,IAAK;AAAA,IACjE,QAAQ;AACN,YAAM,IAAI,SAAS,mBAAmB,iDAAiD,GAAG;AAAA,IAC5F;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/server/http.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { Hono } from "hono";
|
|
2
3
|
import { bodyLimit } from "hono/body-limit";
|
|
3
4
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
@@ -12,6 +13,7 @@ import { socketHandlers } from "./websocket.js";
|
|
|
12
13
|
import { z } from "zod";
|
|
13
14
|
import { releaseChannels } from "../shared/updates.js";
|
|
14
15
|
import { settingsSchema, updateRequestSchema } from "../updates/manager.js";
|
|
16
|
+
import { startShellSchema } from "../shared/shell.js";
|
|
15
17
|
function createApp({
|
|
16
18
|
config,
|
|
17
19
|
service,
|
|
@@ -82,7 +84,46 @@ function createApp({
|
|
|
82
84
|
c.header("Content-Disposition", 'attachment; filename="codex-web-config.json"');
|
|
83
85
|
return c.json(await configuration.export());
|
|
84
86
|
});
|
|
87
|
+
app.get("/api/history-cache-context", async (c) => {
|
|
88
|
+
const identity = c.get("identity");
|
|
89
|
+
if (config.auth.mode !== "local" && !identity.subject)
|
|
90
|
+
throw new AppError("UNAUTHENTICATED", "\u65E0\u6CD5\u786E\u8BA4\u7F13\u5B58\u6240\u5C5E\u7528\u6237", 401);
|
|
91
|
+
const projects = await service.listProjects();
|
|
92
|
+
const scope = createHash("sha256").update(
|
|
93
|
+
JSON.stringify([
|
|
94
|
+
service.events.serverEpoch,
|
|
95
|
+
service.getSystem().codexEpoch,
|
|
96
|
+
config.auth.mode,
|
|
97
|
+
identity.subject ?? "local",
|
|
98
|
+
projects.map((project) => [project.id, project.rootPath, project.available])
|
|
99
|
+
])
|
|
100
|
+
).digest("hex");
|
|
101
|
+
return c.json({ scope });
|
|
102
|
+
});
|
|
85
103
|
app.get("/api/system", (c) => c.json(service.getSystem()));
|
|
104
|
+
app.get(
|
|
105
|
+
"/api/shell",
|
|
106
|
+
(c) => c.json(
|
|
107
|
+
service.shell.snapshot(
|
|
108
|
+
c.req.query("epoch"),
|
|
109
|
+
z.coerce.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0).parse(c.req.query("after"))
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
app.post("/api/projects/:projectId/shell", async (c) => {
|
|
114
|
+
const op = await service.startShell(
|
|
115
|
+
id(c.req.param("projectId")),
|
|
116
|
+
await parse(c, startShellSchema)
|
|
117
|
+
);
|
|
118
|
+
return c.json(op, status(op));
|
|
119
|
+
});
|
|
120
|
+
app.post("/api/shell/:commandId/interrupt", async (c) => {
|
|
121
|
+
const op = await service.interruptShell(
|
|
122
|
+
id(c.req.param("commandId")),
|
|
123
|
+
await parse(c, schemas.operationSchema)
|
|
124
|
+
);
|
|
125
|
+
return c.json(op, status(op));
|
|
126
|
+
});
|
|
86
127
|
app.post("/api/system/compatibility/confirm", async (c) => {
|
|
87
128
|
const op = await service.confirmCompatibility(
|
|
88
129
|
await parse(c, schemas.confirmCompatibilitySchema)
|
|
@@ -150,6 +191,10 @@ function createApp({
|
|
|
150
191
|
"/api/threads/:threadId",
|
|
151
192
|
async (c) => c.json(await service.getThread(id(c.req.param("threadId"))))
|
|
152
193
|
);
|
|
194
|
+
app.get(
|
|
195
|
+
"/api/threads/:threadId/history",
|
|
196
|
+
async (c) => c.json(await service.getThreadHistory(id(c.req.param("threadId")), c.req.query("cursor")))
|
|
197
|
+
);
|
|
153
198
|
app.get(
|
|
154
199
|
"/api/threads/:threadId/metadata",
|
|
155
200
|
async (c) => c.json(await service.getThreadMetadata(id(c.req.param("threadId"))))
|
package/dist/server/http.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/server/http.ts"],
|
|
4
|
-
"sourcesContent": ["import { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport { upgradeWebSocket, type HttpBindings } from '@hono/node-server';\nimport type { ZodType } from 'zod';\nimport { ZodError } from 'zod';\nimport { AppError } from '../shared/errors.js';\nimport { IMAGE_REQUEST_BYTES } from '../shared/images.js';\nimport * as schemas from '../shared/validation.js';\nimport type { Operation } from '../shared/types.js';\nimport type { AppConfig } from './config.js';\nimport { ConfigStore } from './config-store.js';\nimport { createAuthenticator, type Authenticator, type Identity } from './auth.js';\nimport type { GatewayService } from './service.js';\nimport { socketHandlers } from './websocket.js';\nimport { z } from 'zod';\nimport { releaseChannels, type UpdateController } from '../shared/updates.js';\nimport { settingsSchema, updateRequestSchema } from '../updates/manager.js';\nexport interface HttpDependencies {\n config: AppConfig;\n service: GatewayService;\n staticDir: string;\n authenticate?: Authenticator;\n updates?: UpdateController;\n}\nexport function createApp({\n config,\n service,\n staticDir,\n authenticate = createAuthenticator(config),\n updates,\n}: HttpDependencies) {\n const app = new Hono<{\n Bindings: HttpBindings;\n Variables: { identity: Identity; operationId?: string };\n }>();\n app.onError((error, c) => {\n const failure =\n error instanceof AppError\n ? error\n : error instanceof ZodError || error instanceof SyntaxError\n ? new AppError('VALIDATION_FAILED', 'Invalid request data', 400)\n : new AppError('INTERNAL_ERROR', 'An internal error occurred', 500);\n return c.json({ error: failure.toJSON(c.get('operationId')) }, failure.status as 400);\n });\n app.get('/api/health', (c) => c.json({ ok: true }));\n app.use('*', async (c, next) => {\n c.set('identity', await authenticate(c.req.raw, c.req.path === '/ws'));\n await next();\n });\n app.use('/api/*', (c, next) =>\n bodyLimit({\n maxSize: /^\\/api\\/threads\\/[^/]+\\/(turns|steer)$/.test(c.req.path)\n ? IMAGE_REQUEST_BYTES\n : 512 * 1024,\n onError: () => {\n throw new AppError('BODY_TOO_LARGE', 'Request body exceeds limit', 413);\n },\n })(c, next),\n );\n app.use('/api/*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n if (\n service.isInMaintenance() &&\n !['GET', 'HEAD', 'OPTIONS'].includes(c.req.method) &&\n !c.req.path.startsWith('/api/updates')\n )\n throw new AppError('UPDATE_MAINTENANCE', '\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5', 503);\n await next();\n });\n if (updates) {\n app.get('/api/updates', async (c) => c.json(await updates.status()));\n app.post('/api/updates/check', async (c) => {\n const input = z\n .object({ channel: z.enum(releaseChannels).optional() })\n .strict()\n .parse(await c.req.json());\n return c.json(await updates.check(input.channel));\n });\n app.post('/api/updates/settings', async (c) =>\n c.json(await updates.configure(settingsSchema.parse(await c.req.json()))),\n );\n app.post('/api/updates/run', async (c) =>\n c.json(await updates.start(updateRequestSchema.parse(await c.req.json())), 202),\n );\n }\n const id = (value: string) => schemas.idSchema.parse(value);\n const parse = async <T>(\n c: { req: { json: () => Promise<unknown> }; set: (key: 'operationId', value: string) => void },\n schema: ZodType<T>,\n ): Promise<T> => {\n const value: unknown = await c.req.json();\n if (\n value &&\n typeof value === 'object' &&\n 'clientOperationId' in value &&\n typeof value.clientOperationId === 'string'\n )\n c.set('operationId', value.clientOperationId);\n return schema.parse(value);\n };\n const status = (op: Operation) =>\n op.status === 'dispatching' || op.status === 'accepted' ? (202 as const) : (200 as const);\n const configuration = new ConfigStore(config);\n app.use('/api/config*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n await next();\n });\n app.get('/api/config', async (c) => c.json(await configuration.snapshot()));\n app.post('/api/config', async (c) => c.json(await configuration.save(await c.req.json())));\n app.post('/api/config/import', async (c) =>\n c.json(await configuration.previewImport(await c.req.json())),\n );\n app.get('/api/config/export', async (c) => {\n c.header('Content-Disposition', 'attachment; filename=\"codex-web-config.json\"');\n return c.json(await configuration.export());\n });\n app.get('/api/system', (c) => c.json(service.getSystem()));\n app.post('/api/system/compatibility/confirm', async (c) => {\n const op = await service.confirmCompatibility(\n await parse(c, schemas.confirmCompatibilitySchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/projects', async (c) => c.json({ data: await service.listProjects() }));\n app.get('/api/projects/:projectId/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(id(c.req.param('projectId')))),\n );\n app.post('/api/projects/:projectId/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n id(c.req.param('projectId')),\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/projects', async (c) =>\n c.json(service.addProject(await parse(c, schemas.createProjectSchema))),\n );\n app.post('/api/projects/:projectId/rename', async (c) =>\n c.json(\n service.renameProject(\n id(c.req.param('projectId')),\n await parse(c, schemas.renameProjectSchema),\n ),\n ),\n );\n app.post('/api/projects/:projectId/remove', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.removeProject(id(c.req.param('projectId'))));\n });\n app.get('/api/projects/:projectId/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n id(c.req.param('projectId')),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.get('/api/threads', async (c) =>\n c.json(\n await service.listThreads(\n id(c.req.query('projectId') ?? ''),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/threads/:threadId/archive', async (c) => {\n return c.json(\n await service.setThreadArchived(\n id(c.req.param('threadId')),\n await parse(c, schemas.archiveThreadSchema),\n ),\n );\n });\n app.get('/api/threads/:threadId', async (c) =>\n c.json(await service.getThread(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/metadata', async (c) =>\n c.json(await service.getThreadMetadata(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/export', async (c) => {\n const exported = await service.exportThread(id(c.req.param('threadId')));\n c.header('Content-Type', 'text/markdown; charset=utf-8');\n c.header('Content-Disposition', `attachment; filename=\"${exported.filename}\"`);\n c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Export-Completeness', exported.partial ? 'partial' : 'saved-history');\n return c.body(exported.markdown);\n });\n app.get('/api/threads/:threadId/images', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n c.header('Content-Security-Policy', \"default-src 'none'; sandbox\");\n const image = await service.getThreadImage(id(c.req.param('threadId')), c.req.query('path'));\n return c.body(image.bytes, 200, {\n 'Content-Type': image.contentType,\n 'Content-Length': String(image.bytes.length),\n });\n });\n app.get('/api/threads/:threadId/markdown', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(\n await service.getThreadMarkdown(id(c.req.param('threadId')), c.req.query('path')),\n );\n });\n app.get('/api/threads/:threadId/json', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(await service.getThreadJson(id(c.req.param('threadId')), c.req.query('path')));\n });\n app.get('/api/operations/:operationId', (c) =>\n c.json(service.getOperation(id(c.req.param('operationId')))),\n );\n app.post('/api/projects/:projectId/threads', async (c) => {\n const op = await service.createThread(\n id(c.req.param('projectId')),\n await parse(c, schemas.createThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/resume', async (c) => {\n const op = await service.resumeThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.resumeThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/fork', async (c) => {\n const op = await service.forkThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.forkThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/rename', async (c) => {\n const op = await service.renameThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.renameThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/turns', async (c) => {\n const op = await service.startTurn(\n id(c.req.param('threadId')),\n await parse(c, schemas.startTurnSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/review', async (c) => {\n const op = await service.startReview(\n id(c.req.param('threadId')),\n await parse(c, schemas.startReviewSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/steer', async (c) => {\n const op = await service.steer(\n id(c.req.param('threadId')),\n await parse(c, schemas.steerSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/compact', async (c) => {\n const op = await service.compactThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/interrupt', async (c) => {\n const op = await service.interrupt(\n id(c.req.param('threadId')),\n await parse(c, schemas.interruptSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/actions/:actionId/resolve', async (c) => {\n const op = await service.resolveAction(\n id(c.req.param('actionId')),\n await parse(c, schemas.resolveActionSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/operations/:operationId/reconcile', async (c) => {\n const op = await service.reconcileOperation(\n id(c.req.param('operationId')),\n await parse(c, schemas.reconcileSchema),\n );\n return c.json(op, status(op));\n });\n app.get(\n '/ws',\n upgradeWebSocket((c) =>\n socketHandlers(service, config, c.get('identity'), c.req.query('overview') === '1'),\n ),\n );\n app.all('/api/*', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/api', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/ws/*', () => {\n throw new AppError('NOT_FOUND', 'WebSocket route not found', 404);\n });\n app.use('*', async (c, next) => {\n if (!c.req.path.startsWith('/assets/')) c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'same-origin');\n c.header(\n 'Content-Security-Policy',\n // Remote Markdown images load directly in the browser, including HTTPS redirects.\n // Keep scripts, connections and all other resource policies restricted as before.\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'\",\n );\n await next();\n });\n app.get('*', serveStatic({ root: staticDir }));\n app.get('*', async (c, next) => {\n if (!c.req.header('accept')?.includes('text/html') || /\\.[^/]+$/.test(c.req.path))\n return c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404);\n return serveStatic({ path: `${staticDir}/index.html` })(c, next);\n });\n app.notFound((c) => c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404));\n return app;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { createHash } from 'node:crypto';\nimport { Hono } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport { serveStatic } from '@hono/node-server/serve-static';\nimport { upgradeWebSocket, type HttpBindings } from '@hono/node-server';\nimport type { ZodType } from 'zod';\nimport { ZodError } from 'zod';\nimport { AppError } from '../shared/errors.js';\nimport { IMAGE_REQUEST_BYTES } from '../shared/images.js';\nimport * as schemas from '../shared/validation.js';\nimport type { Operation } from '../shared/types.js';\nimport type { AppConfig } from './config.js';\nimport { ConfigStore } from './config-store.js';\nimport { createAuthenticator, type Authenticator, type Identity } from './auth.js';\nimport type { GatewayService } from './service.js';\nimport { socketHandlers } from './websocket.js';\nimport { z } from 'zod';\nimport { releaseChannels, type UpdateController } from '../shared/updates.js';\nimport { settingsSchema, updateRequestSchema } from '../updates/manager.js';\nimport { startShellSchema } from '../shared/shell.js';\nexport interface HttpDependencies {\n config: AppConfig;\n service: GatewayService;\n staticDir: string;\n authenticate?: Authenticator;\n updates?: UpdateController;\n}\nexport function createApp({\n config,\n service,\n staticDir,\n authenticate = createAuthenticator(config),\n updates,\n}: HttpDependencies) {\n const app = new Hono<{\n Bindings: HttpBindings;\n Variables: { identity: Identity; operationId?: string };\n }>();\n app.onError((error, c) => {\n const failure =\n error instanceof AppError\n ? error\n : error instanceof ZodError || error instanceof SyntaxError\n ? new AppError('VALIDATION_FAILED', 'Invalid request data', 400)\n : new AppError('INTERNAL_ERROR', 'An internal error occurred', 500);\n return c.json({ error: failure.toJSON(c.get('operationId')) }, failure.status as 400);\n });\n app.get('/api/health', (c) => c.json({ ok: true }));\n app.use('*', async (c, next) => {\n c.set('identity', await authenticate(c.req.raw, c.req.path === '/ws'));\n await next();\n });\n app.use('/api/*', (c, next) =>\n bodyLimit({\n maxSize: /^\\/api\\/threads\\/[^/]+\\/(turns|steer)$/.test(c.req.path)\n ? IMAGE_REQUEST_BYTES\n : 512 * 1024,\n onError: () => {\n throw new AppError('BODY_TOO_LARGE', 'Request body exceeds limit', 413);\n },\n })(c, next),\n );\n app.use('/api/*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n if (\n service.isInMaintenance() &&\n !['GET', 'HEAD', 'OPTIONS'].includes(c.req.method) &&\n !c.req.path.startsWith('/api/updates')\n )\n throw new AppError('UPDATE_MAINTENANCE', '\u6B63\u5728\u5347\u7EA7\uFF0C\u8BF7\u7B49\u5F85\u670D\u52A1\u91CD\u65B0\u8FDE\u63A5', 503);\n await next();\n });\n if (updates) {\n app.get('/api/updates', async (c) => c.json(await updates.status()));\n app.post('/api/updates/check', async (c) => {\n const input = z\n .object({ channel: z.enum(releaseChannels).optional() })\n .strict()\n .parse(await c.req.json());\n return c.json(await updates.check(input.channel));\n });\n app.post('/api/updates/settings', async (c) =>\n c.json(await updates.configure(settingsSchema.parse(await c.req.json()))),\n );\n app.post('/api/updates/run', async (c) =>\n c.json(await updates.start(updateRequestSchema.parse(await c.req.json())), 202),\n );\n }\n const id = (value: string) => schemas.idSchema.parse(value);\n const parse = async <T>(\n c: { req: { json: () => Promise<unknown> }; set: (key: 'operationId', value: string) => void },\n schema: ZodType<T>,\n ): Promise<T> => {\n const value: unknown = await c.req.json();\n if (\n value &&\n typeof value === 'object' &&\n 'clientOperationId' in value &&\n typeof value.clientOperationId === 'string'\n )\n c.set('operationId', value.clientOperationId);\n return schema.parse(value);\n };\n const status = (op: Operation) =>\n op.status === 'dispatching' || op.status === 'accepted' ? (202 as const) : (200 as const);\n const configuration = new ConfigStore(config);\n app.use('/api/config*', async (c, next) => {\n c.header('Cache-Control', 'no-store');\n await next();\n });\n app.get('/api/config', async (c) => c.json(await configuration.snapshot()));\n app.post('/api/config', async (c) => c.json(await configuration.save(await c.req.json())));\n app.post('/api/config/import', async (c) =>\n c.json(await configuration.previewImport(await c.req.json())),\n );\n app.get('/api/config/export', async (c) => {\n c.header('Content-Disposition', 'attachment; filename=\"codex-web-config.json\"');\n return c.json(await configuration.export());\n });\n app.get('/api/history-cache-context', async (c) => {\n const identity = c.get('identity');\n if (config.auth.mode !== 'local' && !identity.subject)\n throw new AppError('UNAUTHENTICATED', '\u65E0\u6CD5\u786E\u8BA4\u7F13\u5B58\u6240\u5C5E\u7528\u6237', 401);\n const projects = await service.listProjects();\n // A restart, user change or project/permission change creates a new namespace.\n // The subject is hashed on the server and is never exposed to browser storage.\n const scope = createHash('sha256')\n .update(\n JSON.stringify([\n service.events.serverEpoch,\n service.getSystem().codexEpoch,\n config.auth.mode,\n identity.subject ?? 'local',\n projects.map((project) => [project.id, project.rootPath, project.available]),\n ]),\n )\n .digest('hex');\n return c.json({ scope });\n });\n app.get('/api/system', (c) => c.json(service.getSystem()));\n app.get('/api/shell', (c) =>\n c.json(\n service.shell.snapshot(\n c.req.query('epoch'),\n z.coerce\n .number()\n .int()\n .min(0)\n .max(Number.MAX_SAFE_INTEGER)\n .default(0)\n .parse(c.req.query('after')),\n ),\n ),\n );\n app.post('/api/projects/:projectId/shell', async (c) => {\n const op = await service.startShell(\n id(c.req.param('projectId')),\n await parse(c, startShellSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/shell/:commandId/interrupt', async (c) => {\n const op = await service.interruptShell(\n id(c.req.param('commandId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/system/compatibility/confirm', async (c) => {\n const op = await service.confirmCompatibility(\n await parse(c, schemas.confirmCompatibilitySchema),\n );\n return c.json(op, status(op));\n });\n app.get('/api/projects', async (c) => c.json({ data: await service.listProjects() }));\n app.get('/api/projects/:projectId/runtime-settings', async (c) =>\n c.json(await service.readRuntimeSettings(id(c.req.param('projectId')))),\n );\n app.post('/api/projects/:projectId/model-defaults', async (c) => {\n const op = await service.saveModelDefaults(\n id(c.req.param('projectId')),\n await parse(c, schemas.saveModelDefaultsSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/projects', async (c) =>\n c.json(service.addProject(await parse(c, schemas.createProjectSchema))),\n );\n app.post('/api/projects/:projectId/rename', async (c) =>\n c.json(\n service.renameProject(\n id(c.req.param('projectId')),\n await parse(c, schemas.renameProjectSchema),\n ),\n ),\n );\n app.post('/api/projects/:projectId/remove', async (c) => {\n await parse(c, schemas.removeProjectSchema);\n return c.json(service.removeProject(id(c.req.param('projectId'))));\n });\n app.get('/api/projects/:projectId/threads', async (c) =>\n c.json(\n await service.listThreadSummaries(\n id(c.req.param('projectId')),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.get('/api/threads', async (c) =>\n c.json(\n await service.listThreads(\n id(c.req.query('projectId') ?? ''),\n c.req.query('cursor') === undefined\n ? undefined\n : schemas.cursorSchema.parse(c.req.query('cursor')),\n schemas.archivedQuerySchema.parse(c.req.query('archived')),\n ),\n ),\n );\n app.post('/api/threads/:threadId/archive', async (c) => {\n return c.json(\n await service.setThreadArchived(\n id(c.req.param('threadId')),\n await parse(c, schemas.archiveThreadSchema),\n ),\n );\n });\n app.get('/api/threads/:threadId', async (c) =>\n c.json(await service.getThread(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/history', async (c) =>\n c.json(await service.getThreadHistory(id(c.req.param('threadId')), c.req.query('cursor'))),\n );\n app.get('/api/threads/:threadId/metadata', async (c) =>\n c.json(await service.getThreadMetadata(id(c.req.param('threadId')))),\n );\n app.get('/api/threads/:threadId/export', async (c) => {\n const exported = await service.exportThread(id(c.req.param('threadId')));\n c.header('Content-Type', 'text/markdown; charset=utf-8');\n c.header('Content-Disposition', `attachment; filename=\"${exported.filename}\"`);\n c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('X-Export-Completeness', exported.partial ? 'partial' : 'saved-history');\n return c.body(exported.markdown);\n });\n app.get('/api/threads/:threadId/images', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n c.header('Content-Security-Policy', \"default-src 'none'; sandbox\");\n const image = await service.getThreadImage(id(c.req.param('threadId')), c.req.query('path'));\n return c.body(image.bytes, 200, {\n 'Content-Type': image.contentType,\n 'Content-Length': String(image.bytes.length),\n });\n });\n app.get('/api/threads/:threadId/markdown', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(\n await service.getThreadMarkdown(id(c.req.param('threadId')), c.req.query('path')),\n );\n });\n app.get('/api/threads/:threadId/json', async (c) => {\n c.header('Cache-Control', 'private, no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Cross-Origin-Resource-Policy', 'same-origin');\n return c.json(await service.getThreadJson(id(c.req.param('threadId')), c.req.query('path')));\n });\n app.get('/api/operations/:operationId', (c) =>\n c.json(service.getOperation(id(c.req.param('operationId')))),\n );\n app.post('/api/projects/:projectId/threads', async (c) => {\n const op = await service.createThread(\n id(c.req.param('projectId')),\n await parse(c, schemas.createThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/resume', async (c) => {\n const op = await service.resumeThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.resumeThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/fork', async (c) => {\n const op = await service.forkThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.forkThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/rename', async (c) => {\n const op = await service.renameThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.renameThreadSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/turns', async (c) => {\n const op = await service.startTurn(\n id(c.req.param('threadId')),\n await parse(c, schemas.startTurnSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/review', async (c) => {\n const op = await service.startReview(\n id(c.req.param('threadId')),\n await parse(c, schemas.startReviewSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/steer', async (c) => {\n const op = await service.steer(\n id(c.req.param('threadId')),\n await parse(c, schemas.steerSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/compact', async (c) => {\n const op = await service.compactThread(\n id(c.req.param('threadId')),\n await parse(c, schemas.operationSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/threads/:threadId/interrupt', async (c) => {\n const op = await service.interrupt(\n id(c.req.param('threadId')),\n await parse(c, schemas.interruptSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/actions/:actionId/resolve', async (c) => {\n const op = await service.resolveAction(\n id(c.req.param('actionId')),\n await parse(c, schemas.resolveActionSchema),\n );\n return c.json(op, status(op));\n });\n app.post('/api/operations/:operationId/reconcile', async (c) => {\n const op = await service.reconcileOperation(\n id(c.req.param('operationId')),\n await parse(c, schemas.reconcileSchema),\n );\n return c.json(op, status(op));\n });\n app.get(\n '/ws',\n upgradeWebSocket((c) =>\n socketHandlers(service, config, c.get('identity'), c.req.query('overview') === '1'),\n ),\n );\n app.all('/api/*', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/api', () => {\n throw new AppError('NOT_FOUND', 'API route not found', 404);\n });\n app.all('/ws/*', () => {\n throw new AppError('NOT_FOUND', 'WebSocket route not found', 404);\n });\n app.use('*', async (c, next) => {\n if (!c.req.path.startsWith('/assets/')) c.header('Cache-Control', 'no-store');\n c.header('X-Content-Type-Options', 'nosniff');\n c.header('Referrer-Policy', 'same-origin');\n c.header(\n 'Content-Security-Policy',\n // Remote Markdown images load directly in the browser, including HTTPS redirects.\n // Keep scripts, connections and all other resource policies restricted as before.\n \"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; connect-src 'self'; frame-ancestors 'none'; base-uri 'none'\",\n );\n await next();\n });\n app.get('*', serveStatic({ root: staticDir }));\n app.get('*', async (c, next) => {\n if (!c.req.header('accept')?.includes('text/html') || /\\.[^/]+$/.test(c.req.path))\n return c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404);\n return serveStatic({ path: `${staticDir}/index.html` })(c, next);\n });\n app.notFound((c) => c.json({ error: { code: 'NOT_FOUND', message: 'Resource not found' } }, 404));\n return app;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/server/service.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ShellService } from "./shell.js";
|
|
1
2
|
import { realpathSync } from "node:fs";
|
|
2
3
|
import { AppError } from "../shared/errors.js";
|
|
3
4
|
import { threadNameError } from "../shared/thread-name.js";
|
|
@@ -24,6 +25,7 @@ class GatewayService {
|
|
|
24
25
|
this.turnUsage = new TurnUsageStore(this.store.database);
|
|
25
26
|
this.projects = options.projects;
|
|
26
27
|
this.codex = options.codex;
|
|
28
|
+
this.shell = new ShellService(this.codex);
|
|
27
29
|
this.events = new EventHub(options.limits?.eventBytes);
|
|
28
30
|
this.projection = new Projection(options.limits?.itemBytes);
|
|
29
31
|
this.currentEpoch = this.codex.epoch;
|
|
@@ -31,6 +33,7 @@ class GatewayService {
|
|
|
31
33
|
this.removeListener = this.codex.onEvent((event) => this.consume(event));
|
|
32
34
|
}
|
|
33
35
|
options;
|
|
36
|
+
shell;
|
|
34
37
|
events;
|
|
35
38
|
projection;
|
|
36
39
|
store;
|
|
@@ -61,6 +64,21 @@ class GatewayService {
|
|
|
61
64
|
listProjects() {
|
|
62
65
|
return this.projects.list();
|
|
63
66
|
}
|
|
67
|
+
startShell(projectId, input) {
|
|
68
|
+
return this.perform("shell.start", projectId, input, async () => {
|
|
69
|
+
this.ensureCompatibilityConfirmed();
|
|
70
|
+
const project = this.projects.get(projectId);
|
|
71
|
+
this.store.dispatch(input.clientOperationId);
|
|
72
|
+
return { result: { shellCommand: this.shell.start(project, input) } };
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
interruptShell(id, input) {
|
|
76
|
+
return this.perform("shell.interrupt", id, input, async () => {
|
|
77
|
+
this.store.dispatch(input.clientOperationId);
|
|
78
|
+
await this.shell.interrupt(id);
|
|
79
|
+
return { result: { interrupted: true } };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
64
82
|
isInMaintenance() {
|
|
65
83
|
return this.maintenance;
|
|
66
84
|
}
|
|
@@ -68,6 +86,7 @@ class GatewayService {
|
|
|
68
86
|
this.maintenance = value;
|
|
69
87
|
}
|
|
70
88
|
prepareUpdate() {
|
|
89
|
+
if (this.shell.active()) return { ready: false, reason: "\u7B49\u5F85 Shell \u547D\u4EE4\u7ED3\u675F" };
|
|
71
90
|
if (this.inFlightOperations.size || this.resumes.size || this.pendingThreadCreations.size)
|
|
72
91
|
return { ready: false, reason: "\u7B49\u5F85\u6B63\u5728\u63D0\u4EA4\u6216\u6062\u590D\u7684\u64CD\u4F5C\u5B8C\u6210" };
|
|
73
92
|
if (this.store.activeMarkers().length || this.store.unresolvedOperations().length)
|
|
@@ -99,7 +118,7 @@ class GatewayService {
|
|
|
99
118
|
const active = this.projection.values().find(
|
|
100
119
|
(thread) => thread.projectId === projectId && (isActive(thread.status) || thread.actions.some((action) => ["pending", "responding"].includes(action.status)))
|
|
101
120
|
);
|
|
102
|
-
if (pending || marker || active)
|
|
121
|
+
if (pending || marker || active || this.shell.active(projectId))
|
|
103
122
|
throw new AppError(
|
|
104
123
|
"PROJECT_BUSY",
|
|
105
124
|
"\u9879\u76EE\u4ECD\u6709\u6D3B\u52A8\u4EFB\u52A1\u6216\u7ED3\u679C\u5F85\u6838\u5BF9\u7684\u64CD\u4F5C\uFF1B\u8BF7\u5148\u7ED3\u675F\u4EFB\u52A1\u5E76\u6838\u5BF9\u65E7\u64CD\u4F5C",
|
|
@@ -380,6 +399,18 @@ class GatewayService {
|
|
|
380
399
|
this.projects.assertOwnership(thread.projectId, thread.cwd);
|
|
381
400
|
return this.threadView(thread);
|
|
382
401
|
}
|
|
402
|
+
async getThreadHistory(threadId, cursor) {
|
|
403
|
+
if (!cursor || cursor.length > 8192)
|
|
404
|
+
throw new AppError("VALIDATION_FAILED", "Missing or invalid history cursor", 400);
|
|
405
|
+
this.ensureReady();
|
|
406
|
+
const metadata = this.normalize(await this.codex.readThreadMetadata(threadId));
|
|
407
|
+
this.projects.assertOwnership(metadata.projectId, metadata.cwd);
|
|
408
|
+
if (!this.codex.readThreadPage)
|
|
409
|
+
throw new AppError("HISTORY_UNAVAILABLE", "\u5F53\u524D Codex \u4E0D\u652F\u6301\u5386\u53F2\u5206\u9875", 409);
|
|
410
|
+
const page = this.normalize(await this.codex.readThreadPage(threadId, cursor));
|
|
411
|
+
this.projects.assertOwnership(page.projectId, page.cwd);
|
|
412
|
+
return page;
|
|
413
|
+
}
|
|
383
414
|
async exportThread(threadId) {
|
|
384
415
|
this.ensureReady();
|
|
385
416
|
const epoch = this.codex.epoch;
|
|
@@ -438,13 +469,16 @@ class GatewayService {
|
|
|
438
469
|
await this.refreshExecution(marker);
|
|
439
470
|
return this.threadView(cached);
|
|
440
471
|
}
|
|
441
|
-
if (cached.status !== "unknown" || !this.codex.ready)
|
|
472
|
+
if ((cached.managed || isActive(cached.status)) && cached.status !== "unknown" || !this.codex.ready)
|
|
473
|
+
return this.threadView(cached);
|
|
442
474
|
}
|
|
443
475
|
const existing = this.reads.get(threadId);
|
|
444
476
|
if (existing) return this.threadView(await existing);
|
|
445
477
|
const revision = this.projection.revision(threadId);
|
|
446
478
|
const loading = (async () => {
|
|
447
|
-
const thread = this.normalize(
|
|
479
|
+
const thread = this.normalize(
|
|
480
|
+
await (this.codex.readThreadPage?.(threadId) ?? this.codex.readThread(threadId))
|
|
481
|
+
);
|
|
448
482
|
const current = this.projection.get(threadId);
|
|
449
483
|
const preserveCurrent = current && (cached === void 0 || this.projection.revision(threadId) !== revision);
|
|
450
484
|
const result = preserveCurrent ? current : this.projection.thread(thread);
|