@alas-ide/codex-acp 2.2.2-alas.3 → 2.2.2-alas.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/dist/index.js +279 -58
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -34392,7 +34392,7 @@ var package_default = {
|
|
|
34392
34392
|
publishConfig: {
|
|
34393
34393
|
access: "public"
|
|
34394
34394
|
},
|
|
34395
|
-
version: "2.2.2-alas.
|
|
34395
|
+
version: "2.2.2-alas.4",
|
|
34396
34396
|
description: "",
|
|
34397
34397
|
main: "dist/index.js",
|
|
34398
34398
|
bin: {
|
|
@@ -34469,7 +34469,7 @@ var package_default = {
|
|
|
34469
34469
|
alasDownstream: {
|
|
34470
34470
|
upstreamVersion: "2.2.2",
|
|
34471
34471
|
upstreamCommit: "202e66e63343ec4f5a5e35ab590251d813d129ca",
|
|
34472
|
-
sourceCommit: "
|
|
34472
|
+
sourceCommit: "4b517e7e77ece05ef63f34c890bc853b7fb96a43"
|
|
34473
34473
|
}
|
|
34474
34474
|
};
|
|
34475
34475
|
|
|
@@ -35186,6 +35186,19 @@ var CodexAcpClient = class _CodexAcpClient {
|
|
|
35186
35186
|
isClientConfiguredProvider(providerId) {
|
|
35187
35187
|
return providerId === CUSTOM_GATEWAY_PROVIDER_ID && this.gatewayConfigSource === "acpProviders";
|
|
35188
35188
|
}
|
|
35189
|
+
/** Provider inputs that can change the routing of a subsequent open or turn. Never returned over ACP. */
|
|
35190
|
+
async hookReviewProviderInputs() {
|
|
35191
|
+
const persisted = (await this.codexClient.configRead({ includeLayers: false })).config;
|
|
35192
|
+
const modelProvider = this.getModelProvider() ?? persisted.model_provider ?? "openai";
|
|
35193
|
+
const selected = (providers) => {
|
|
35194
|
+
if (providers === null || typeof providers !== "object" || Array.isArray(providers)) return {};
|
|
35195
|
+
const value = providers[modelProvider];
|
|
35196
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
35197
|
+
};
|
|
35198
|
+
const merged = this.gatewayConfig?.modelProvider === modelProvider ? this.gatewayConfig.config : { ...selected(persisted["model_providers"]), ...selected(this.config["model_providers"]) };
|
|
35199
|
+
const { name: _name, env_key_instructions: _instructions, ...config2 } = merged;
|
|
35200
|
+
return { modelProvider, config: config2 };
|
|
35201
|
+
}
|
|
35189
35202
|
/**
|
|
35190
35203
|
* The model provider the agent itself is configured with (launch option or
|
|
35191
35204
|
* Codex config), ignoring any ACP-configured gateway routing. The
|
|
@@ -37141,6 +37154,21 @@ var CodexAppServerClient = class {
|
|
|
37141
37154
|
threadLoadsInFlight() {
|
|
37142
37155
|
return [...this.threadLoads.keys()];
|
|
37143
37156
|
}
|
|
37157
|
+
/** Validates a reviewed process/configuration and returns the final synchronous dispatch fence. */
|
|
37158
|
+
hookExecutionGate;
|
|
37159
|
+
dispatchRequest(request) {
|
|
37160
|
+
const activeGoal = request.method === "thread/goal/set" && request.params.status !== "paused";
|
|
37161
|
+
if (this.hookExecutionGate !== void 0 && (activeGoal || ["thread/start", "thread/resume", "thread/fork", "turn/start", "review/start"].includes(request.method))) {
|
|
37162
|
+
return this.dispatchReviewedRequest(request, this.hookExecutionGate);
|
|
37163
|
+
}
|
|
37164
|
+
return request.params ? this.connection.sendRequest(request.method, request.params) : this.connection.sendRequest(request.method);
|
|
37165
|
+
}
|
|
37166
|
+
async dispatchReviewedRequest(request, gate) {
|
|
37167
|
+
const params = request.params;
|
|
37168
|
+
const fence = await gate(params.cwd ?? void 0, params.modelProvider);
|
|
37169
|
+
fence();
|
|
37170
|
+
return await this.connection.sendRequest(request.method, request.params);
|
|
37171
|
+
}
|
|
37144
37172
|
async sendRequest(request) {
|
|
37145
37173
|
for (const callback of this.codexEventHandlers) {
|
|
37146
37174
|
callback({ eventType: "request", ...request });
|
|
@@ -37148,11 +37176,7 @@ var CodexAppServerClient = class {
|
|
|
37148
37176
|
const loadedThreadId = threadLoadOf(request);
|
|
37149
37177
|
let result;
|
|
37150
37178
|
if (loadedThreadId === null) {
|
|
37151
|
-
|
|
37152
|
-
result = await this.connection.sendRequest(request.method, request.params);
|
|
37153
|
-
} else {
|
|
37154
|
-
result = await this.connection.sendRequest(request.method);
|
|
37155
|
-
}
|
|
37179
|
+
result = await this.dispatchRequest(request);
|
|
37156
37180
|
} else {
|
|
37157
37181
|
result = await this.threadLoadGate(loadedThreadId, () => this.sendThreadLoad(loadedThreadId, request));
|
|
37158
37182
|
}
|
|
@@ -37164,7 +37188,7 @@ var CodexAppServerClient = class {
|
|
|
37164
37188
|
async sendThreadLoad(threadId, request) {
|
|
37165
37189
|
this.threadLoads.set(threadId, (this.threadLoads.get(threadId) ?? 0) + 1);
|
|
37166
37190
|
try {
|
|
37167
|
-
return await this.
|
|
37191
|
+
return await this.dispatchRequest(request);
|
|
37168
37192
|
} finally {
|
|
37169
37193
|
const count = (this.threadLoads.get(threadId) ?? 1) - 1;
|
|
37170
37194
|
if (count > 0) this.threadLoads.set(threadId, count);
|
|
@@ -37268,6 +37292,183 @@ async function withHistoryTimeout(page, method, threadId) {
|
|
|
37268
37292
|
}
|
|
37269
37293
|
}
|
|
37270
37294
|
|
|
37295
|
+
// src/CodexHookReview.ts
|
|
37296
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
37297
|
+
import { createHash as createHash2, randomUUID as randomUUID3 } from "node:crypto";
|
|
37298
|
+
|
|
37299
|
+
// src/CodexHookTrust.ts
|
|
37300
|
+
var CODEX_HOOKS_LIST_METHOD = "_codex/hooks/list";
|
|
37301
|
+
var CODEX_HOOKS_TRUST_METHOD = "_codex/hooks/trust";
|
|
37302
|
+
async function listCodexHooks(client, cwd) {
|
|
37303
|
+
const [entry] = (await client.hooksList({ cwds: [cwd] })).data;
|
|
37304
|
+
if (entry === void 0) throw new Error("Codex could not list hooks for the requested directory");
|
|
37305
|
+
return { ...entry, hooks: entry.hooks.filter((hook) => hook.source === "sessionFlags") };
|
|
37306
|
+
}
|
|
37307
|
+
async function trustCodexHooks(client, cwd, requested, beforeWrite, afterReadback) {
|
|
37308
|
+
const isListed = (hooks, request) => hooks.find((hook) => hook.key === request.key && hook.currentHash === request.currentHash);
|
|
37309
|
+
const entry = await listCodexHooks(client, cwd);
|
|
37310
|
+
beforeWrite?.(entry);
|
|
37311
|
+
const current = entry.hooks;
|
|
37312
|
+
const edits = requested.map((request) => {
|
|
37313
|
+
const hook = isListed(current, request);
|
|
37314
|
+
if (hook === void 0) throw new Error("A Codex hook changed before trust was recorded");
|
|
37315
|
+
return hook;
|
|
37316
|
+
}).filter((hook) => hook.trustStatus !== "trusted").map((hook) => ({
|
|
37317
|
+
keyPath: `hooks.state.${JSON.stringify(hook.key)}.trusted_hash`,
|
|
37318
|
+
value: hook.currentHash,
|
|
37319
|
+
mergeStrategy: "replace"
|
|
37320
|
+
}));
|
|
37321
|
+
if (edits.length > 0) {
|
|
37322
|
+
await client.configBatchWrite({ edits, reloadUserConfig: true });
|
|
37323
|
+
}
|
|
37324
|
+
const verified = (await listCodexHooks(client, cwd)).hooks;
|
|
37325
|
+
afterReadback?.();
|
|
37326
|
+
return requested.every((request) => isListed(verified, request)?.trustStatus === "trusted");
|
|
37327
|
+
}
|
|
37328
|
+
|
|
37329
|
+
// src/CodexHookReview.ts
|
|
37330
|
+
var CODEX_HOOK_REVIEW_ERROR = -32044;
|
|
37331
|
+
var CodexHookReviewError = class extends RequestError {
|
|
37332
|
+
constructor(kind) {
|
|
37333
|
+
super(CODEX_HOOK_REVIEW_ERROR, kind === "codex_hook_changed" ? "A Codex hook changed; review the startup hooks again" : "Review the startup hooks for the current Codex process before continuing", { kind });
|
|
37334
|
+
}
|
|
37335
|
+
};
|
|
37336
|
+
var CodexHookReview = class {
|
|
37337
|
+
constructor(client) {
|
|
37338
|
+
this.client = client;
|
|
37339
|
+
}
|
|
37340
|
+
client;
|
|
37341
|
+
enabled = false;
|
|
37342
|
+
revision = 0;
|
|
37343
|
+
reviews = /* @__PURE__ */ new Map();
|
|
37344
|
+
context = new AsyncLocalStorage();
|
|
37345
|
+
configure(capability, air) {
|
|
37346
|
+
this.enabled = !air && typeof capability === "object" && capability !== null && !Array.isArray(capability) && capability.version === 1;
|
|
37347
|
+
this.invalidate();
|
|
37348
|
+
this.bind(this.client());
|
|
37349
|
+
}
|
|
37350
|
+
invalidate() {
|
|
37351
|
+
this.revision++;
|
|
37352
|
+
this.reviews.clear();
|
|
37353
|
+
}
|
|
37354
|
+
bind(client) {
|
|
37355
|
+
client.appServerClient.hookExecutionGate = this.enabled ? async (cwd, provider) => {
|
|
37356
|
+
const context = this.context.getStore();
|
|
37357
|
+
const fail = (error62) => {
|
|
37358
|
+
if (context?.dispatched && error62 instanceof CodexHookReviewError) {
|
|
37359
|
+
throw RequestError.internalError(
|
|
37360
|
+
void 0,
|
|
37361
|
+
"Codex hook review changed after this operation began executing. Review again before sending new work; do not retry the completed work automatically."
|
|
37362
|
+
);
|
|
37363
|
+
}
|
|
37364
|
+
throw error62;
|
|
37365
|
+
};
|
|
37366
|
+
try {
|
|
37367
|
+
if (context === void 0 || cwd !== void 0 && cwd !== context.cwd) throw new CodexHookReviewError("codex_hook_review_required");
|
|
37368
|
+
const fence = await this.validate(client, context.cwd, context.token, provider);
|
|
37369
|
+
return () => {
|
|
37370
|
+
try {
|
|
37371
|
+
fence();
|
|
37372
|
+
} catch (error62) {
|
|
37373
|
+
fail(error62);
|
|
37374
|
+
}
|
|
37375
|
+
context.dispatched = true;
|
|
37376
|
+
};
|
|
37377
|
+
} catch (error62) {
|
|
37378
|
+
return fail(error62);
|
|
37379
|
+
}
|
|
37380
|
+
} : void 0;
|
|
37381
|
+
}
|
|
37382
|
+
run(cwd, meta3, operation) {
|
|
37383
|
+
if (!this.enabled) return operation();
|
|
37384
|
+
const hooks = meta3?.codexHooks;
|
|
37385
|
+
return this.context.run({ cwd, token: hooks?.reviewToken, dispatched: false }, operation);
|
|
37386
|
+
}
|
|
37387
|
+
continueOperation(cwd, meta3, operation) {
|
|
37388
|
+
return this.context.getStore() === void 0 ? this.run(cwd, meta3, operation) : operation();
|
|
37389
|
+
}
|
|
37390
|
+
async list(cwd) {
|
|
37391
|
+
const client = this.client();
|
|
37392
|
+
const revision = this.revision;
|
|
37393
|
+
if (!this.enabled) return await listCodexHooks(client.appServerClient, cwd);
|
|
37394
|
+
const [entry, provider] = await Promise.all([
|
|
37395
|
+
listCodexHooks(client.appServerClient, cwd),
|
|
37396
|
+
client.hookReviewProviderInputs()
|
|
37397
|
+
]);
|
|
37398
|
+
this.assertCurrent(client.appServerClient, revision);
|
|
37399
|
+
const definitions = definitionFingerprint(entry);
|
|
37400
|
+
const providerFingerprint = fingerprint(provider);
|
|
37401
|
+
const previous = this.reviews.get(cwd);
|
|
37402
|
+
const review = previous?.client === client.appServerClient && previous.revision === revision && previous.fingerprint === definitions && previous.providerFingerprint === providerFingerprint ? previous : { cwd, token: randomUUID3(), fingerprint: definitions, revision, client: client.appServerClient, provider: provider.modelProvider, providerFingerprint };
|
|
37403
|
+
this.reviews.set(cwd, review);
|
|
37404
|
+
const home = client.getHomePath();
|
|
37405
|
+
return { ...entry, reviewToken: review.token, ...home === null ? {} : { codexHome: home } };
|
|
37406
|
+
}
|
|
37407
|
+
async trust(cwd, requested, token) {
|
|
37408
|
+
const client = this.client().appServerClient;
|
|
37409
|
+
if (!this.enabled) return await trustCodexHooks(client, cwd, requested);
|
|
37410
|
+
const review = this.requireReview(client, cwd, token);
|
|
37411
|
+
const fence = await this.validate(this.client(), cwd, token);
|
|
37412
|
+
fence();
|
|
37413
|
+
if (requested.length === 0 || new Set(requested.map((hook) => hook.key)).size !== requested.length || requested.some((hook) => !hook.key || !hook.currentHash)) throw new CodexHookReviewError("codex_hook_changed");
|
|
37414
|
+
return await trustCodexHooks(client, cwd, requested, (entry) => {
|
|
37415
|
+
this.checkDefinition(client, review, entry);
|
|
37416
|
+
for (const request of requested) {
|
|
37417
|
+
const matches = entry.hooks.filter((hook) => hook.key === request.key);
|
|
37418
|
+
if (matches.length !== 1 || matches[0].currentHash !== request.currentHash) {
|
|
37419
|
+
throw new CodexHookReviewError("codex_hook_changed");
|
|
37420
|
+
}
|
|
37421
|
+
}
|
|
37422
|
+
}, () => {
|
|
37423
|
+
this.requireReview(client, cwd, token);
|
|
37424
|
+
});
|
|
37425
|
+
}
|
|
37426
|
+
async validate(client, cwd, token, requestedProvider) {
|
|
37427
|
+
const review = this.requireReview(client.appServerClient, cwd, token);
|
|
37428
|
+
const [entry, provider] = await Promise.all([
|
|
37429
|
+
listCodexHooks(client.appServerClient, cwd),
|
|
37430
|
+
client.hookReviewProviderInputs()
|
|
37431
|
+
]);
|
|
37432
|
+
this.checkDefinition(client.appServerClient, review, entry);
|
|
37433
|
+
if (fingerprint(provider) !== review.providerFingerprint || requestedProvider != null && requestedProvider !== review.provider) {
|
|
37434
|
+
throw new CodexHookReviewError("codex_hook_changed");
|
|
37435
|
+
}
|
|
37436
|
+
return () => {
|
|
37437
|
+
this.requireReview(client.appServerClient, cwd, token);
|
|
37438
|
+
};
|
|
37439
|
+
}
|
|
37440
|
+
requireReview(client, cwd, token) {
|
|
37441
|
+
const review = this.reviews.get(cwd);
|
|
37442
|
+
if (review === void 0 || typeof token !== "string" || token !== review.token || review.client !== client) {
|
|
37443
|
+
throw new CodexHookReviewError("codex_hook_review_required");
|
|
37444
|
+
}
|
|
37445
|
+
this.assertCurrent(client, review.revision);
|
|
37446
|
+
return review;
|
|
37447
|
+
}
|
|
37448
|
+
checkDefinition(client, review, entry) {
|
|
37449
|
+
this.requireReview(client, review.cwd, review.token);
|
|
37450
|
+
if (definitionFingerprint(entry) !== review.fingerprint) throw new CodexHookReviewError("codex_hook_changed");
|
|
37451
|
+
}
|
|
37452
|
+
assertCurrent(client, revision) {
|
|
37453
|
+
if (client !== this.client().appServerClient || revision !== this.revision || client.connectionLoss.lost) {
|
|
37454
|
+
throw new CodexHookReviewError("codex_hook_review_required");
|
|
37455
|
+
}
|
|
37456
|
+
}
|
|
37457
|
+
};
|
|
37458
|
+
function definitionFingerprint(entry) {
|
|
37459
|
+
const value = { ...entry, hooks: entry.hooks.map(({ trustStatus: _trust, ...definition }) => definition) };
|
|
37460
|
+
return fingerprint(value);
|
|
37461
|
+
}
|
|
37462
|
+
function fingerprint(value) {
|
|
37463
|
+
return createHash2("sha256").update(JSON.stringify(value, (_key, value2) => {
|
|
37464
|
+
if (typeof value2 === "bigint") return value2.toString();
|
|
37465
|
+
if (value2 !== null && typeof value2 === "object" && !Array.isArray(value2)) {
|
|
37466
|
+
return Object.fromEntries(Object.entries(value2).sort(([a], [b]) => a.localeCompare(b)));
|
|
37467
|
+
}
|
|
37468
|
+
return value2;
|
|
37469
|
+
})).digest("hex");
|
|
37470
|
+
}
|
|
37471
|
+
|
|
37271
37472
|
// src/app-server-recovery/AppServerRecovery.ts
|
|
37272
37473
|
var import_node3 = __toESM(require_main(), 1);
|
|
37273
37474
|
|
|
@@ -37907,7 +38108,7 @@ var AppServerRecovery = class {
|
|
|
37907
38108
|
});
|
|
37908
38109
|
}
|
|
37909
38110
|
resumeError(sessionId, error62, client) {
|
|
37910
|
-
if (isAppServerUnavailableError(error62)) return error62;
|
|
38111
|
+
if (isAppServerUnavailableError(error62) || error62 instanceof CodexHookReviewError) return error62;
|
|
37911
38112
|
const mapped = this.mapError(error62, client);
|
|
37912
38113
|
if (mapped !== error62) return mapped;
|
|
37913
38114
|
if (isMissingRolloutError(error62)) {
|
|
@@ -40020,35 +40221,8 @@ function clientSupportsSubagents(capabilities) {
|
|
|
40020
40221
|
return clientSupportsAirCapability(capabilities, AIR_NATIVE_SUBAGENT_SESSIONS_KEY);
|
|
40021
40222
|
}
|
|
40022
40223
|
|
|
40023
|
-
// src/CodexHookTrust.ts
|
|
40024
|
-
var CODEX_HOOKS_LIST_METHOD = "_codex/hooks/list";
|
|
40025
|
-
var CODEX_HOOKS_TRUST_METHOD = "_codex/hooks/trust";
|
|
40026
|
-
async function listCodexHooks(client, cwd) {
|
|
40027
|
-
const [entry] = (await client.hooksList({ cwds: [cwd] })).data;
|
|
40028
|
-
if (entry === void 0) throw new Error("Codex could not list hooks for the requested directory");
|
|
40029
|
-
return { ...entry, hooks: entry.hooks.filter((hook) => hook.source === "sessionFlags") };
|
|
40030
|
-
}
|
|
40031
|
-
async function trustCodexHooks(client, cwd, requested) {
|
|
40032
|
-
const isListed = (hooks, request) => hooks.find((hook) => hook.key === request.key && hook.currentHash === request.currentHash);
|
|
40033
|
-
const current = (await listCodexHooks(client, cwd)).hooks;
|
|
40034
|
-
const edits = requested.map((request) => {
|
|
40035
|
-
const hook = isListed(current, request);
|
|
40036
|
-
if (hook === void 0) throw new Error("A Codex hook changed before trust was recorded");
|
|
40037
|
-
return hook;
|
|
40038
|
-
}).filter((hook) => hook.trustStatus !== "trusted").map((hook) => ({
|
|
40039
|
-
keyPath: `hooks.state.${JSON.stringify(hook.key)}.trusted_hash`,
|
|
40040
|
-
value: hook.currentHash,
|
|
40041
|
-
mergeStrategy: "replace"
|
|
40042
|
-
}));
|
|
40043
|
-
if (edits.length > 0) {
|
|
40044
|
-
await client.configBatchWrite({ edits, reloadUserConfig: true });
|
|
40045
|
-
}
|
|
40046
|
-
const verified = (await listCodexHooks(client, cwd)).hooks;
|
|
40047
|
-
return requested.every((request) => isListed(verified, request)?.trustStatus === "trusted");
|
|
40048
|
-
}
|
|
40049
|
-
|
|
40050
40224
|
// src/CodexAcpServer.ts
|
|
40051
|
-
import { randomUUID as
|
|
40225
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
40052
40226
|
|
|
40053
40227
|
// src/TitleGenerator.ts
|
|
40054
40228
|
var TITLE_MODEL = "gpt-5.6-luna";
|
|
@@ -40871,7 +41045,7 @@ function remember(cache, key, value) {
|
|
|
40871
41045
|
}
|
|
40872
41046
|
|
|
40873
41047
|
// src/SessionListSubscriptions.ts
|
|
40874
|
-
import { randomUUID as
|
|
41048
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
40875
41049
|
import path12 from "node:path";
|
|
40876
41050
|
|
|
40877
41051
|
// src/CodexHomeWatcher.ts
|
|
@@ -41227,7 +41401,7 @@ var SessionListSubscriptions = class {
|
|
|
41227
41401
|
this.startWatching();
|
|
41228
41402
|
created.ready = this.makeReady(created);
|
|
41229
41403
|
}
|
|
41230
|
-
const subscription = { id:
|
|
41404
|
+
const subscription = { id: randomUUID4(), group, sent: /* @__PURE__ */ new Map(), ready: false, held: null, readyTimer: null, startedSecond: null, epoch: ++this.epoch };
|
|
41231
41405
|
this.subscriptions.set(subscription.id, subscription);
|
|
41232
41406
|
group.subscriptions.add(subscription);
|
|
41233
41407
|
this.startWatching();
|
|
@@ -42486,6 +42660,7 @@ var CodexAcpServer = class {
|
|
|
42486
42660
|
recovery;
|
|
42487
42661
|
initializeRequest = null;
|
|
42488
42662
|
providerUpdate = null;
|
|
42663
|
+
hookReview = new CodexHookReview(() => this.codexAcpClient);
|
|
42489
42664
|
/** The `sessionIndex` extension, for AIR or a client-neutral opt-in, see `SessionIndexService.ts`. */
|
|
42490
42665
|
sessionIndex = new SessionIndexService({
|
|
42491
42666
|
connection: () => this.connection,
|
|
@@ -42533,7 +42708,7 @@ var CodexAcpServer = class {
|
|
|
42533
42708
|
this.captureStderr();
|
|
42534
42709
|
this.getExitCode = getExitCode ?? (() => this.codexProcessState?.connection.process.exitCode ?? null);
|
|
42535
42710
|
this.getRecentStderr = getRecentStderr ?? (() => this.codexProcessState?.stderr ?? "");
|
|
42536
|
-
this.sessionFailureEpoch =
|
|
42711
|
+
this.sessionFailureEpoch = randomUUID5();
|
|
42537
42712
|
this.clientInfo = null;
|
|
42538
42713
|
this.clientCapabilities = null;
|
|
42539
42714
|
this.capabilities = ClientCapabilities.DEFAULT;
|
|
@@ -42562,6 +42737,7 @@ var CodexAcpServer = class {
|
|
|
42562
42737
|
this.reportingConnection.reports.compareMeta = this.capabilities.airClient;
|
|
42563
42738
|
this.booleanConfigOptionsSupported = clientSupportsBooleanConfigOptions(_params.clientCapabilities);
|
|
42564
42739
|
this.sessionIndex.configure(_params.clientCapabilities);
|
|
42740
|
+
this.hookReview.configure(_params.clientCapabilities?._meta?.["codexHooks"], this.capabilities.airClient);
|
|
42565
42741
|
await this.runWithProcessCheck(() => this.codexAcpClient.initialize(_params));
|
|
42566
42742
|
this.sessionIndex.observe(this.codexAcpClient);
|
|
42567
42743
|
this.publishFirstAuthStatusAfterResponse();
|
|
@@ -42621,6 +42797,7 @@ var CodexAcpServer = class {
|
|
|
42621
42797
|
...this.capabilities.asyncTasks && !this.capabilities.airClient ? {
|
|
42622
42798
|
"async-tasks": asyncTaskCapability()
|
|
42623
42799
|
} : {},
|
|
42800
|
+
...this.hookReview.enabled ? { codexHooks: { version: 1, reviewToken: true } } : {},
|
|
42624
42801
|
...neutralSessionIndex ? {
|
|
42625
42802
|
[NEUTRAL_SESSION_INDEX_META_KEY]: neutralSessionIndex
|
|
42626
42803
|
} : {},
|
|
@@ -42653,15 +42830,22 @@ var CodexAcpServer = class {
|
|
|
42653
42830
|
if (this.providerUpdate !== null) await this.waitForProviderUpdate();
|
|
42654
42831
|
const appServer = this.ensureAppServer();
|
|
42655
42832
|
if (appServer) await appServer;
|
|
42656
|
-
return await this.runWithProcessCheck(() =>
|
|
42833
|
+
return await this.runWithProcessCheck(() => this.hookReview.list(cwd));
|
|
42657
42834
|
}
|
|
42658
|
-
async trustHooks(cwd, hooks) {
|
|
42835
|
+
async trustHooks(cwd, hooks, reviewToken) {
|
|
42659
42836
|
if (this.providerUpdate !== null) await this.waitForProviderUpdate();
|
|
42660
42837
|
const appServer = this.ensureAppServer();
|
|
42661
42838
|
if (appServer) await appServer;
|
|
42662
|
-
return { trusted: await this.runWithProcessCheck(() =>
|
|
42839
|
+
return { trusted: await this.runWithProcessCheck(() => this.hookReview.trust(cwd, hooks, reviewToken)) };
|
|
42663
42840
|
}
|
|
42664
42841
|
async extMethod(method, params) {
|
|
42842
|
+
if ((method === GOAL_CONTROL_METHOD || method === LEGACY_GOAL_CONTROL_METHOD) && (params["action"] === "set" || params["action"] === "resume")) {
|
|
42843
|
+
const session = this.sessions.get(params["sessionId"]);
|
|
42844
|
+
if (session !== void 0) return this.hookReview.run(session.cwd, params["_meta"], () => this.extMethodReviewed(method, params));
|
|
42845
|
+
}
|
|
42846
|
+
return this.extMethodReviewed(method, params);
|
|
42847
|
+
}
|
|
42848
|
+
async extMethodReviewed(method, params) {
|
|
42665
42849
|
const methodRequest = { method, params };
|
|
42666
42850
|
if (!isExtMethodRequest(methodRequest)) {
|
|
42667
42851
|
return {};
|
|
@@ -43198,6 +43382,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43198
43382
|
return null;
|
|
43199
43383
|
}
|
|
43200
43384
|
async loadSession(params) {
|
|
43385
|
+
return this.hookReview.run(params.cwd, params._meta, () => this.loadSessionReviewed(params));
|
|
43386
|
+
}
|
|
43387
|
+
async loadSessionReviewed(params) {
|
|
43201
43388
|
readSessionInstructionAppend(params._meta);
|
|
43202
43389
|
return this.recovery === null ? await this.loadSessionOnce(params) : await this.recovery.trackOpen(params.sessionId, () => this.loadSessionOnce(params));
|
|
43203
43390
|
}
|
|
@@ -43241,6 +43428,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43241
43428
|
};
|
|
43242
43429
|
}
|
|
43243
43430
|
async resumeSession(params) {
|
|
43431
|
+
return this.hookReview.run(params.cwd, params._meta, () => this.resumeSessionReviewed(params));
|
|
43432
|
+
}
|
|
43433
|
+
async resumeSessionReviewed(params) {
|
|
43244
43434
|
readSessionInstructionAppend(params._meta);
|
|
43245
43435
|
return this.recovery === null ? await this.resumeSessionOnce(params) : await this.recovery.trackOpen(params.sessionId, () => this.resumeSessionOnce(params));
|
|
43246
43436
|
}
|
|
@@ -43264,6 +43454,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43264
43454
|
};
|
|
43265
43455
|
}
|
|
43266
43456
|
async forkSession(params) {
|
|
43457
|
+
return this.hookReview.run(params.cwd, params._meta, () => this.forkSessionReviewed(params));
|
|
43458
|
+
}
|
|
43459
|
+
async forkSessionReviewed(params) {
|
|
43267
43460
|
readSessionInstructionAppend(params._meta);
|
|
43268
43461
|
if (this.providerUpdate !== null) {
|
|
43269
43462
|
await this.waitForProviderUpdate();
|
|
@@ -43376,6 +43569,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43376
43569
|
return this.sessionOpenGenerations.get(sessionId) === this.getSessionGeneration(sessionId);
|
|
43377
43570
|
}
|
|
43378
43571
|
async newSession(params) {
|
|
43572
|
+
return this.hookReview.run(params.cwd, params._meta, () => this.newSessionReviewed(params));
|
|
43573
|
+
}
|
|
43574
|
+
async newSessionReviewed(params) {
|
|
43379
43575
|
readSessionInstructionAppend(params._meta);
|
|
43380
43576
|
if (this.providerUpdate !== null) {
|
|
43381
43577
|
await this.waitForProviderUpdate();
|
|
@@ -43401,14 +43597,19 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43401
43597
|
const appServer = this.ensureAppServer();
|
|
43402
43598
|
if (appServer) await appServer;
|
|
43403
43599
|
const elicitationRequester = this.createUrlElicitationRequester(requestId);
|
|
43404
|
-
|
|
43405
|
-
|
|
43406
|
-
|
|
43407
|
-
|
|
43600
|
+
this.hookReview.invalidate();
|
|
43601
|
+
try {
|
|
43602
|
+
const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(_params, elicitationRequester));
|
|
43603
|
+
if (!isAuthenticated) {
|
|
43604
|
+
logger.log("Authenticate request failed");
|
|
43605
|
+
throw RequestError.authRequired({ methodId: _params.methodId }, "Sign-in did not complete");
|
|
43606
|
+
}
|
|
43607
|
+
await this.refreshAuthState(this.getAuthProviderForAuthenticateRequest(_params));
|
|
43608
|
+
logger.log("Authenticate request completed");
|
|
43609
|
+
return {};
|
|
43610
|
+
} finally {
|
|
43611
|
+
this.hookReview.invalidate();
|
|
43408
43612
|
}
|
|
43409
|
-
await this.refreshAuthState(this.getAuthProviderForAuthenticateRequest(_params));
|
|
43410
|
-
logger.log("Authenticate request completed");
|
|
43411
|
-
return {};
|
|
43412
43613
|
}
|
|
43413
43614
|
createUrlElicitationRequester(requestId) {
|
|
43414
43615
|
if (requestId == null || !clientSupportsUrlElicitation(this.clientCapabilities)) {
|
|
@@ -43447,11 +43648,13 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43447
43648
|
}
|
|
43448
43649
|
async setProvider(params) {
|
|
43449
43650
|
this.codexAcpClient.setProvider(params);
|
|
43651
|
+
this.hookReview.invalidate();
|
|
43450
43652
|
await this.enqueueProviderUpdate((client) => client.setProvider(params));
|
|
43451
43653
|
return {};
|
|
43452
43654
|
}
|
|
43453
43655
|
async disableProvider(params) {
|
|
43454
43656
|
this.codexAcpClient.disableProvider(params);
|
|
43657
|
+
if (params.providerId === OPENAI_PROVIDER_ID) this.hookReview.invalidate();
|
|
43455
43658
|
if (params.providerId !== OPENAI_PROVIDER_ID) {
|
|
43456
43659
|
return {};
|
|
43457
43660
|
}
|
|
@@ -43480,6 +43683,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43480
43683
|
throw new Error("Cannot restart Codex app-server before ACP initialization");
|
|
43481
43684
|
}
|
|
43482
43685
|
await replacement.initialize(this.initializeRequest);
|
|
43686
|
+
this.hookReview.bind(replacement);
|
|
43483
43687
|
this.codexAcpClient = replacement;
|
|
43484
43688
|
this.sessionIndex.observe(replacement);
|
|
43485
43689
|
this.availableCommands = this.createAvailableCommands(replacement);
|
|
@@ -43492,6 +43696,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43492
43696
|
if (replacement.appServerClient.connectionLoss.lost) {
|
|
43493
43697
|
break;
|
|
43494
43698
|
}
|
|
43699
|
+
if (this.hookReview.enabled) continue;
|
|
43495
43700
|
try {
|
|
43496
43701
|
const request = {
|
|
43497
43702
|
sessionId: session.sessionId,
|
|
@@ -43594,7 +43799,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43594
43799
|
currentClient: () => this.codexAcpClient,
|
|
43595
43800
|
createClient: (connection) => {
|
|
43596
43801
|
this.captureStderr();
|
|
43597
|
-
|
|
43802
|
+
const client = this.codexAcpClient.withAppServer(new CodexAppServerClient(connection.connection));
|
|
43803
|
+
this.hookReview.bind(client);
|
|
43804
|
+
return client;
|
|
43598
43805
|
},
|
|
43599
43806
|
handshake: (client) => this.initializeRequest !== null && this.codexAcpClient.initialized ? client.initialize(this.initializeRequest) : null,
|
|
43600
43807
|
install: (client) => this.installCodexClient(client),
|
|
@@ -43626,6 +43833,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
43626
43833
|
installCodexClient(client) {
|
|
43627
43834
|
client.adoptRoutingFrom(this.codexAcpClient);
|
|
43628
43835
|
this.codexAcpClient = client;
|
|
43836
|
+
this.hookReview.bind(client);
|
|
43629
43837
|
this.sessionIndex.observe(client);
|
|
43630
43838
|
this.availableCommands = this.createAvailableCommands(client);
|
|
43631
43839
|
for (const session of this.sessions.values()) {
|
|
@@ -44161,11 +44369,15 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
44161
44369
|
}
|
|
44162
44370
|
return await new Promise((resolve, reject) => {
|
|
44163
44371
|
let turnStarted = false;
|
|
44164
|
-
const promptDone = this.
|
|
44165
|
-
|
|
44166
|
-
|
|
44167
|
-
|
|
44168
|
-
|
|
44372
|
+
const promptDone = this.hookReview.continueOperation(
|
|
44373
|
+
this.getSessionState(params.sessionId).cwd,
|
|
44374
|
+
params._meta,
|
|
44375
|
+
() => this.promptReviewed(params, void 0, () => {
|
|
44376
|
+
turnStarted = true;
|
|
44377
|
+
logger.log(`${source} started a new turn`, { sessionId: params.sessionId });
|
|
44378
|
+
resolve(true);
|
|
44379
|
+
})
|
|
44380
|
+
);
|
|
44169
44381
|
promptDone.then(
|
|
44170
44382
|
(response) => {
|
|
44171
44383
|
if (!turnStarted && response.stopReason === "cancelled") {
|
|
@@ -44220,7 +44432,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
44220
44432
|
}
|
|
44221
44433
|
return {
|
|
44222
44434
|
sessionId,
|
|
44223
|
-
prompt
|
|
44435
|
+
prompt,
|
|
44436
|
+
...params["_meta"] === void 0 ? {} : { _meta: params["_meta"] }
|
|
44224
44437
|
};
|
|
44225
44438
|
}
|
|
44226
44439
|
createSessionConfigOptions(sessionState) {
|
|
@@ -45016,6 +45229,13 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
45016
45229
|
return turnId;
|
|
45017
45230
|
}
|
|
45018
45231
|
async prompt(params, signal, onTurnStarted) {
|
|
45232
|
+
return this.hookReview.run(
|
|
45233
|
+
this.getSessionState(params.sessionId).cwd,
|
|
45234
|
+
params._meta,
|
|
45235
|
+
() => this.promptReviewed(params, signal, onTurnStarted)
|
|
45236
|
+
);
|
|
45237
|
+
}
|
|
45238
|
+
async promptReviewed(params, signal, onTurnStarted) {
|
|
45019
45239
|
if (this.providerUpdate !== null) {
|
|
45020
45240
|
await this.waitForProviderUpdate();
|
|
45021
45241
|
}
|
|
@@ -45857,6 +46077,7 @@ var asyncTaskStopParamsParser = external_exports.object({
|
|
|
45857
46077
|
}).passthrough();
|
|
45858
46078
|
var hooksListParamsParser = external_exports.object({ cwd: external_exports.string().trim().min(1) });
|
|
45859
46079
|
var hooksTrustParamsParser = external_exports.object({
|
|
46080
|
+
reviewToken: external_exports.string().min(1).optional(),
|
|
45860
46081
|
cwd: external_exports.string().trim().min(1),
|
|
45861
46082
|
hooks: external_exports.array(external_exports.object({ key: external_exports.string().min(1), currentHash: external_exports.string().min(1) })).min(1)
|
|
45862
46083
|
});
|
|
@@ -45940,5 +46161,5 @@ function startAcpServer() {
|
|
|
45940
46161
|
codexAcpServer = null;
|
|
45941
46162
|
}
|
|
45942
46163
|
});
|
|
45943
|
-
}).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.fork, (ctx) => getAgent().forkSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params, ctx.requestId)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => getAgent().listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => getAgent().setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => getAgent().disableProvider(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).onRequest(SESSION_STEERING_METHOD, sessionSteerParamsParser, (ctx) => getAgent().extMethod(SESSION_STEERING_METHOD, ctx.params)).onRequest(ASYNC_TASK_STOP_METHOD, asyncTaskStopParamsParser, (ctx) => getAgent().extMethod(ASYNC_TASK_STOP_METHOD, ctx.params)).onRequest(CODEX_HOOKS_LIST_METHOD, hooksListParamsParser, (ctx) => getAgent().listHooks(ctx.params.cwd)).onRequest(CODEX_HOOKS_TRUST_METHOD, hooksTrustParamsParser, (ctx) => getAgent().trustHooks(ctx.params.cwd, ctx.params.hooks)).onRequest(GOAL_CONTROL_METHOD, goalControlParamsParser, (ctx) => getAgent().extMethod(GOAL_CONTROL_METHOD, ctx.params)).onRequest(SESSION_RENAME_METHOD, sessionRenameParamsParser, (ctx) => getAgent().sessionIndex.rename(ctx.params)).onRequest(SESSION_ARCHIVE_METHOD, sessionArchiveParamsParser, (ctx) => getAgent().sessionIndex.setArchived(ctx.params, true)).onRequest(SESSION_UNARCHIVE_METHOD, sessionArchiveParamsParser, (ctx) => getAgent().sessionIndex.setArchived(ctx.params, false)).onRequest(SESSION_LIST_SUBSCRIBE_METHOD, sessionListSubscriptionParamsParser, (ctx) => getAgent().sessionIndex.subscribeList(ctx.params)).onRequest(SESSION_LIST_UNSUBSCRIBE_METHOD, sessionListSubscriptionParamsParser, (ctx) => getAgent().sessionIndex.unsubscribeList(ctx.params)).connect(acpJsonStream);
|
|
46164
|
+
}).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.fork, (ctx) => getAgent().forkSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params, ctx.requestId)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => getAgent().listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => getAgent().setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => getAgent().disableProvider(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).onRequest(SESSION_STEERING_METHOD, sessionSteerParamsParser, (ctx) => getAgent().extMethod(SESSION_STEERING_METHOD, ctx.params)).onRequest(ASYNC_TASK_STOP_METHOD, asyncTaskStopParamsParser, (ctx) => getAgent().extMethod(ASYNC_TASK_STOP_METHOD, ctx.params)).onRequest(CODEX_HOOKS_LIST_METHOD, hooksListParamsParser, (ctx) => getAgent().listHooks(ctx.params.cwd)).onRequest(CODEX_HOOKS_TRUST_METHOD, hooksTrustParamsParser, (ctx) => getAgent().trustHooks(ctx.params.cwd, ctx.params.hooks, ctx.params.reviewToken)).onRequest(GOAL_CONTROL_METHOD, goalControlParamsParser, (ctx) => getAgent().extMethod(GOAL_CONTROL_METHOD, ctx.params)).onRequest(SESSION_RENAME_METHOD, sessionRenameParamsParser, (ctx) => getAgent().sessionIndex.rename(ctx.params)).onRequest(SESSION_ARCHIVE_METHOD, sessionArchiveParamsParser, (ctx) => getAgent().sessionIndex.setArchived(ctx.params, true)).onRequest(SESSION_UNARCHIVE_METHOD, sessionArchiveParamsParser, (ctx) => getAgent().sessionIndex.setArchived(ctx.params, false)).onRequest(SESSION_LIST_SUBSCRIBE_METHOD, sessionListSubscriptionParamsParser, (ctx) => getAgent().sessionIndex.subscribeList(ctx.params)).onRequest(SESSION_LIST_UNSUBSCRIBE_METHOD, sessionListSubscriptionParamsParser, (ctx) => getAgent().sessionIndex.unsubscribeList(ctx.params)).connect(acpJsonStream);
|
|
45944
46165
|
}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "2.2.2-alas.
|
|
6
|
+
"version": "2.2.2-alas.4",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"bin": {
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
"alasDownstream": {
|
|
81
81
|
"upstreamVersion": "2.2.2",
|
|
82
82
|
"upstreamCommit": "202e66e63343ec4f5a5e35ab590251d813d129ca",
|
|
83
|
-
"sourceCommit": "
|
|
83
|
+
"sourceCommit": "4b517e7e77ece05ef63f34c890bc853b7fb96a43"
|
|
84
84
|
}
|
|
85
85
|
}
|