orkestrator 2.26.0-alpha → 2.26.1-alpha
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/client.js +156 -31
- package/dist/main.js +42146 -41106
- package/package.json +3 -3
- package/resources/claude-bridge/dist/index.js +40 -2
- package/resources/codex-bridge/dist/index.js +216 -73
|
@@ -3984,11 +3984,6 @@ var LEGACY_ENABLED_AGENT_PLATFORMS = Object.freeze([
|
|
|
3984
3984
|
// ../protocol/src/native-agent-transcript-patch.ts
|
|
3985
3985
|
var FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
3986
3986
|
|
|
3987
|
-
// ../protocol/src/native-agent-policy-effects.ts
|
|
3988
|
-
function appendNativeAgentPolicyNote(policy, note) {
|
|
3989
|
-
return { ...policy, note: policy.note ? `${policy.note} ${note}` : note };
|
|
3990
|
-
}
|
|
3991
|
-
|
|
3992
3987
|
// ../protocol/src/native-agent-steer-rejection.ts
|
|
3993
3988
|
var MAX_STEER_JOURNAL_BYTES = 1024 * 1024 * 1024;
|
|
3994
3989
|
// ../protocol/src/native-agent.ts
|
|
@@ -17200,7 +17195,7 @@ function reduceHistoricalTurns(turns, generation, threadId, handle) {
|
|
|
17200
17195
|
return { events, unsupportedItemTypes };
|
|
17201
17196
|
}
|
|
17202
17197
|
|
|
17203
|
-
//
|
|
17198
|
+
// ../protocol/src/secret-redaction.ts
|
|
17204
17199
|
var TEXT_RULES = [
|
|
17205
17200
|
{
|
|
17206
17201
|
pattern: /([a-z][a-z0-9+.-]*:\/\/)[^/\s:@]+(?::[^/\s@]*)?@/gi,
|
|
@@ -18023,6 +18018,7 @@ function coordinatorCapabilityPolicy(mode) {
|
|
|
18023
18018
|
}
|
|
18024
18019
|
|
|
18025
18020
|
// ../../bridges/codex-bridge/src/codex-config.ts
|
|
18021
|
+
import { realpathSync } from "node:fs";
|
|
18026
18022
|
import { isAbsolute as isAbsolute5 } from "node:path";
|
|
18027
18023
|
var CODEX_MAX_CONCURRENT_THREADS_ENV = "CODEX_MAX_CONCURRENT_THREADS_PER_SESSION";
|
|
18028
18024
|
var DEFAULT_CODEX_MAX_CONCURRENT_THREADS = 5;
|
|
@@ -18042,6 +18038,43 @@ function codexNetworkDeniedConfig(policy) {
|
|
|
18042
18038
|
"features.standalone_web_search": false
|
|
18043
18039
|
};
|
|
18044
18040
|
}
|
|
18041
|
+
function codexProjectTrustConfig(policy, cwd) {
|
|
18042
|
+
if (!policy || policy.projectResources || !cwd || !isAbsolute5(cwd))
|
|
18043
|
+
return {};
|
|
18044
|
+
const roots = new Set([cwd]);
|
|
18045
|
+
try {
|
|
18046
|
+
roots.add(realpathSync(cwd));
|
|
18047
|
+
} catch {}
|
|
18048
|
+
return {
|
|
18049
|
+
projects: Object.fromEntries([...roots].map((root) => [root, { trust_level: "untrusted" }]))
|
|
18050
|
+
};
|
|
18051
|
+
}
|
|
18052
|
+
var MAX_CODEX_DISABLED_SKILLS = 1024;
|
|
18053
|
+
var KEPT_SKILL_SCOPES = new Set(["user", "system", "admin"]);
|
|
18054
|
+
function codexProjectSkillsConfig(listed) {
|
|
18055
|
+
const data = listed && typeof listed === "object" && Array.isArray(listed.data) ? listed.data : undefined;
|
|
18056
|
+
if (!data)
|
|
18057
|
+
throw new Error("Codex skills/list returned no skill inventory");
|
|
18058
|
+
const disabled = new Set;
|
|
18059
|
+
for (const entry of data) {
|
|
18060
|
+
const skills = entry?.skills;
|
|
18061
|
+
for (const skill of Array.isArray(skills) ? skills : []) {
|
|
18062
|
+
const { path, scope, enabled } = skill ?? {};
|
|
18063
|
+
if (enabled === true && typeof scope === "string" && KEPT_SKILL_SCOPES.has(scope))
|
|
18064
|
+
continue;
|
|
18065
|
+
if (typeof path !== "string" || !isAbsolute5(path)) {
|
|
18066
|
+
throw new Error("Codex listed a project skill without a path it can be disabled by");
|
|
18067
|
+
}
|
|
18068
|
+
disabled.add(path);
|
|
18069
|
+
}
|
|
18070
|
+
}
|
|
18071
|
+
if (disabled.size > MAX_CODEX_DISABLED_SKILLS) {
|
|
18072
|
+
throw new Error(`Codex listed more than ${MAX_CODEX_DISABLED_SKILLS} skills to disable`);
|
|
18073
|
+
}
|
|
18074
|
+
if (disabled.size === 0)
|
|
18075
|
+
return {};
|
|
18076
|
+
return { skills: { config: [...disabled].map((path) => ({ path, enabled: false })) } };
|
|
18077
|
+
}
|
|
18045
18078
|
var READ_ONLY_TURN_FALLBACK_POLICY = Object.freeze({
|
|
18046
18079
|
id: "interactive-host",
|
|
18047
18080
|
sandbox: "provider",
|
|
@@ -18537,6 +18570,8 @@ function mcpFailureReason(notice) {
|
|
|
18537
18570
|
return reason || undefined;
|
|
18538
18571
|
}
|
|
18539
18572
|
var MAX_SKILL_LOAD_NOTICES = 16;
|
|
18573
|
+
var MCP_STATUS_PAGE_SIZE = 100;
|
|
18574
|
+
var MCP_STATUS_MAX_PAGES = 10;
|
|
18540
18575
|
function skillPathFingerprint(path) {
|
|
18541
18576
|
let hash = 2166136261;
|
|
18542
18577
|
for (let index = 0;index < path.length; index += 1) {
|
|
@@ -19063,10 +19098,30 @@ class AppServerEngine {
|
|
|
19063
19098
|
}
|
|
19064
19099
|
throw new Error("Codex model catalogue exceeded its page limit");
|
|
19065
19100
|
}
|
|
19066
|
-
|
|
19101
|
+
async projectResourceThreadConfig(generation, config) {
|
|
19102
|
+
if (!config.policy || config.policy.projectResources)
|
|
19103
|
+
return {};
|
|
19104
|
+
let listed;
|
|
19105
|
+
try {
|
|
19106
|
+
listed = await this.supervisor.requestOnGeneration(generation, "skills/list", {
|
|
19107
|
+
cwds: [config.cwd ?? this.options.cwd],
|
|
19108
|
+
forceReload: true
|
|
19109
|
+
});
|
|
19110
|
+
} catch (error) {
|
|
19111
|
+
if (error instanceof AppServerRpcError && error.code === JSON_RPC_METHOD_NOT_FOUND) {
|
|
19112
|
+
throw new Error("Codex cannot enforce disabled project resources without skills/list");
|
|
19113
|
+
}
|
|
19114
|
+
throw error;
|
|
19115
|
+
}
|
|
19116
|
+
return codexProjectSkillsConfig(listed);
|
|
19117
|
+
}
|
|
19118
|
+
toThreadParams(config, extraConfig = {}) {
|
|
19067
19119
|
const approveAgentMcpTools = config.policy?.approvals === "auto-approve" && (config.approvalPolicy ?? "never") === "never" && config.sandbox !== "read-only" || config.policy?.id === "coordinator-read-only" && Boolean(config.permissionProfile) || Boolean(config.workflowResultTool && config.agentMcp);
|
|
19120
|
+
const cwd = config.cwd ?? this.options.cwd;
|
|
19068
19121
|
const threadConfig = {
|
|
19069
19122
|
...codexNetworkDeniedConfig(config.policy),
|
|
19123
|
+
...codexProjectTrustConfig(config.policy, cwd),
|
|
19124
|
+
...extraConfig,
|
|
19070
19125
|
...config.agentMcp ? {
|
|
19071
19126
|
...config.agentMcp.design ? {
|
|
19072
19127
|
"mcp_servers.orkestrator-design": {
|
|
@@ -19095,7 +19150,7 @@ class AppServerEngine {
|
|
|
19095
19150
|
} : {}
|
|
19096
19151
|
};
|
|
19097
19152
|
return {
|
|
19098
|
-
cwd
|
|
19153
|
+
cwd,
|
|
19099
19154
|
approvalPolicy: config.approvalPolicy ?? "never",
|
|
19100
19155
|
approvalsReviewer: config.approvalsReviewer ?? "user",
|
|
19101
19156
|
...config.permissionProfile ? {} : {
|
|
@@ -19126,13 +19181,15 @@ class AppServerEngine {
|
|
|
19126
19181
|
}
|
|
19127
19182
|
async startThread(options) {
|
|
19128
19183
|
const generation = await this.assertHostedNetworkLock(options.config);
|
|
19129
|
-
const
|
|
19184
|
+
const extra = await this.projectResourceThreadConfig(generation, options.config);
|
|
19185
|
+
const response = await this.supervisor.requestOnGeneration(generation, "thread/start", this.toThreadParams(options.config, extra));
|
|
19130
19186
|
this.assertPermissionProfile(response.activePermissionProfile, options.config);
|
|
19131
19187
|
return this.bindThread(response.thread, options.config, response.model);
|
|
19132
19188
|
}
|
|
19133
19189
|
async resumeThread(threadId, options) {
|
|
19134
19190
|
const generation = await this.assertHostedNetworkLock(options.config);
|
|
19135
|
-
const
|
|
19191
|
+
const extra = await this.projectResourceThreadConfig(generation, options.config);
|
|
19192
|
+
const response = await this.supervisor.requestOnGeneration(generation, "thread/resume", { threadId, ...this.toThreadParams(options.config, extra) });
|
|
19136
19193
|
this.assertPermissionProfile(response.activePermissionProfile, options.config);
|
|
19137
19194
|
const thread = this.bindThread(response.thread, options.config, response.model);
|
|
19138
19195
|
thread.turns = this.extractTurns(response.thread);
|
|
@@ -19150,10 +19207,11 @@ class AppServerEngine {
|
|
|
19150
19207
|
}
|
|
19151
19208
|
async forkThread(threadId, config, lastTurnId) {
|
|
19152
19209
|
const generation = await this.assertHostedNetworkLock(config);
|
|
19210
|
+
const extra = await this.projectResourceThreadConfig(generation, config);
|
|
19153
19211
|
const response = await this.supervisor.requestOnGeneration(generation, "thread/fork", {
|
|
19154
19212
|
threadId,
|
|
19155
19213
|
...lastTurnId ? { lastTurnId } : {},
|
|
19156
|
-
...this.toThreadParams(config)
|
|
19214
|
+
...this.toThreadParams(config, extra)
|
|
19157
19215
|
});
|
|
19158
19216
|
this.assertPermissionProfile(response.activePermissionProfile, config);
|
|
19159
19217
|
return this.bindThread(response.thread, config, response.model);
|
|
@@ -19193,11 +19251,7 @@ class AppServerEngine {
|
|
|
19193
19251
|
}
|
|
19194
19252
|
async getRuntimeHealth(threadId) {
|
|
19195
19253
|
const [mcp, skills, hooks, rateLimits] = await Promise.allSettled([
|
|
19196
|
-
this.
|
|
19197
|
-
limit: 100,
|
|
19198
|
-
detail: "full",
|
|
19199
|
-
...threadId ? { threadId } : {}
|
|
19200
|
-
}),
|
|
19254
|
+
this.listMcpServerStatus(threadId),
|
|
19201
19255
|
this.supervisor.request("skills/list", {
|
|
19202
19256
|
cwds: [this.options.cwd]
|
|
19203
19257
|
}),
|
|
@@ -19260,12 +19314,29 @@ class AppServerEngine {
|
|
|
19260
19314
|
rateLimits: allowlistRateLimits(rateLimitValue)
|
|
19261
19315
|
};
|
|
19262
19316
|
}
|
|
19317
|
+
async listMcpServerStatus(threadId) {
|
|
19318
|
+
const data = [];
|
|
19319
|
+
let cursor;
|
|
19320
|
+
let last = {};
|
|
19321
|
+
for (let page = 0;page < MCP_STATUS_MAX_PAGES; page += 1) {
|
|
19322
|
+
const response = await this.supervisor.request("mcpServerStatus/list", {
|
|
19323
|
+
...cursor ? { cursor } : {},
|
|
19324
|
+
limit: MCP_STATUS_PAGE_SIZE,
|
|
19325
|
+
detail: "full",
|
|
19326
|
+
...threadId ? { threadId } : {}
|
|
19327
|
+
});
|
|
19328
|
+
last = objectRecord(response);
|
|
19329
|
+
if (!Array.isArray(last.data))
|
|
19330
|
+
return page === 0 ? response : { ...last, data };
|
|
19331
|
+
data.push(...last.data);
|
|
19332
|
+
cursor = typeof last.nextCursor === "string" && last.nextCursor ? last.nextCursor : undefined;
|
|
19333
|
+
if (!cursor)
|
|
19334
|
+
break;
|
|
19335
|
+
}
|
|
19336
|
+
return { ...last, data };
|
|
19337
|
+
}
|
|
19263
19338
|
async listMcpServers(threadId) {
|
|
19264
|
-
const response = await this.
|
|
19265
|
-
limit: 100,
|
|
19266
|
-
detail: "full",
|
|
19267
|
-
...threadId ? { threadId } : {}
|
|
19268
|
-
});
|
|
19339
|
+
const response = await this.listMcpServerStatus(threadId);
|
|
19269
19340
|
const root = objectRecord(response);
|
|
19270
19341
|
if (!Array.isArray(root.data))
|
|
19271
19342
|
return response;
|
|
@@ -19489,18 +19560,24 @@ class AppServerEngine {
|
|
|
19489
19560
|
rolloutPath(threadId) {
|
|
19490
19561
|
return this.rolloutPaths.get(threadId);
|
|
19491
19562
|
}
|
|
19492
|
-
async unsubscribeThread(handle) {
|
|
19563
|
+
async unsubscribeThread(handle, requireConfirmation = false) {
|
|
19493
19564
|
const binding = this.bindings.get(handle);
|
|
19494
|
-
|
|
19495
|
-
|
|
19496
|
-
|
|
19497
|
-
|
|
19565
|
+
const threadId = binding?.threadId ?? handle;
|
|
19566
|
+
if (!binding && !requireConfirmation) {
|
|
19567
|
+
this.accountProofTurns.delete(threadId);
|
|
19568
|
+
this.rolloutPaths.delete(threadId);
|
|
19498
19569
|
return;
|
|
19570
|
+
}
|
|
19499
19571
|
try {
|
|
19500
|
-
await this.supervisor.request("thread/unsubscribe", { threadId
|
|
19572
|
+
await this.supervisor.request("thread/unsubscribe", { threadId });
|
|
19501
19573
|
} catch (error) {
|
|
19574
|
+
if (requireConfirmation)
|
|
19575
|
+
throw error;
|
|
19502
19576
|
console.warn("[codex-bridge] thread/unsubscribe failed:", error instanceof Error ? error.message : error);
|
|
19503
19577
|
}
|
|
19578
|
+
this.accountProofTurns.delete(threadId);
|
|
19579
|
+
this.rolloutPaths.delete(threadId);
|
|
19580
|
+
this.bindings.delete(handle);
|
|
19504
19581
|
}
|
|
19505
19582
|
async configureThread(handle, config) {
|
|
19506
19583
|
const binding = this.bindings.get(handle);
|
|
@@ -20013,14 +20090,6 @@ class ThreadRegistry {
|
|
|
20013
20090
|
}
|
|
20014
20091
|
}
|
|
20015
20092
|
|
|
20016
|
-
// ../../bridges/codex-bridge/src/codex-reported-policy.ts
|
|
20017
|
-
var CODEX_PROJECT_TRUST_NOTE = "Codex loads a trusted project's own configuration, including its MCP servers and hooks, whatever this session's policy says.";
|
|
20018
|
-
function codexReportedPolicy(policy) {
|
|
20019
|
-
if (policy.projectResources || policy.id === "coordinator-read-only")
|
|
20020
|
-
return policy;
|
|
20021
|
-
return appendNativeAgentPolicyNote({ ...policy, projectResources: true }, CODEX_PROJECT_TRUST_NOTE);
|
|
20022
|
-
}
|
|
20023
|
-
|
|
20024
20093
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
20025
20094
|
var SESSION_CLOSING_ERROR = "Session is closing";
|
|
20026
20095
|
|
|
@@ -20720,14 +20789,25 @@ class CodexRuntimeSessions {
|
|
|
20720
20789
|
if (requestedModelChanged)
|
|
20721
20790
|
attached.modelId = undefined;
|
|
20722
20791
|
await this.ctx.options.engine.configureThread(attached.engineHandle, nextConfig);
|
|
20792
|
+
if (session.config.policy?.projectResources !== nextConfig.policy?.projectResources || (session.config.cwd ?? this.ctx.options.cwd) !== (nextConfig.cwd ?? this.ctx.options.cwd)) {
|
|
20793
|
+
await this.lifecycle.detachThread(attached, true);
|
|
20794
|
+
}
|
|
20723
20795
|
}
|
|
20724
20796
|
} catch (error) {
|
|
20797
|
+
if (attached) {
|
|
20798
|
+
await this.ctx.options.engine.configureThread(attached.engineHandle, session.config).catch(() => {
|
|
20799
|
+
return;
|
|
20800
|
+
});
|
|
20801
|
+
}
|
|
20725
20802
|
if (attached && requestedModelChanged) {
|
|
20726
20803
|
attached.modelId = previousConfirmedModel;
|
|
20727
20804
|
}
|
|
20728
20805
|
console.warn(`[codex-bridge] Could not apply configuration for session ${sessionId}:`, error instanceof Error ? error.message : error);
|
|
20729
20806
|
return "unavailable";
|
|
20730
20807
|
}
|
|
20808
|
+
if (session.config.policy?.projectResources !== nextConfig.policy?.projectResources) {
|
|
20809
|
+
this.ctx.commandCatalogue.markPolicyChanged();
|
|
20810
|
+
}
|
|
20731
20811
|
session.config = nextConfig;
|
|
20732
20812
|
session.configurationRevision += 1;
|
|
20733
20813
|
this.ctx.registry.touch(sessionId);
|
|
@@ -20818,7 +20898,7 @@ class CodexRuntimeSessions {
|
|
|
20818
20898
|
const error = context?.error ?? (phase === "failed" && session.restartFailure ? CODEX_RESTARTED_MID_TURN_MESSAGE : undefined);
|
|
20819
20899
|
return {
|
|
20820
20900
|
status: phaseToExternalStatus(phase),
|
|
20821
|
-
...session.config.policy ? { policy:
|
|
20901
|
+
...session.config.policy ? { policy: session.config.policy } : {},
|
|
20822
20902
|
phase,
|
|
20823
20903
|
title: session.title,
|
|
20824
20904
|
error,
|
|
@@ -21003,7 +21083,7 @@ class CodexRuntimeSessions {
|
|
|
21003
21083
|
...session.config.reasoningEffort ? { modelReasoningEffort: session.config.reasoningEffort } : {},
|
|
21004
21084
|
mode: session.config.mode,
|
|
21005
21085
|
fastMode: session.config.serviceTier === "fast",
|
|
21006
|
-
...session.config.policy ? { policy:
|
|
21086
|
+
...session.config.policy ? { policy: session.config.policy } : {},
|
|
21007
21087
|
durable: await this.isSessionConfigPersisted(session)
|
|
21008
21088
|
};
|
|
21009
21089
|
}
|
|
@@ -21855,7 +21935,13 @@ function normalizeSkillsList(raw, context) {
|
|
|
21855
21935
|
fetchedAt: context.now
|
|
21856
21936
|
};
|
|
21857
21937
|
}
|
|
21858
|
-
function skillUnavailability(binding) {
|
|
21938
|
+
function skillUnavailability(binding, projectResources = true) {
|
|
21939
|
+
if (!projectResources && !["user", "system", "admin"].includes(binding.scope)) {
|
|
21940
|
+
return {
|
|
21941
|
+
reason: "disabled",
|
|
21942
|
+
message: "This skill is disabled because project resources are off for this session."
|
|
21943
|
+
};
|
|
21944
|
+
}
|
|
21859
21945
|
if (!binding.enabled) {
|
|
21860
21946
|
return {
|
|
21861
21947
|
reason: "disabled",
|
|
@@ -21870,8 +21956,8 @@ function skillUnavailability(binding) {
|
|
|
21870
21956
|
}
|
|
21871
21957
|
return;
|
|
21872
21958
|
}
|
|
21873
|
-
function skillCommandRow(binding) {
|
|
21874
|
-
const unavailable = skillUnavailability(binding);
|
|
21959
|
+
function skillCommandRow(binding, projectResources = true) {
|
|
21960
|
+
const unavailable = skillUnavailability(binding, projectResources);
|
|
21875
21961
|
return {
|
|
21876
21962
|
name: `$${binding.name}`,
|
|
21877
21963
|
insertText: `$${binding.name}`,
|
|
@@ -22065,7 +22151,10 @@ class CodexCommandCatalogue {
|
|
|
22065
22151
|
onRefreshed: (read) => {
|
|
22066
22152
|
this.skillsDigest = commandBindingRevision([
|
|
22067
22153
|
String(read.fresh),
|
|
22068
|
-
read.snapshot ? JSON.stringify([
|
|
22154
|
+
read.snapshot ? JSON.stringify([
|
|
22155
|
+
read.snapshot.truncated,
|
|
22156
|
+
read.snapshot.bindings.map((binding) => skillCommandRow(binding))
|
|
22157
|
+
]) : "none"
|
|
22069
22158
|
]);
|
|
22070
22159
|
this.bumpIfChanged();
|
|
22071
22160
|
}
|
|
@@ -22083,6 +22172,9 @@ class CodexCommandCatalogue {
|
|
|
22083
22172
|
this.compositeDigest = composite;
|
|
22084
22173
|
this.revisionValue += 1;
|
|
22085
22174
|
}
|
|
22175
|
+
markPolicyChanged() {
|
|
22176
|
+
this.revisionValue += 1;
|
|
22177
|
+
}
|
|
22086
22178
|
markSkillsChanged() {
|
|
22087
22179
|
this.skills.markChanged();
|
|
22088
22180
|
}
|
|
@@ -22109,7 +22201,7 @@ class CodexCommandCatalogue {
|
|
|
22109
22201
|
const templates = await this.scanTemplates();
|
|
22110
22202
|
return [...BUILTINS.map(builtinRow), ...templates.effective.map(templateCommandRow)];
|
|
22111
22203
|
}
|
|
22112
|
-
async collect() {
|
|
22204
|
+
async collect(projectResources = true) {
|
|
22113
22205
|
this.deferredBumps += 1;
|
|
22114
22206
|
let templates;
|
|
22115
22207
|
let skillRead;
|
|
@@ -22122,7 +22214,7 @@ class CodexCommandCatalogue {
|
|
|
22122
22214
|
const candidates = [
|
|
22123
22215
|
...BUILTINS.map(builtinRow),
|
|
22124
22216
|
...templates.effective.map(templateCommandRow),
|
|
22125
|
-
...skillRead.snapshot?.bindings.map(skillCommandRow) ?? []
|
|
22217
|
+
...skillRead.snapshot?.bindings.map((binding) => skillCommandRow(binding, projectResources)) ?? []
|
|
22126
22218
|
];
|
|
22127
22219
|
const commands = [];
|
|
22128
22220
|
let bytes = 0;
|
|
@@ -22144,8 +22236,8 @@ class CodexCommandCatalogue {
|
|
|
22144
22236
|
skills: skillRead.snapshot
|
|
22145
22237
|
};
|
|
22146
22238
|
}
|
|
22147
|
-
async list() {
|
|
22148
|
-
const collected = await this.collect();
|
|
22239
|
+
async list(projectResources = true) {
|
|
22240
|
+
const collected = await this.collect(projectResources);
|
|
22149
22241
|
this.listedTemplates = new Map(collected.templates.effective.map((entry) => [entry.id, entry.fingerprint]));
|
|
22150
22242
|
return {
|
|
22151
22243
|
catalogueVersion: NATIVE_AGENT_COMMAND_CATALOGUE_VERSION,
|
|
@@ -22167,7 +22259,7 @@ class CodexCommandCatalogue {
|
|
|
22167
22259
|
}
|
|
22168
22260
|
return { outcome: "reloaded" };
|
|
22169
22261
|
}
|
|
22170
|
-
async resolveSelected(command) {
|
|
22262
|
+
async resolveSelected(command, projectResources = true) {
|
|
22171
22263
|
const stale = (name) => ({
|
|
22172
22264
|
kind: "refused",
|
|
22173
22265
|
message: `${name} changed since it was selected. Choose it again from the menu.`
|
|
@@ -22228,7 +22320,11 @@ class CodexCommandCatalogue {
|
|
|
22228
22320
|
const binding = read.snapshot.byId.get(command.id);
|
|
22229
22321
|
if (!binding)
|
|
22230
22322
|
return this.unknownSelection();
|
|
22231
|
-
return checkRow(skillCommandRow(binding)) ?? {
|
|
22323
|
+
return checkRow(skillCommandRow(binding, projectResources)) ?? {
|
|
22324
|
+
kind: "skill",
|
|
22325
|
+
binding,
|
|
22326
|
+
args: command.arguments
|
|
22327
|
+
};
|
|
22232
22328
|
}
|
|
22233
22329
|
return this.unknownSelection();
|
|
22234
22330
|
}
|
|
@@ -22238,7 +22334,21 @@ class CodexCommandCatalogue {
|
|
|
22238
22334
|
message: "The selected command is no longer available. Choose it again from the menu."
|
|
22239
22335
|
};
|
|
22240
22336
|
}
|
|
22241
|
-
async resolveTyped(prompt) {
|
|
22337
|
+
async resolveTyped(prompt, projectResources = true) {
|
|
22338
|
+
if (!projectResources) {
|
|
22339
|
+
const mention = parseCommandToken(prompt, ["$"]);
|
|
22340
|
+
if (mention) {
|
|
22341
|
+
const read = await this.skills.read();
|
|
22342
|
+
if (!read.fresh)
|
|
22343
|
+
return { kind: "refused", message: "Codex skills could not be verified." };
|
|
22344
|
+
const binding = read.snapshot?.bindings.find((candidate) => `$${candidate.name}` === mention.token);
|
|
22345
|
+
if (binding) {
|
|
22346
|
+
const unavailable = skillUnavailability(binding, projectResources);
|
|
22347
|
+
if (unavailable)
|
|
22348
|
+
return { kind: "refused", message: unavailable.message };
|
|
22349
|
+
}
|
|
22350
|
+
}
|
|
22351
|
+
}
|
|
22242
22352
|
const token = parseCommandToken(prompt, ["/"]);
|
|
22243
22353
|
if (!token)
|
|
22244
22354
|
return { kind: "text" };
|
|
@@ -22247,7 +22357,7 @@ class CodexCommandCatalogue {
|
|
|
22247
22357
|
if (builtin)
|
|
22248
22358
|
return { kind: "builtin", builtin: builtin.kind };
|
|
22249
22359
|
if (typed.toLowerCase().startsWith(SKILL_ALIAS_PREFIX)) {
|
|
22250
|
-
return this.resolveTypedSkill(typed, token.arguments);
|
|
22360
|
+
return this.resolveTypedSkill(typed, token.arguments, projectResources);
|
|
22251
22361
|
}
|
|
22252
22362
|
const scan = await this.scanTemplates();
|
|
22253
22363
|
const matches = matchByPrecedence(scan.effective, (entry) => [entry.displayName], typed);
|
|
@@ -22264,7 +22374,7 @@ class CodexCommandCatalogue {
|
|
|
22264
22374
|
return { kind: "refused", message: entry.problem.message };
|
|
22265
22375
|
return { kind: "template", entry, args: token.arguments };
|
|
22266
22376
|
}
|
|
22267
|
-
async resolveTypedSkill(typed, args) {
|
|
22377
|
+
async resolveTypedSkill(typed, args, projectResources) {
|
|
22268
22378
|
const read = await this.skills.read();
|
|
22269
22379
|
if (!read.snapshot) {
|
|
22270
22380
|
return {
|
|
@@ -22286,7 +22396,7 @@ class CodexCommandCatalogue {
|
|
|
22286
22396
|
};
|
|
22287
22397
|
}
|
|
22288
22398
|
const binding = matches[0];
|
|
22289
|
-
const unavailable = skillUnavailability(binding);
|
|
22399
|
+
const unavailable = skillUnavailability(binding, projectResources);
|
|
22290
22400
|
if (unavailable)
|
|
22291
22401
|
return { kind: "refused", message: unavailable.message };
|
|
22292
22402
|
return { kind: "skill", binding, args };
|
|
@@ -22297,8 +22407,8 @@ class CodexCommandCatalogue {
|
|
|
22297
22407
|
return loaded;
|
|
22298
22408
|
return expandTemplateArguments(loaded.body, args, TEMPLATE_LIMITS.maxExpandedBytes);
|
|
22299
22409
|
}
|
|
22300
|
-
async helpText() {
|
|
22301
|
-
const collected = await this.collect();
|
|
22410
|
+
async helpText(projectResources = true) {
|
|
22411
|
+
const collected = await this.collect(projectResources);
|
|
22302
22412
|
const lines = ["Available Codex slash commands:"];
|
|
22303
22413
|
const describe = (row, label) => {
|
|
22304
22414
|
const hint = row.argumentHint ? ` ${row.argumentHint}` : "";
|
|
@@ -22402,6 +22512,7 @@ class CodexRuntimeContext {
|
|
|
22402
22512
|
transcriptHydrateInFlight = new Map;
|
|
22403
22513
|
steerRequests = new Map;
|
|
22404
22514
|
commandCatalogue;
|
|
22515
|
+
projectSkillsRevision = 0;
|
|
22405
22516
|
accountRateLimits = [];
|
|
22406
22517
|
accountCredits;
|
|
22407
22518
|
closingSessionIds = new Set;
|
|
@@ -22461,6 +22572,8 @@ function promptThreadConfig(config) {
|
|
|
22461
22572
|
config.permissionProfile,
|
|
22462
22573
|
config.workflowResultTool
|
|
22463
22574
|
] : [],
|
|
22575
|
+
config.policy?.projectResources,
|
|
22576
|
+
config.cwd,
|
|
22464
22577
|
codexNetworkDeniedConfig(config.policy)
|
|
22465
22578
|
]);
|
|
22466
22579
|
}
|
|
@@ -22767,7 +22880,7 @@ class CodexRuntimeLifecycle {
|
|
|
22767
22880
|
return;
|
|
22768
22881
|
}
|
|
22769
22882
|
const lastMessage = context.messages.at(-1);
|
|
22770
|
-
const assistantMessage = lastMessage?.role === "assistant" ? lastMessage : {
|
|
22883
|
+
const assistantMessage = lastMessage?.role === "assistant" && !lastMessage.content && (lastMessage.parts?.length ?? 0) === 0 ? lastMessage : {
|
|
22771
22884
|
id: createMessageId(),
|
|
22772
22885
|
role: "assistant",
|
|
22773
22886
|
content: "",
|
|
@@ -22817,7 +22930,11 @@ class CodexRuntimeLifecycle {
|
|
|
22817
22930
|
}
|
|
22818
22931
|
return { detached, forgotten };
|
|
22819
22932
|
}
|
|
22820
|
-
async detachThread(context) {
|
|
22933
|
+
async detachThread(context, requireUnsubscribe = false) {
|
|
22934
|
+
if (requireUnsubscribe) {
|
|
22935
|
+
context.promptThreadConfig = undefined;
|
|
22936
|
+
await this.ctx.options.engine.unsubscribeThread(context.engineHandle, true);
|
|
22937
|
+
}
|
|
22821
22938
|
const sessionIds = [...context.bridgeSessionIds];
|
|
22822
22939
|
this.releaseThreadRuntimeState(context.threadId);
|
|
22823
22940
|
this.ctx.registry.detachThread(context.threadId);
|
|
@@ -22831,9 +22948,11 @@ class CodexRuntimeLifecycle {
|
|
|
22831
22948
|
}));
|
|
22832
22949
|
}
|
|
22833
22950
|
this.ctx.detachedThreads += 1;
|
|
22834
|
-
|
|
22835
|
-
|
|
22836
|
-
|
|
22951
|
+
if (!requireUnsubscribe) {
|
|
22952
|
+
await this.ctx.options.engine.unsubscribeThread(context.engineHandle).catch(() => {
|
|
22953
|
+
return;
|
|
22954
|
+
});
|
|
22955
|
+
}
|
|
22837
22956
|
}
|
|
22838
22957
|
releaseThreadRuntimeState(threadId) {
|
|
22839
22958
|
const timer = this.ctx.recoveryBackstops.get(threadId);
|
|
@@ -23031,6 +23150,7 @@ class CodexRuntimeLifecycle {
|
|
|
23031
23150
|
return;
|
|
23032
23151
|
}
|
|
23033
23152
|
if (event.kind === "skills.changed") {
|
|
23153
|
+
this.ctx.projectSkillsRevision += 1;
|
|
23034
23154
|
this.ctx.commandCatalogue.markSkillsChanged();
|
|
23035
23155
|
return;
|
|
23036
23156
|
}
|
|
@@ -24253,7 +24373,7 @@ class CodexRuntimePrompt {
|
|
|
24253
24373
|
const interpretCommands = input.allowProviderCommands !== false;
|
|
24254
24374
|
let plan;
|
|
24255
24375
|
if (input.command) {
|
|
24256
|
-
plan = await this.ctx.commandCatalogue.resolveSelected(input.command);
|
|
24376
|
+
plan = await this.ctx.commandCatalogue.resolveSelected(input.command, session.config.policy?.projectResources !== false);
|
|
24257
24377
|
if (plan.kind === "refused")
|
|
24258
24378
|
return commandRefusal(plan.message);
|
|
24259
24379
|
if (plan.kind === "builtin" && input.outputSchema) {
|
|
@@ -24289,22 +24409,19 @@ class CodexRuntimePrompt {
|
|
|
24289
24409
|
context = await this.ctx.callbacks.ensureAttached(session.id);
|
|
24290
24410
|
this.ctx.registry.assertNoActiveTurn(context);
|
|
24291
24411
|
if (!plan) {
|
|
24292
|
-
plan = interpretCommands && !input.outputSchema ? await this.ctx.commandCatalogue.resolveTyped(input.prompt) : { kind: "text" };
|
|
24412
|
+
plan = interpretCommands && !input.outputSchema ? await this.ctx.commandCatalogue.resolveTyped(input.prompt, session.config.policy?.projectResources !== false) : { kind: "text" };
|
|
24293
24413
|
} else if (plan.kind === "skill") {
|
|
24294
|
-
const
|
|
24295
|
-
if (
|
|
24296
|
-
|
|
24297
|
-
|
|
24298
|
-
return commandRefusal(revalidated.message);
|
|
24299
|
-
plan = revalidated;
|
|
24300
|
-
}
|
|
24414
|
+
const revalidated = await this.ctx.commandCatalogue.resolveSelected(input.command, session.config.policy?.projectResources !== false);
|
|
24415
|
+
if (revalidated.kind === "refused")
|
|
24416
|
+
return commandRefusal(revalidated.message);
|
|
24417
|
+
plan = revalidated;
|
|
24301
24418
|
}
|
|
24302
24419
|
if (plan.kind === "refused") {
|
|
24303
24420
|
this.emitLocalResponse(session, input.prompt, plan.message);
|
|
24304
24421
|
return { ok: true, result: { status: "processing", requestId } };
|
|
24305
24422
|
}
|
|
24306
24423
|
if (plan.kind === "builtin") {
|
|
24307
|
-
const response = plan.builtin === "help" ? await this.ctx.commandCatalogue.helpText() : await this.modelsListText(session);
|
|
24424
|
+
const response = plan.builtin === "help" ? await this.ctx.commandCatalogue.helpText(session.config.policy?.projectResources !== false) : await this.modelsListText(session);
|
|
24308
24425
|
this.emitLocalResponse(session, input.prompt, response);
|
|
24309
24426
|
return { ok: true, result: { status: "processing", requestId } };
|
|
24310
24427
|
}
|
|
@@ -24323,6 +24440,11 @@ class CodexRuntimePrompt {
|
|
|
24323
24440
|
executionPrompt = `$${plan.binding.name}${plan.args ? ` ${plan.args}` : ""}`;
|
|
24324
24441
|
skillInput = { name: plan.binding.name, path: plan.binding.path };
|
|
24325
24442
|
}
|
|
24443
|
+
if (plan.kind === "skill") {
|
|
24444
|
+
const unavailable = skillUnavailability(plan.binding, session.config.policy?.projectResources !== false);
|
|
24445
|
+
if (unavailable)
|
|
24446
|
+
return commandRefusal(unavailable.message);
|
|
24447
|
+
}
|
|
24326
24448
|
const isPlanReview = session.config.mode === "plan";
|
|
24327
24449
|
const promptConfig = () => ({
|
|
24328
24450
|
...session.config,
|
|
@@ -24336,7 +24458,8 @@ class CodexRuntimePrompt {
|
|
|
24336
24458
|
} : {},
|
|
24337
24459
|
...input.workflowResultTool ? { workflowResultTool: input.workflowResultTool } : {}
|
|
24338
24460
|
});
|
|
24339
|
-
|
|
24461
|
+
let projectSkillsRevision = this.ctx.projectSkillsRevision;
|
|
24462
|
+
const needsThreadReload = (config) => Boolean(input.workflowResultTool) || context?.promptThreadConfig !== promptThreadConfig(config) || config.policy?.projectResources === false && context?.projectSkillsRevision !== projectSkillsRevision;
|
|
24340
24463
|
if (context && !context.materialized && needsThreadReload(promptConfig())) {
|
|
24341
24464
|
await this.lifecycle.detachThread(context);
|
|
24342
24465
|
context = undefined;
|
|
@@ -24370,7 +24493,28 @@ class CodexRuntimePrompt {
|
|
|
24370
24493
|
if (hadAttachedContext && needsThreadReload(turnConfig)) {
|
|
24371
24494
|
context = await this.resumeThreadForPrompt(session.id, context, turnConfig);
|
|
24372
24495
|
}
|
|
24496
|
+
for (let attempt = 0;turnConfig.policy?.projectResources === false && projectSkillsRevision !== this.ctx.projectSkillsRevision; attempt += 1) {
|
|
24497
|
+
if (attempt >= 3) {
|
|
24498
|
+
context.promptThreadConfig = undefined;
|
|
24499
|
+
return {
|
|
24500
|
+
ok: false,
|
|
24501
|
+
status: 503,
|
|
24502
|
+
error: "Codex project skills kept changing; retry when the inventory settles"
|
|
24503
|
+
};
|
|
24504
|
+
}
|
|
24505
|
+
if (!context.materialized) {
|
|
24506
|
+
await this.lifecycle.detachThread(context, true);
|
|
24507
|
+
return {
|
|
24508
|
+
ok: false,
|
|
24509
|
+
status: 503,
|
|
24510
|
+
error: "Codex project skills changed during attachment; retry the prompt"
|
|
24511
|
+
};
|
|
24512
|
+
}
|
|
24513
|
+
projectSkillsRevision = this.ctx.projectSkillsRevision;
|
|
24514
|
+
context = await this.resumeThreadForPrompt(session.id, context, turnConfig);
|
|
24515
|
+
}
|
|
24373
24516
|
context.promptThreadConfig = promptThreadConfig(turnConfig);
|
|
24517
|
+
context.projectSkillsRevision = projectSkillsRevision;
|
|
24374
24518
|
if (input.workflowResultTool && turnConfig.agentMcp) {
|
|
24375
24519
|
const availability = await this.ctx.options.engine.workflowResultToolAvailability(context.threadId, input.workflowResultTool);
|
|
24376
24520
|
if (availability.state === "missing") {
|
|
@@ -24553,6 +24697,7 @@ class CodexRuntimePrompt {
|
|
|
24553
24697
|
context = await this.resumeThreadForPrompt(session.id, context, turnConfig);
|
|
24554
24698
|
}
|
|
24555
24699
|
context.promptThreadConfig = promptThreadConfig(turnConfig);
|
|
24700
|
+
context.projectSkillsRevision = projectSkillsRevision;
|
|
24556
24701
|
context.dispatchInFlight = true;
|
|
24557
24702
|
this.ctx.registry.setPhase(context, "starting");
|
|
24558
24703
|
if (context !== staleContext) {
|
|
@@ -24946,7 +25091,7 @@ class CodexRuntimePrompt {
|
|
|
24946
25091
|
commands: []
|
|
24947
25092
|
};
|
|
24948
25093
|
}
|
|
24949
|
-
return this.ctx.commandCatalogue.list();
|
|
25094
|
+
return this.ctx.commandCatalogue.list(this.ctx.registry.getSession(sessionId)?.config.policy?.projectResources !== false);
|
|
24950
25095
|
}
|
|
24951
25096
|
async refreshCommandCatalogue(sessionId) {
|
|
24952
25097
|
if (!this.ctx.registry.getSession(sessionId)) {
|
|
@@ -27240,7 +27385,5 @@ export {
|
|
|
27240
27385
|
REPLAY_IDLE_RETENTION_MS,
|
|
27241
27386
|
__testing,
|
|
27242
27387
|
app,
|
|
27243
|
-
boundCodexTranscriptResponse
|
|
27244
|
-
itemToParts,
|
|
27245
|
-
stringifyUnknown
|
|
27388
|
+
boundCodexTranscriptResponse
|
|
27246
27389
|
};
|