@nextclaw/nextclaw-narp-runtime-codex-sdk 0.1.33-beta.0 → 0.1.33-beta.1

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.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ import { CodexDesktopVisibilityPatch, CodexDesktopVisibilityPatchService } from "./services/codex-desktop-visibility-patch.service.js";
1
2
  import { CodexNarpRuntimeFactory, CodexNarpRuntimeWrapper } from "./services/codex-narp-runtime-wrapper.service.js";
2
- export { type CodexNarpRuntimeFactory, CodexNarpRuntimeWrapper };
3
+ export { type CodexDesktopVisibilityPatch, CodexDesktopVisibilityPatchService, type CodexNarpRuntimeFactory, CodexNarpRuntimeWrapper };
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ import { CodexDesktopVisibilityPatchService } from "./services/codex-desktop-visibility-patch.service.js";
1
2
  import { CodexNarpRuntimeWrapper } from "./services/codex-narp-runtime-wrapper.service.js";
2
- export { CodexNarpRuntimeWrapper };
3
+ export { CodexDesktopVisibilityPatchService, CodexNarpRuntimeWrapper };
@@ -0,0 +1,41 @@
1
+ //#region src/services/codex-desktop-visibility-patch.service.d.ts
2
+ interface CodexDesktopVisibilityPatch {
3
+ ensureWorkspaceVisible(params: {
4
+ workingDirectory?: string;
5
+ }): Promise<void>;
6
+ }
7
+ type OpenCodexDeepLink = (url: string) => Promise<void>;
8
+ interface CodexDesktopVisibilityPatchServiceOptions {
9
+ deepLinkVerificationIntervalMs?: number;
10
+ deepLinkVerificationTimeoutMs?: number;
11
+ env?: NodeJS.ProcessEnv;
12
+ globalStatePath?: string;
13
+ homeDirectory?: string;
14
+ openCodexDeepLink?: OpenCodexDeepLink;
15
+ platform?: NodeJS.Platform;
16
+ }
17
+ declare class CodexDesktopVisibilityPatchService implements CodexDesktopVisibilityPatch {
18
+ private readonly deepLinkVerificationIntervalMs;
19
+ private readonly deepLinkVerificationTimeoutMs;
20
+ private readonly env;
21
+ private readonly globalStatePath?;
22
+ private readonly homeDirectory;
23
+ private readonly openCodexDeepLink;
24
+ private readonly platform;
25
+ private readonly shouldUseCodexDeepLink;
26
+ constructor(options?: CodexDesktopVisibilityPatchServiceOptions);
27
+ ensureWorkspaceVisible: (params: {
28
+ workingDirectory?: string;
29
+ }) => Promise<void>;
30
+ private registerWithCodexDesktop;
31
+ private waitForWorkspaceVisibility;
32
+ private isWorkspaceVisible;
33
+ private updateCodexGlobalState;
34
+ private resolveGlobalStatePath;
35
+ private readGlobalState;
36
+ private writeGlobalState;
37
+ private backupExistingState;
38
+ }
39
+ //#endregion
40
+ export { CodexDesktopVisibilityPatch, CodexDesktopVisibilityPatchService };
41
+ //# sourceMappingURL=codex-desktop-visibility-patch.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-desktop-visibility-patch.service.d.ts","names":[],"sources":["../../src/services/codex-desktop-visibility-patch.service.ts"],"mappings":";UAuBiB,2BAAA;EACf,sBAAA,CAAuB,MAAA;IAAU,gBAAA;EAAA,IAA8B,OAAA;AAAA;AAAA,KAGrD,iBAAA,IAAqB,GAAA,aAAgB,OAAA;AAAA,UAEhC,yCAAA;EACf,8BAAA;EACA,6BAAA;EACA,GAAA,GAAM,MAAA,CAAO,UAAA;EACb,eAAA;EACA,aAAA;EACA,iBAAA,GAAoB,iBAAA;EACpB,QAAA,GAAW,MAAA,CAAO,QAAA;AAAA;AAAA,cAGP,kCAAA,YAA8C,2BAAA;EAAA,iBACxC,8BAAA;EAAA,iBACA,6BAAA;EAAA,iBACA,GAAA;EAAA,iBACA,eAAA;EAAA,iBACA,aAAA;EAAA,iBACA,iBAAA;EAAA,iBACA,QAAA;EAAA,iBACA,sBAAA;cAEL,OAAA,GAAS,yCAAA;EAcrB,sBAAA,GAAgC,MAAA;IAAU,gBAAA;EAAA,MAA8B,OAAA;EAAA,QA0BhE,wBAAA;EAAA,QAeA,0BAAA;EAAA,QAcA,kBAAA;EAAA,QAMA,sBAAA;EAAA,QAaA,sBAAA;EAAA,QAQA,eAAA;EAAA,QAYA,gBAAA;EAAA,QAWA,mBAAA;AAAA"}
@@ -0,0 +1,150 @@
1
+ import { constants, copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, isAbsolute, join, normalize, sep } from "node:path";
4
+ import { execFile } from "node:child_process";
5
+ import { randomUUID } from "node:crypto";
6
+ import { setTimeout } from "node:timers/promises";
7
+ import { promisify } from "node:util";
8
+ //#region src/services/codex-desktop-visibility-patch.service.ts
9
+ const VISIBILITY_PATCH_ENV = "NEXTCLAW_CODEX_DESKTOP_VISIBILITY_PATCH";
10
+ const CODEX_GLOBAL_STATE_FILE_NAME = ".codex-global-state.json";
11
+ const SAVED_WORKSPACE_ROOTS_KEY = "electron-saved-workspace-roots";
12
+ const DEEP_LINK_VERIFICATION_TIMEOUT_MS = 2500;
13
+ const DEEP_LINK_VERIFICATION_INTERVAL_MS = 100;
14
+ const execFileAsync = promisify(execFile);
15
+ var CodexDesktopVisibilityPatchService = class {
16
+ deepLinkVerificationIntervalMs;
17
+ deepLinkVerificationTimeoutMs;
18
+ env;
19
+ globalStatePath;
20
+ homeDirectory;
21
+ openCodexDeepLink;
22
+ platform;
23
+ shouldUseCodexDeepLink;
24
+ constructor(options = {}) {
25
+ this.deepLinkVerificationIntervalMs = options.deepLinkVerificationIntervalMs ?? DEEP_LINK_VERIFICATION_INTERVAL_MS;
26
+ this.deepLinkVerificationTimeoutMs = options.deepLinkVerificationTimeoutMs ?? DEEP_LINK_VERIFICATION_TIMEOUT_MS;
27
+ this.env = options.env ?? process.env;
28
+ this.globalStatePath = options.globalStatePath;
29
+ this.homeDirectory = options.homeDirectory ?? homedir();
30
+ this.openCodexDeepLink = options.openCodexDeepLink ?? defaultOpenCodexDeepLink;
31
+ this.platform = options.platform ?? process.platform;
32
+ this.shouldUseCodexDeepLink = options.openCodexDeepLink !== void 0 || this.platform === "darwin";
33
+ }
34
+ ensureWorkspaceVisible = async (params) => {
35
+ if (isDisabled(this.env[VISIBILITY_PATCH_ENV])) return;
36
+ const workspaceRoot = normalizeWorkspaceRoot(params.workingDirectory);
37
+ if (!workspaceRoot) return;
38
+ try {
39
+ const statePath = this.resolveGlobalStatePath();
40
+ if (this.isWorkspaceVisible(statePath, workspaceRoot)) return;
41
+ if (await this.registerWithCodexDesktop(statePath, workspaceRoot)) return;
42
+ this.updateCodexGlobalState(statePath, workspaceRoot);
43
+ } catch (error) {
44
+ console.error(`[nextclaw-codex-narp] failed to patch Codex Desktop workspace visibility: ${error instanceof Error ? error.message : String(error)}`);
45
+ }
46
+ };
47
+ registerWithCodexDesktop = async (statePath, workspaceRoot) => {
48
+ if (!this.shouldUseCodexDeepLink) return false;
49
+ try {
50
+ await this.openCodexDeepLink(buildCodexNewThreadDeepLink(workspaceRoot));
51
+ return this.waitForWorkspaceVisibility(statePath, workspaceRoot);
52
+ } catch {
53
+ return false;
54
+ }
55
+ };
56
+ waitForWorkspaceVisibility = async (statePath, workspaceRoot) => {
57
+ const deadline = Date.now() + this.deepLinkVerificationTimeoutMs;
58
+ do {
59
+ if (this.isWorkspaceVisible(statePath, workspaceRoot)) return true;
60
+ await setTimeout(this.deepLinkVerificationIntervalMs);
61
+ } while (Date.now() < deadline);
62
+ return this.isWorkspaceVisible(statePath, workspaceRoot);
63
+ };
64
+ isWorkspaceVisible = (statePath, workspaceRoot) => {
65
+ return includesWorkspaceRoot(readStringArrayField(this.readGlobalState(statePath), SAVED_WORKSPACE_ROOTS_KEY), workspaceRoot);
66
+ };
67
+ updateCodexGlobalState = (statePath, workspaceRoot) => {
68
+ const state = this.readGlobalState(statePath);
69
+ const savedWorkspaceRoots = readStringArrayField(state, SAVED_WORKSPACE_ROOTS_KEY);
70
+ const nextSavedWorkspaceRoots = prependMissingPath(savedWorkspaceRoots, workspaceRoot);
71
+ if (nextSavedWorkspaceRoots === savedWorkspaceRoots) return;
72
+ state[SAVED_WORKSPACE_ROOTS_KEY] = nextSavedWorkspaceRoots;
73
+ this.writeGlobalState(statePath, state);
74
+ };
75
+ resolveGlobalStatePath = () => {
76
+ if (this.globalStatePath) return this.globalStatePath;
77
+ return join(readString(this.env.CODEX_HOME) ?? join(this.homeDirectory, ".codex"), CODEX_GLOBAL_STATE_FILE_NAME);
78
+ };
79
+ readGlobalState = (statePath) => {
80
+ if (!existsSync(statePath)) return {};
81
+ const raw = readFileSync(statePath, "utf8");
82
+ const parsed = JSON.parse(raw);
83
+ if (!isRecord(parsed)) throw new Error(`Codex global state is not an object: ${statePath}`);
84
+ return parsed;
85
+ };
86
+ writeGlobalState = (statePath, state) => {
87
+ mkdirSync(dirname(statePath), { recursive: true });
88
+ this.backupExistingState(statePath);
89
+ const tempPath = `${statePath}.nextclaw-${randomUUID()}.tmp`;
90
+ writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}\n`, {
91
+ encoding: "utf8",
92
+ flag: "wx"
93
+ });
94
+ renameSync(tempPath, statePath);
95
+ };
96
+ backupExistingState = (statePath) => {
97
+ if (!existsSync(statePath)) return;
98
+ try {
99
+ copyFileSync(statePath, `${statePath}.nextclaw-backup`, constants.COPYFILE_EXCL);
100
+ } catch (error) {
101
+ if (isNodeError(error) && error.code === "EEXIST") return;
102
+ throw error;
103
+ }
104
+ };
105
+ };
106
+ function buildCodexNewThreadDeepLink(workspaceRoot) {
107
+ const url = new URL("codex://new");
108
+ url.searchParams.set("path", workspaceRoot);
109
+ return url.toString();
110
+ }
111
+ async function defaultOpenCodexDeepLink(url) {
112
+ await execFileAsync("open", [url]);
113
+ }
114
+ function prependMissingPath(values, path) {
115
+ return includesWorkspaceRoot(values, path) ? values : [path, ...values];
116
+ }
117
+ function includesWorkspaceRoot(values, path) {
118
+ return values.some((value) => normalizeWorkspaceRoot(value) === path);
119
+ }
120
+ function readStringArrayField(state, key) {
121
+ const value = state[key];
122
+ if (value === void 0) return [];
123
+ if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) throw new Error(`Codex global state field must be a string array: ${key}`);
124
+ return value;
125
+ }
126
+ function normalizeWorkspaceRoot(value) {
127
+ const normalized = readString(value);
128
+ if (!normalized || !isAbsolute(normalized)) return null;
129
+ const path = normalize(normalized);
130
+ return path.length > 1 && path.endsWith(sep) ? path.slice(0, -1) : path;
131
+ }
132
+ function isDisabled(value) {
133
+ const normalized = readString(value)?.toLowerCase();
134
+ return normalized === "0" || normalized === "false" || normalized === "off";
135
+ }
136
+ function readString(value) {
137
+ if (typeof value !== "string") return;
138
+ const trimmed = value.trim();
139
+ return trimmed.length > 0 ? trimmed : void 0;
140
+ }
141
+ function isRecord(value) {
142
+ return typeof value === "object" && value !== null && !Array.isArray(value);
143
+ }
144
+ function isNodeError(error) {
145
+ return error instanceof Error && "code" in error;
146
+ }
147
+ //#endregion
148
+ export { CodexDesktopVisibilityPatchService };
149
+
150
+ //# sourceMappingURL=codex-desktop-visibility-patch.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-desktop-visibility-patch.service.js","names":["delay"],"sources":["../../src/services/codex-desktop-visibility-patch.service.ts"],"sourcesContent":["import {\n constants,\n copyFileSync,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n writeFileSync,\n} from \"node:fs\";\nimport { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, normalize, sep } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\n\nconst VISIBILITY_PATCH_ENV = \"NEXTCLAW_CODEX_DESKTOP_VISIBILITY_PATCH\";\nconst CODEX_GLOBAL_STATE_FILE_NAME = \".codex-global-state.json\";\nconst SAVED_WORKSPACE_ROOTS_KEY = \"electron-saved-workspace-roots\";\nconst DEEP_LINK_VERIFICATION_TIMEOUT_MS = 2_500;\nconst DEEP_LINK_VERIFICATION_INTERVAL_MS = 100;\nconst execFileAsync = promisify(execFile);\n\nexport interface CodexDesktopVisibilityPatch {\n ensureWorkspaceVisible(params: { workingDirectory?: string }): Promise<void>;\n}\n\nexport type OpenCodexDeepLink = (url: string) => Promise<void>;\n\nexport interface CodexDesktopVisibilityPatchServiceOptions {\n deepLinkVerificationIntervalMs?: number;\n deepLinkVerificationTimeoutMs?: number;\n env?: NodeJS.ProcessEnv;\n globalStatePath?: string;\n homeDirectory?: string;\n openCodexDeepLink?: OpenCodexDeepLink;\n platform?: NodeJS.Platform;\n}\n\nexport class CodexDesktopVisibilityPatchService implements CodexDesktopVisibilityPatch {\n private readonly deepLinkVerificationIntervalMs: number;\n private readonly deepLinkVerificationTimeoutMs: number;\n private readonly env: NodeJS.ProcessEnv;\n private readonly globalStatePath?: string;\n private readonly homeDirectory: string;\n private readonly openCodexDeepLink: OpenCodexDeepLink;\n private readonly platform: NodeJS.Platform;\n private readonly shouldUseCodexDeepLink: boolean;\n\n constructor(options: CodexDesktopVisibilityPatchServiceOptions = {}) {\n this.deepLinkVerificationIntervalMs =\n options.deepLinkVerificationIntervalMs ?? DEEP_LINK_VERIFICATION_INTERVAL_MS;\n this.deepLinkVerificationTimeoutMs =\n options.deepLinkVerificationTimeoutMs ?? DEEP_LINK_VERIFICATION_TIMEOUT_MS;\n this.env = options.env ?? process.env;\n this.globalStatePath = options.globalStatePath;\n this.homeDirectory = options.homeDirectory ?? homedir();\n this.openCodexDeepLink = options.openCodexDeepLink ?? defaultOpenCodexDeepLink;\n this.platform = options.platform ?? process.platform;\n this.shouldUseCodexDeepLink =\n options.openCodexDeepLink !== undefined || this.platform === \"darwin\";\n }\n\n ensureWorkspaceVisible = async (params: { workingDirectory?: string }): Promise<void> => {\n if (isDisabled(this.env[VISIBILITY_PATCH_ENV])) {\n return;\n }\n const workspaceRoot = normalizeWorkspaceRoot(params.workingDirectory);\n if (!workspaceRoot) {\n return;\n }\n try {\n const statePath = this.resolveGlobalStatePath();\n if (this.isWorkspaceVisible(statePath, workspaceRoot)) {\n return;\n }\n if (await this.registerWithCodexDesktop(statePath, workspaceRoot)) {\n return;\n }\n this.updateCodexGlobalState(statePath, workspaceRoot);\n } catch (error) {\n console.error(\n `[nextclaw-codex-narp] failed to patch Codex Desktop workspace visibility: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n };\n\n private registerWithCodexDesktop = async (\n statePath: string,\n workspaceRoot: string,\n ): Promise<boolean> => {\n if (!this.shouldUseCodexDeepLink) {\n return false;\n }\n try {\n await this.openCodexDeepLink(buildCodexNewThreadDeepLink(workspaceRoot));\n return this.waitForWorkspaceVisibility(statePath, workspaceRoot);\n } catch {\n return false;\n }\n };\n\n private waitForWorkspaceVisibility = async (\n statePath: string,\n workspaceRoot: string,\n ): Promise<boolean> => {\n const deadline = Date.now() + this.deepLinkVerificationTimeoutMs;\n do {\n if (this.isWorkspaceVisible(statePath, workspaceRoot)) {\n return true;\n }\n await delay(this.deepLinkVerificationIntervalMs);\n } while (Date.now() < deadline);\n return this.isWorkspaceVisible(statePath, workspaceRoot);\n };\n\n private isWorkspaceVisible = (statePath: string, workspaceRoot: string): boolean => {\n const state = this.readGlobalState(statePath);\n const savedWorkspaceRoots = readStringArrayField(state, SAVED_WORKSPACE_ROOTS_KEY);\n return includesWorkspaceRoot(savedWorkspaceRoots, workspaceRoot);\n };\n\n private updateCodexGlobalState = (statePath: string, workspaceRoot: string): void => {\n const state = this.readGlobalState(statePath);\n const savedWorkspaceRoots = readStringArrayField(state, SAVED_WORKSPACE_ROOTS_KEY);\n const nextSavedWorkspaceRoots = prependMissingPath(savedWorkspaceRoots, workspaceRoot);\n\n if (nextSavedWorkspaceRoots === savedWorkspaceRoots) {\n return;\n }\n\n state[SAVED_WORKSPACE_ROOTS_KEY] = nextSavedWorkspaceRoots;\n this.writeGlobalState(statePath, state);\n };\n\n private resolveGlobalStatePath = (): string => {\n if (this.globalStatePath) {\n return this.globalStatePath;\n }\n const codexHome = readString(this.env.CODEX_HOME) ?? join(this.homeDirectory, \".codex\");\n return join(codexHome, CODEX_GLOBAL_STATE_FILE_NAME);\n };\n\n private readGlobalState = (statePath: string): Record<string, unknown> => {\n if (!existsSync(statePath)) {\n return {};\n }\n const raw = readFileSync(statePath, \"utf8\");\n const parsed = JSON.parse(raw) as unknown;\n if (!isRecord(parsed)) {\n throw new Error(`Codex global state is not an object: ${statePath}`);\n }\n return parsed;\n };\n\n private writeGlobalState = (statePath: string, state: Record<string, unknown>): void => {\n mkdirSync(dirname(statePath), { recursive: true });\n this.backupExistingState(statePath);\n const tempPath = `${statePath}.nextclaw-${randomUUID()}.tmp`;\n writeFileSync(tempPath, `${JSON.stringify(state, null, 2)}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n renameSync(tempPath, statePath);\n };\n\n private backupExistingState = (statePath: string): void => {\n if (!existsSync(statePath)) {\n return;\n }\n try {\n copyFileSync(statePath, `${statePath}.nextclaw-backup`, constants.COPYFILE_EXCL);\n } catch (error) {\n if (isNodeError(error) && error.code === \"EEXIST\") {\n return;\n }\n throw error;\n }\n };\n}\n\nfunction buildCodexNewThreadDeepLink(workspaceRoot: string): string {\n const url = new URL(\"codex://new\");\n url.searchParams.set(\"path\", workspaceRoot);\n return url.toString();\n}\n\nasync function defaultOpenCodexDeepLink(url: string): Promise<void> {\n await execFileAsync(\"open\", [url]);\n}\n\nfunction prependMissingPath(values: string[], path: string): string[] {\n return includesWorkspaceRoot(values, path) ? values : [path, ...values];\n}\n\nfunction includesWorkspaceRoot(values: string[], path: string): boolean {\n return values.some((value) => normalizeWorkspaceRoot(value) === path);\n}\n\nfunction readStringArrayField(state: Record<string, unknown>, key: string): string[] {\n const value = state[key];\n if (value === undefined) {\n return [];\n }\n if (!Array.isArray(value) || value.some((item) => typeof item !== \"string\")) {\n throw new Error(`Codex global state field must be a string array: ${key}`);\n }\n return value;\n}\n\nfunction normalizeWorkspaceRoot(value: string | undefined): string | null {\n const normalized = readString(value);\n if (!normalized || !isAbsolute(normalized)) {\n return null;\n }\n const path = normalize(normalized);\n return path.length > 1 && path.endsWith(sep) ? path.slice(0, -1) : path;\n}\n\nfunction isDisabled(value: string | undefined): boolean {\n const normalized = readString(value)?.toLowerCase();\n return normalized === \"0\" || normalized === \"false\" || normalized === \"off\";\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { CodexDesktopVisibilityPatch } from "./codex-desktop-visibility-patch.service.js";
1
2
  import { NarpStdioRuntimeWrapperContext } from "@nextclaw/nextclaw-narp-stdio-runtime-wrapper";
2
3
  import { CodexOpenAiResponsesBridgeResult, CodexOpenAiResponsesBridgeRuntimeConfig, CodexSdkNcpAgentRuntimeConfig } from "@nextclaw/nextclaw-ncp-runtime-codex-sdk";
3
4
  import { NcpAgentRuntime } from "@nextclaw/ncp";
@@ -8,7 +9,8 @@ type CodexResponsesBridgeFactory = (config: CodexOpenAiResponsesBridgeRuntimeCon
8
9
  declare class CodexNarpRuntimeWrapper {
9
10
  private readonly createRuntime;
10
11
  private readonly ensureResponsesBridge;
11
- constructor(createRuntime?: CodexNarpRuntimeFactory, ensureResponsesBridge?: CodexResponsesBridgeFactory);
12
+ private readonly desktopVisibilityPatch;
13
+ constructor(createRuntime?: CodexNarpRuntimeFactory, ensureResponsesBridge?: CodexResponsesBridgeFactory, desktopVisibilityPatch?: CodexDesktopVisibilityPatch);
12
14
  start: () => void;
13
15
  createCodexRuntime: (context: NarpStdioRuntimeWrapperContext) => NcpAgentRuntime;
14
16
  buildRuntimeConfig: (context: NarpStdioRuntimeWrapperContext) => Promise<CodexSdkNcpAgentRuntimeConfig>;
@@ -1 +1 @@
1
- {"version":3,"file":"codex-narp-runtime-wrapper.service.d.ts","names":[],"sources":["../../src/services/codex-narp-runtime-wrapper.service.ts"],"mappings":";;;;;KA2BY,uBAAA,IACV,MAAA,EAAQ,6BAAA,KACL,eAAA;AAAA,KAEO,2BAAA,IACV,MAAA,EAAQ,uCAAA,KACL,OAAA,CAAQ,gCAAA;AAAA,cAsBA,uBAAA;EAAA,iBAEQ,aAAA;EAAA,iBAGA,qBAAA;cAHA,aAAA,GAAe,uBAAA,EAGf,qBAAA,GAAuB,2BAAA;EAI1C,KAAA;EAOA,kBAAA,GAAsB,OAAA,EAAS,8BAAA,KAAiC,eAAA;EAMhE,kBAAA,GACE,OAAA,EAAS,8BAAA,KACR,OAAA,CAAQ,6BAAA;EAAA,QAiDH,oBAAA;AAAA"}
1
+ {"version":3,"file":"codex-narp-runtime-wrapper.service.d.ts","names":[],"sources":["../../src/services/codex-narp-runtime-wrapper.service.ts"],"mappings":";;;;;;KA+BY,uBAAA,IACV,MAAA,EAAQ,6BAAA,KACL,eAAA;AAAA,KAEO,2BAAA,IACV,MAAA,EAAQ,uCAAA,KACL,OAAA,CAAQ,gCAAA;AAAA,cAsBA,uBAAA;EAAA,iBAEQ,aAAA;EAAA,iBAGA,qBAAA;EAAA,iBAEA,sBAAA;cALA,aAAA,GAAe,uBAAA,EAGf,qBAAA,GAAuB,2BAAA,EAEvB,sBAAA,GAAwB,2BAAA;EAI3C,KAAA;EAOA,kBAAA,GAAsB,OAAA,EAAS,8BAAA,KAAiC,eAAA;EAMhE,kBAAA,GACE,OAAA,EAAS,8BAAA,KACR,OAAA,CAAQ,6BAAA;EAAA,QAiDH,oBAAA;AAAA"}
@@ -1,3 +1,4 @@
1
+ import { CodexDesktopVisibilityPatchService } from "./codex-desktop-visibility-patch.service.js";
1
2
  import { appendFileSync, mkdirSync } from "node:fs";
2
3
  import { homedir } from "node:os";
3
4
  import { dirname, join } from "node:path";
@@ -18,9 +19,10 @@ var DeferredCodexNarpRuntime = class {
18
19
  };
19
20
  };
20
21
  var CodexNarpRuntimeWrapper = class {
21
- constructor(createRuntime = (config) => new CodexAppServerNcpAgentRuntime(config), ensureResponsesBridge = ensureCodexOpenAiResponsesBridge) {
22
+ constructor(createRuntime = (config) => new CodexAppServerNcpAgentRuntime(config), ensureResponsesBridge = ensureCodexOpenAiResponsesBridge, desktopVisibilityPatch = new CodexDesktopVisibilityPatchService()) {
22
23
  this.createRuntime = createRuntime;
23
24
  this.ensureResponsesBridge = ensureResponsesBridge;
25
+ this.desktopVisibilityPatch = desktopVisibilityPatch;
24
26
  }
25
27
  start = () => {
26
28
  new NarpStdioRuntimeWrapper({
@@ -82,6 +84,7 @@ var CodexNarpRuntimeWrapper = class {
82
84
  modelProvider: bridgeModelProvider,
83
85
  providerLocalModel
84
86
  }) : requestedThreadModel;
87
+ await this.desktopVisibilityPatch.ensureWorkspaceVisible({ workingDirectory: cwd });
85
88
  const config = {
86
89
  sessionId,
87
90
  apiKey,
@@ -1 +1 @@
1
- {"version":3,"file":"codex-narp-runtime-wrapper.service.js","names":[],"sources":["../../src/services/codex-narp-runtime-wrapper.service.ts"],"sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type {\n NcpAgentRunInput,\n NcpAgentRunOptions,\n NcpAgentRuntime,\n NcpEndpointEvent,\n} from \"@nextclaw/ncp\";\nimport {\n NarpStdioRuntimeWrapper,\n type NarpStdioRuntimeWrapperContext,\n} from \"@nextclaw/nextclaw-narp-stdio-runtime-wrapper\";\nimport {\n CodexAppServerNcpAgentRuntime,\n CodexLiveOutputStream,\n buildCodexBridgeModelProviderId,\n ensureCodexOpenAiResponsesBridge,\n type CodexSdkNcpAgentRuntimeConfig,\n type CodexOpenAiResponsesBridgeResult,\n type CodexOpenAiResponsesBridgeRuntimeConfig,\n} from \"@nextclaw/nextclaw-ncp-runtime-codex-sdk\";\n\nconst NARP_API_MODE_HEADER = \"x-nextclaw-narp-api-mode\";\nconst CODEX_NARP_DEBUG_CONFIG_ENV = \"NEXTCLAW_CODEX_NARP_DEBUG_CONFIG\";\nconst RUNTIME_DEFAULT_MODEL_VALUE = \"__nextclaw_runtime_default__\";\n\nexport type CodexNarpRuntimeFactory = (\n config: CodexSdkNcpAgentRuntimeConfig,\n) => NcpAgentRuntime;\n\nexport type CodexResponsesBridgeFactory = (\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n) => Promise<CodexOpenAiResponsesBridgeResult>;\n\ntype CodexReasoningEffort = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\nclass DeferredCodexNarpRuntime implements NcpAgentRuntime {\n private runtimePromise: Promise<NcpAgentRuntime> | null = null;\n\n constructor(private readonly createRuntime: () => Promise<NcpAgentRuntime>) {}\n\n run = async function* (\n this: DeferredCodexNarpRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n if (!this.runtimePromise) {\n this.runtimePromise = this.createRuntime();\n }\n const runtime = await this.runtimePromise;\n yield* runtime.run(input, options);\n };\n}\n\nexport class CodexNarpRuntimeWrapper {\n constructor(\n private readonly createRuntime: CodexNarpRuntimeFactory = (\n config,\n ) => new CodexAppServerNcpAgentRuntime(config),\n private readonly ensureResponsesBridge: CodexResponsesBridgeFactory =\n ensureCodexOpenAiResponsesBridge,\n ) {}\n\n start = (): void => {\n new NarpStdioRuntimeWrapper({\n agentName: \"NextClaw Codex NARP\",\n createRuntime: (context) => this.createCodexRuntime(context),\n }).start();\n };\n\n createCodexRuntime = (context: NarpStdioRuntimeWrapperContext): NcpAgentRuntime => {\n return new DeferredCodexNarpRuntime(async () =>\n this.createRuntime(await this.buildRuntimeConfig(context)),\n );\n };\n\n buildRuntimeConfig = (\n context: NarpStdioRuntimeWrapperContext,\n ): Promise<CodexSdkNcpAgentRuntimeConfig> => {\n const { cwd, modelId, promptMeta, sessionId, setSessionMetadata } = context;\n const providerRoute = promptMeta.providerRoute;\n const sessionMetadata = promptMeta.sessionMetadata ?? {};\n const useCodexRuntimeDefault = isRuntimeDefaultModelValue(\n readString(sessionMetadata.preferred_model) ??\n readString(sessionMetadata.preferredModel) ??\n readString(sessionMetadata.model) ??\n readString(modelId),\n );\n const providerLocalModel = useCodexRuntimeDefault\n ? undefined\n : stripProviderPrefix(readString(providerRoute?.model)) ??\n stripProviderPrefix(readString(modelId)) ??\n readString(process.env.NEXTCLAW_MODEL);\n const upstreamApiBase =\n useCodexRuntimeDefault\n ? undefined\n : readString(providerRoute?.apiBase) ?? readString(process.env.NEXTCLAW_API_BASE);\n const externalModelProvider = resolveExternalModelProvider({\n apiBase: upstreamApiBase,\n modelId,\n });\n\n return this.resolveRuntimeConfig({\n apiKey:\n (useCodexRuntimeDefault\n ? undefined\n : readString(providerRoute?.apiKey) ?? readString(process.env.NEXTCLAW_API_KEY)) ??\n \"\",\n cwd,\n externalModelProvider,\n providerLocalModel,\n sessionId,\n sessionMetadata,\n setSessionMetadata,\n threadModel: useCodexRuntimeDefault\n ? undefined\n : readString(modelId) ??\n composeModelRoute({\n modelProvider: externalModelProvider,\n providerLocalModel,\n }) ??\n providerLocalModel,\n upstreamApiBase,\n upstreamExtraHeaders: providerRoute?.headers,\n });\n };\n\n private resolveRuntimeConfig = async (params: {\n apiKey: string;\n cwd?: string;\n externalModelProvider?: string;\n providerLocalModel?: string;\n sessionId: string;\n sessionMetadata: Record<string, unknown>;\n threadModel?: string;\n upstreamApiBase?: string;\n upstreamExtraHeaders?: Record<string, string>;\n setSessionMetadata?: CodexSdkNcpAgentRuntimeConfig[\"setSessionMetadata\"];\n }): Promise<CodexSdkNcpAgentRuntimeConfig> => {\n const {\n apiKey,\n cwd,\n externalModelProvider,\n providerLocalModel,\n sessionId,\n sessionMetadata,\n setSessionMetadata,\n threadModel: requestedThreadModel,\n upstreamApiBase,\n upstreamExtraHeaders,\n } = params;\n const bridgeModelProvider =\n upstreamApiBase && shouldUseResponsesBridge({\n apiBase: upstreamApiBase,\n headers: upstreamExtraHeaders,\n })\n ? buildCodexBridgeModelProviderId(externalModelProvider ?? \"chat\")\n : undefined;\n const liveOutputStream = new CodexLiveOutputStream();\n const bridge = bridgeModelProvider\n ? await this.ensureResponsesBridge({\n upstreamApiBase: upstreamApiBase ?? \"\",\n upstreamApiKey: apiKey,\n upstreamExtraHeaders: stripInternalRouteHeaders(upstreamExtraHeaders),\n defaultModel: providerLocalModel,\n outputObserver: liveOutputStream,\n upstreamReasoningSplit: isMiniMaxApiBase(upstreamApiBase ?? \"\"),\n modelPrefixes: [\n externalModelProvider ?? \"\",\n bridgeModelProvider,\n ],\n })\n : null;\n const apiBase = bridge?.baseUrl ?? upstreamApiBase;\n const modelProvider = bridgeModelProvider ?? externalModelProvider;\n const codexPathOverride =\n readString(process.env.NEXTCLAW_CODEX_PATH) ??\n readString(process.env.CODEX_PATH);\n const modelReasoningEffort =\n readReasoningEffort(sessionMetadata.preferred_thinking) ??\n readReasoningEffort(sessionMetadata.thinking);\n const threadModel = bridgeModelProvider\n ? composeModelRoute({\n modelProvider: bridgeModelProvider,\n providerLocalModel,\n })\n : requestedThreadModel;\n\n const threadModelScope = threadModel ?? RUNTIME_DEFAULT_MODEL_VALUE;\n const config = {\n sessionId,\n apiKey,\n apiBase,\n model: providerLocalModel,\n threadId: resolveReusableThreadId(sessionMetadata, threadModelScope),\n ...(codexPathOverride ? { codexPathOverride } : {}),\n sessionMetadata,\n ...(setSessionMetadata ? { setSessionMetadata } : {}),\n liveOutputStream: bridge ? liveOutputStream : undefined,\n cliConfig: buildCodexCliConfig({\n apiBase,\n modelProvider,\n showRawAgentReasoning: Boolean(modelReasoningEffort),\n }),\n threadOptions: {\n ...(threadModel ? { model: threadModel } : {}),\n workingDirectory: cwd,\n skipGitRepoCheck: true,\n ...(modelReasoningEffort ? { modelReasoningEffort } : {}),\n },\n };\n logCodexRuntimeConfig({\n bridgeModelProvider,\n config,\n externalModelProvider,\n providerLocalModel,\n requestedThreadModel,\n sessionMetadata,\n threadModel,\n });\n return config;\n };\n}\n\nfunction resolveReusableThreadId(\n sessionMetadata: Record<string, unknown>,\n threadModelScope: string,\n): string | null {\n const threadId = readString(sessionMetadata.codex_thread_id);\n if (!threadId) {\n return null;\n }\n const threadScope = readString(sessionMetadata.codex_thread_model);\n if (!threadScope) {\n return null;\n }\n return threadScope === threadModelScope ? threadId : null;\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction stripProviderPrefix(value: string | undefined): string | undefined {\n const normalized = readString(value);\n if (!normalized) {\n return undefined;\n }\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex <= 0) {\n return normalized;\n }\n return readString(normalized.slice(slashIndex + 1));\n}\n\nfunction isRuntimeDefaultModelValue(value: string | undefined): boolean {\n return value === RUNTIME_DEFAULT_MODEL_VALUE;\n}\n\nfunction readReasoningEffort(value: unknown): CodexReasoningEffort | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const normalized = value.trim().toLowerCase();\n if (\n normalized === \"minimal\" ||\n normalized === \"low\" ||\n normalized === \"medium\" ||\n normalized === \"high\" ||\n normalized === \"xhigh\"\n ) {\n return normalized;\n }\n return undefined;\n}\n\nfunction readModelProvider(value: string | undefined): string | undefined {\n const normalized = readString(value);\n if (!normalized) {\n return undefined;\n }\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex <= 0) {\n return undefined;\n }\n return readString(normalized.slice(0, slashIndex));\n}\n\nfunction composeModelRoute(params: {\n modelProvider?: string;\n providerLocalModel?: string;\n}): string | undefined {\n const { modelProvider, providerLocalModel } = params;\n if (!modelProvider || !providerLocalModel) {\n return undefined;\n }\n return `${modelProvider}/${providerLocalModel}`;\n}\n\nfunction buildCodexCliConfig(params: {\n apiBase?: string;\n modelProvider?: string;\n showRawAgentReasoning?: boolean;\n}): CodexSdkNcpAgentRuntimeConfig[\"cliConfig\"] | undefined {\n const { apiBase, modelProvider, showRawAgentReasoning } = params;\n if (!modelProvider && !showRawAgentReasoning) {\n return undefined;\n }\n const config: Record<string, unknown> = {};\n if (showRawAgentReasoning) {\n config.show_raw_agent_reasoning = true;\n }\n if (modelProvider) {\n config.model_provider = modelProvider;\n config.preferred_auth_method = \"apikey\";\n }\n if (apiBase && modelProvider) {\n config.model_providers = {\n [modelProvider]: {\n name: modelProvider,\n base_url: apiBase,\n wire_api: \"responses\",\n requires_openai_auth: true,\n },\n };\n }\n return config as CodexSdkNcpAgentRuntimeConfig[\"cliConfig\"];\n}\n\nfunction logCodexRuntimeConfig(params: {\n bridgeModelProvider?: string;\n config: CodexSdkNcpAgentRuntimeConfig;\n externalModelProvider?: string;\n providerLocalModel?: string;\n requestedThreadModel?: string;\n sessionMetadata: Record<string, unknown>;\n threadModel?: string;\n}): void {\n if (process.env[CODEX_NARP_DEBUG_CONFIG_ENV] !== \"1\") {\n return;\n }\n const {\n bridgeModelProvider,\n config,\n externalModelProvider,\n providerLocalModel,\n requestedThreadModel,\n sessionMetadata,\n threadModel,\n } = params;\n const cliConfig = config.cliConfig as Record<string, unknown> | undefined;\n const modelProviders = cliConfig?.model_providers;\n const snapshot = {\n bridgeModelProvider: bridgeModelProvider ?? null,\n externalModelProvider: externalModelProvider ?? null,\n hasApiBase: Boolean(config.apiBase),\n hasApiKey: Boolean(config.apiKey),\n hasLiveOutputStream: Boolean(config.liveOutputStream),\n providerLocalModel: providerLocalModel ?? null,\n requestedThreadModel: requestedThreadModel ?? null,\n sessionId: config.sessionId,\n sessionMetadata: {\n codex_thread_id: readString(sessionMetadata.codex_thread_id) ?? null,\n codex_thread_model: readString(sessionMetadata.codex_thread_model) ?? null,\n model: readString(sessionMetadata.model) ?? null,\n preferred_model: readString(sessionMetadata.preferred_model) ?? null,\n preferred_thinking: readString(sessionMetadata.preferred_thinking) ?? null,\n thinking: readString(sessionMetadata.thinking) ?? null,\n },\n sdkConfig: {\n cliConfig: cliConfig\n ? {\n model_provider: readString(cliConfig.model_provider) ?? null,\n model_providers:\n modelProviders && typeof modelProviders === \"object\" && !Array.isArray(modelProviders)\n ? Object.keys(modelProviders)\n : [],\n preferred_auth_method: readString(cliConfig.preferred_auth_method) ?? null,\n show_raw_agent_reasoning: cliConfig.show_raw_agent_reasoning === true,\n }\n : null,\n model: config.model ?? null,\n threadId: config.threadId ?? null,\n threadOptions: {\n model: config.threadOptions?.model ?? null,\n modelReasoningEffort: config.threadOptions?.modelReasoningEffort ?? null,\n skipGitRepoCheck: config.threadOptions?.skipGitRepoCheck ?? null,\n workingDirectory: config.threadOptions?.workingDirectory ?? null,\n },\n },\n threadModel: threadModel ?? null,\n ts: new Date().toISOString(),\n };\n const line = `[nextclaw-codex-narp] runtime-config ${JSON.stringify(snapshot)}`;\n console.error(line);\n appendDebugLog(snapshot);\n}\n\nfunction appendDebugLog(snapshot: Record<string, unknown>): void {\n try {\n const home = readString(process.env.NEXTCLAW_HOME) ?? join(homedir(), \".nextclaw\");\n const logPath = join(home, \"logs\", \"codex-narp-runtime-config.jsonl\");\n mkdirSync(dirname(logPath), { recursive: true });\n appendFileSync(logPath, `${JSON.stringify(snapshot)}\\n`, \"utf8\");\n } catch (error) {\n console.error(\n `[nextclaw-codex-narp] failed to write runtime config debug log: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\nfunction readApiMode(headers: Record<string, string> | undefined): string | undefined {\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (key.toLowerCase() === NARP_API_MODE_HEADER) {\n return readString(value)?.toLowerCase();\n }\n }\n return undefined;\n}\n\nfunction shouldUseResponsesBridge(params: {\n apiBase?: string;\n headers?: Record<string, string>;\n}): boolean {\n const apiMode = readApiMode(params.headers);\n if (apiMode === \"chat_completions\") {\n return true;\n }\n return Boolean(params.apiBase && isMiniMaxApiBase(params.apiBase));\n}\n\nfunction stripInternalRouteHeaders(\n headers: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (key.toLowerCase() === NARP_API_MODE_HEADER) {\n continue;\n }\n out[key] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction resolveExternalModelProvider(params: {\n apiBase?: string;\n modelId?: string;\n}): string | undefined {\n return readModelProvider(params.modelId) ??\n (params.apiBase && isMiniMaxApiBase(params.apiBase) ? \"minimax\" : undefined);\n}\n\nfunction isMiniMaxApiBase(apiBase: string): boolean {\n try {\n const host = new URL(apiBase).hostname.toLowerCase();\n return host === \"api.minimaxi.com\" || host.endsWith(\".minimaxi.com\");\n } catch {\n return apiBase.toLowerCase().includes(\"api.minimaxi.com\");\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"codex-narp-runtime-wrapper.service.js","names":[],"sources":["../../src/services/codex-narp-runtime-wrapper.service.ts"],"sourcesContent":["import { appendFileSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type {\n NcpAgentRunInput,\n NcpAgentRunOptions,\n NcpAgentRuntime,\n NcpEndpointEvent,\n} from \"@nextclaw/ncp\";\nimport {\n NarpStdioRuntimeWrapper,\n type NarpStdioRuntimeWrapperContext,\n} from \"@nextclaw/nextclaw-narp-stdio-runtime-wrapper\";\nimport {\n CodexAppServerNcpAgentRuntime,\n CodexLiveOutputStream,\n buildCodexBridgeModelProviderId,\n ensureCodexOpenAiResponsesBridge,\n type CodexSdkNcpAgentRuntimeConfig,\n type CodexOpenAiResponsesBridgeResult,\n type CodexOpenAiResponsesBridgeRuntimeConfig,\n} from \"@nextclaw/nextclaw-ncp-runtime-codex-sdk\";\nimport {\n CodexDesktopVisibilityPatchService,\n type CodexDesktopVisibilityPatch,\n} from \"./codex-desktop-visibility-patch.service.js\";\n\nconst NARP_API_MODE_HEADER = \"x-nextclaw-narp-api-mode\";\nconst CODEX_NARP_DEBUG_CONFIG_ENV = \"NEXTCLAW_CODEX_NARP_DEBUG_CONFIG\";\nconst RUNTIME_DEFAULT_MODEL_VALUE = \"__nextclaw_runtime_default__\";\n\nexport type CodexNarpRuntimeFactory = (\n config: CodexSdkNcpAgentRuntimeConfig,\n) => NcpAgentRuntime;\n\nexport type CodexResponsesBridgeFactory = (\n config: CodexOpenAiResponsesBridgeRuntimeConfig,\n) => Promise<CodexOpenAiResponsesBridgeResult>;\n\ntype CodexReasoningEffort = \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\nclass DeferredCodexNarpRuntime implements NcpAgentRuntime {\n private runtimePromise: Promise<NcpAgentRuntime> | null = null;\n\n constructor(private readonly createRuntime: () => Promise<NcpAgentRuntime>) {}\n\n run = async function* (\n this: DeferredCodexNarpRuntime,\n input: NcpAgentRunInput,\n options?: NcpAgentRunOptions,\n ): AsyncGenerator<NcpEndpointEvent> {\n if (!this.runtimePromise) {\n this.runtimePromise = this.createRuntime();\n }\n const runtime = await this.runtimePromise;\n yield* runtime.run(input, options);\n };\n}\n\nexport class CodexNarpRuntimeWrapper {\n constructor(\n private readonly createRuntime: CodexNarpRuntimeFactory = (\n config,\n ) => new CodexAppServerNcpAgentRuntime(config),\n private readonly ensureResponsesBridge: CodexResponsesBridgeFactory =\n ensureCodexOpenAiResponsesBridge,\n private readonly desktopVisibilityPatch: CodexDesktopVisibilityPatch =\n new CodexDesktopVisibilityPatchService(),\n ) {}\n\n start = (): void => {\n new NarpStdioRuntimeWrapper({\n agentName: \"NextClaw Codex NARP\",\n createRuntime: (context) => this.createCodexRuntime(context),\n }).start();\n };\n\n createCodexRuntime = (context: NarpStdioRuntimeWrapperContext): NcpAgentRuntime => {\n return new DeferredCodexNarpRuntime(async () =>\n this.createRuntime(await this.buildRuntimeConfig(context)),\n );\n };\n\n buildRuntimeConfig = (\n context: NarpStdioRuntimeWrapperContext,\n ): Promise<CodexSdkNcpAgentRuntimeConfig> => {\n const { cwd, modelId, promptMeta, sessionId, setSessionMetadata } = context;\n const providerRoute = promptMeta.providerRoute;\n const sessionMetadata = promptMeta.sessionMetadata ?? {};\n const useCodexRuntimeDefault = isRuntimeDefaultModelValue(\n readString(sessionMetadata.preferred_model) ??\n readString(sessionMetadata.preferredModel) ??\n readString(sessionMetadata.model) ??\n readString(modelId),\n );\n const providerLocalModel = useCodexRuntimeDefault\n ? undefined\n : stripProviderPrefix(readString(providerRoute?.model)) ??\n stripProviderPrefix(readString(modelId)) ??\n readString(process.env.NEXTCLAW_MODEL);\n const upstreamApiBase =\n useCodexRuntimeDefault\n ? undefined\n : readString(providerRoute?.apiBase) ?? readString(process.env.NEXTCLAW_API_BASE);\n const externalModelProvider = resolveExternalModelProvider({\n apiBase: upstreamApiBase,\n modelId,\n });\n\n return this.resolveRuntimeConfig({\n apiKey:\n (useCodexRuntimeDefault\n ? undefined\n : readString(providerRoute?.apiKey) ?? readString(process.env.NEXTCLAW_API_KEY)) ??\n \"\",\n cwd,\n externalModelProvider,\n providerLocalModel,\n sessionId,\n sessionMetadata,\n setSessionMetadata,\n threadModel: useCodexRuntimeDefault\n ? undefined\n : readString(modelId) ??\n composeModelRoute({\n modelProvider: externalModelProvider,\n providerLocalModel,\n }) ??\n providerLocalModel,\n upstreamApiBase,\n upstreamExtraHeaders: providerRoute?.headers,\n });\n };\n\n private resolveRuntimeConfig = async (params: {\n apiKey: string;\n cwd?: string;\n externalModelProvider?: string;\n providerLocalModel?: string;\n sessionId: string;\n sessionMetadata: Record<string, unknown>;\n threadModel?: string;\n upstreamApiBase?: string;\n upstreamExtraHeaders?: Record<string, string>;\n setSessionMetadata?: CodexSdkNcpAgentRuntimeConfig[\"setSessionMetadata\"];\n }): Promise<CodexSdkNcpAgentRuntimeConfig> => {\n const {\n apiKey,\n cwd,\n externalModelProvider,\n providerLocalModel,\n sessionId,\n sessionMetadata,\n setSessionMetadata,\n threadModel: requestedThreadModel,\n upstreamApiBase,\n upstreamExtraHeaders,\n } = params;\n const bridgeModelProvider =\n upstreamApiBase && shouldUseResponsesBridge({\n apiBase: upstreamApiBase,\n headers: upstreamExtraHeaders,\n })\n ? buildCodexBridgeModelProviderId(externalModelProvider ?? \"chat\")\n : undefined;\n const liveOutputStream = new CodexLiveOutputStream();\n const bridge = bridgeModelProvider\n ? await this.ensureResponsesBridge({\n upstreamApiBase: upstreamApiBase ?? \"\",\n upstreamApiKey: apiKey,\n upstreamExtraHeaders: stripInternalRouteHeaders(upstreamExtraHeaders),\n defaultModel: providerLocalModel,\n outputObserver: liveOutputStream,\n upstreamReasoningSplit: isMiniMaxApiBase(upstreamApiBase ?? \"\"),\n modelPrefixes: [\n externalModelProvider ?? \"\",\n bridgeModelProvider,\n ],\n })\n : null;\n const apiBase = bridge?.baseUrl ?? upstreamApiBase;\n const modelProvider = bridgeModelProvider ?? externalModelProvider;\n const codexPathOverride =\n readString(process.env.NEXTCLAW_CODEX_PATH) ??\n readString(process.env.CODEX_PATH);\n const modelReasoningEffort =\n readReasoningEffort(sessionMetadata.preferred_thinking) ??\n readReasoningEffort(sessionMetadata.thinking);\n const threadModel = bridgeModelProvider\n ? composeModelRoute({\n modelProvider: bridgeModelProvider,\n providerLocalModel,\n })\n : requestedThreadModel;\n await this.desktopVisibilityPatch.ensureWorkspaceVisible({\n workingDirectory: cwd,\n });\n\n const threadModelScope = threadModel ?? RUNTIME_DEFAULT_MODEL_VALUE;\n const config = {\n sessionId,\n apiKey,\n apiBase,\n model: providerLocalModel,\n threadId: resolveReusableThreadId(sessionMetadata, threadModelScope),\n ...(codexPathOverride ? { codexPathOverride } : {}),\n sessionMetadata,\n ...(setSessionMetadata ? { setSessionMetadata } : {}),\n liveOutputStream: bridge ? liveOutputStream : undefined,\n cliConfig: buildCodexCliConfig({\n apiBase,\n modelProvider,\n showRawAgentReasoning: Boolean(modelReasoningEffort),\n }),\n threadOptions: {\n ...(threadModel ? { model: threadModel } : {}),\n workingDirectory: cwd,\n skipGitRepoCheck: true,\n ...(modelReasoningEffort ? { modelReasoningEffort } : {}),\n },\n };\n logCodexRuntimeConfig({\n bridgeModelProvider,\n config,\n externalModelProvider,\n providerLocalModel,\n requestedThreadModel,\n sessionMetadata,\n threadModel,\n });\n return config;\n };\n}\n\nfunction resolveReusableThreadId(\n sessionMetadata: Record<string, unknown>,\n threadModelScope: string,\n): string | null {\n const threadId = readString(sessionMetadata.codex_thread_id);\n if (!threadId) {\n return null;\n }\n const threadScope = readString(sessionMetadata.codex_thread_model);\n if (!threadScope) {\n return null;\n }\n return threadScope === threadModelScope ? threadId : null;\n}\n\nfunction readString(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction stripProviderPrefix(value: string | undefined): string | undefined {\n const normalized = readString(value);\n if (!normalized) {\n return undefined;\n }\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex <= 0) {\n return normalized;\n }\n return readString(normalized.slice(slashIndex + 1));\n}\n\nfunction isRuntimeDefaultModelValue(value: string | undefined): boolean {\n return value === RUNTIME_DEFAULT_MODEL_VALUE;\n}\n\nfunction readReasoningEffort(value: unknown): CodexReasoningEffort | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const normalized = value.trim().toLowerCase();\n if (\n normalized === \"minimal\" ||\n normalized === \"low\" ||\n normalized === \"medium\" ||\n normalized === \"high\" ||\n normalized === \"xhigh\"\n ) {\n return normalized;\n }\n return undefined;\n}\n\nfunction readModelProvider(value: string | undefined): string | undefined {\n const normalized = readString(value);\n if (!normalized) {\n return undefined;\n }\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex <= 0) {\n return undefined;\n }\n return readString(normalized.slice(0, slashIndex));\n}\n\nfunction composeModelRoute(params: {\n modelProvider?: string;\n providerLocalModel?: string;\n}): string | undefined {\n const { modelProvider, providerLocalModel } = params;\n if (!modelProvider || !providerLocalModel) {\n return undefined;\n }\n return `${modelProvider}/${providerLocalModel}`;\n}\n\nfunction buildCodexCliConfig(params: {\n apiBase?: string;\n modelProvider?: string;\n showRawAgentReasoning?: boolean;\n}): CodexSdkNcpAgentRuntimeConfig[\"cliConfig\"] | undefined {\n const { apiBase, modelProvider, showRawAgentReasoning } = params;\n if (!modelProvider && !showRawAgentReasoning) {\n return undefined;\n }\n const config: Record<string, unknown> = {};\n if (showRawAgentReasoning) {\n config.show_raw_agent_reasoning = true;\n }\n if (modelProvider) {\n config.model_provider = modelProvider;\n config.preferred_auth_method = \"apikey\";\n }\n if (apiBase && modelProvider) {\n config.model_providers = {\n [modelProvider]: {\n name: modelProvider,\n base_url: apiBase,\n wire_api: \"responses\",\n requires_openai_auth: true,\n },\n };\n }\n return config as CodexSdkNcpAgentRuntimeConfig[\"cliConfig\"];\n}\n\nfunction logCodexRuntimeConfig(params: {\n bridgeModelProvider?: string;\n config: CodexSdkNcpAgentRuntimeConfig;\n externalModelProvider?: string;\n providerLocalModel?: string;\n requestedThreadModel?: string;\n sessionMetadata: Record<string, unknown>;\n threadModel?: string;\n}): void {\n if (process.env[CODEX_NARP_DEBUG_CONFIG_ENV] !== \"1\") {\n return;\n }\n const {\n bridgeModelProvider,\n config,\n externalModelProvider,\n providerLocalModel,\n requestedThreadModel,\n sessionMetadata,\n threadModel,\n } = params;\n const cliConfig = config.cliConfig as Record<string, unknown> | undefined;\n const modelProviders = cliConfig?.model_providers;\n const snapshot = {\n bridgeModelProvider: bridgeModelProvider ?? null,\n externalModelProvider: externalModelProvider ?? null,\n hasApiBase: Boolean(config.apiBase),\n hasApiKey: Boolean(config.apiKey),\n hasLiveOutputStream: Boolean(config.liveOutputStream),\n providerLocalModel: providerLocalModel ?? null,\n requestedThreadModel: requestedThreadModel ?? null,\n sessionId: config.sessionId,\n sessionMetadata: {\n codex_thread_id: readString(sessionMetadata.codex_thread_id) ?? null,\n codex_thread_model: readString(sessionMetadata.codex_thread_model) ?? null,\n model: readString(sessionMetadata.model) ?? null,\n preferred_model: readString(sessionMetadata.preferred_model) ?? null,\n preferred_thinking: readString(sessionMetadata.preferred_thinking) ?? null,\n thinking: readString(sessionMetadata.thinking) ?? null,\n },\n sdkConfig: {\n cliConfig: cliConfig\n ? {\n model_provider: readString(cliConfig.model_provider) ?? null,\n model_providers:\n modelProviders && typeof modelProviders === \"object\" && !Array.isArray(modelProviders)\n ? Object.keys(modelProviders)\n : [],\n preferred_auth_method: readString(cliConfig.preferred_auth_method) ?? null,\n show_raw_agent_reasoning: cliConfig.show_raw_agent_reasoning === true,\n }\n : null,\n model: config.model ?? null,\n threadId: config.threadId ?? null,\n threadOptions: {\n model: config.threadOptions?.model ?? null,\n modelReasoningEffort: config.threadOptions?.modelReasoningEffort ?? null,\n skipGitRepoCheck: config.threadOptions?.skipGitRepoCheck ?? null,\n workingDirectory: config.threadOptions?.workingDirectory ?? null,\n },\n },\n threadModel: threadModel ?? null,\n ts: new Date().toISOString(),\n };\n const line = `[nextclaw-codex-narp] runtime-config ${JSON.stringify(snapshot)}`;\n console.error(line);\n appendDebugLog(snapshot);\n}\n\nfunction appendDebugLog(snapshot: Record<string, unknown>): void {\n try {\n const home = readString(process.env.NEXTCLAW_HOME) ?? join(homedir(), \".nextclaw\");\n const logPath = join(home, \"logs\", \"codex-narp-runtime-config.jsonl\");\n mkdirSync(dirname(logPath), { recursive: true });\n appendFileSync(logPath, `${JSON.stringify(snapshot)}\\n`, \"utf8\");\n } catch (error) {\n console.error(\n `[nextclaw-codex-narp] failed to write runtime config debug log: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n}\n\nfunction readApiMode(headers: Record<string, string> | undefined): string | undefined {\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (key.toLowerCase() === NARP_API_MODE_HEADER) {\n return readString(value)?.toLowerCase();\n }\n }\n return undefined;\n}\n\nfunction shouldUseResponsesBridge(params: {\n apiBase?: string;\n headers?: Record<string, string>;\n}): boolean {\n const apiMode = readApiMode(params.headers);\n if (apiMode === \"chat_completions\") {\n return true;\n }\n return Boolean(params.apiBase && isMiniMaxApiBase(params.apiBase));\n}\n\nfunction stripInternalRouteHeaders(\n headers: Record<string, string> | undefined,\n): Record<string, string> | undefined {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers ?? {})) {\n if (key.toLowerCase() === NARP_API_MODE_HEADER) {\n continue;\n }\n out[key] = value;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction resolveExternalModelProvider(params: {\n apiBase?: string;\n modelId?: string;\n}): string | undefined {\n return readModelProvider(params.modelId) ??\n (params.apiBase && isMiniMaxApiBase(params.apiBase) ? \"minimax\" : undefined);\n}\n\nfunction isMiniMaxApiBase(apiBase: string): boolean {\n try {\n const host = new URL(apiBase).hostname.toLowerCase();\n return host === \"api.minimaxi.com\" || host.endsWith(\".minimaxi.com\");\n } catch {\n return apiBase.toLowerCase().includes(\"api.minimaxi.com\");\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/nextclaw-narp-runtime-codex-sdk",
3
- "version": "0.1.33-beta.0",
3
+ "version": "0.1.33-beta.1",
4
4
  "private": false,
5
5
  "description": "NARP stdio launcher for the NextClaw Codex SDK runtime.",
6
6
  "type": "module",
@@ -19,9 +19,9 @@
19
19
  "README.md"
20
20
  ],
21
21
  "dependencies": {
22
- "@nextclaw/nextclaw-narp-stdio-runtime-wrapper": "0.2.14-beta.0",
23
- "@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.55-beta.0",
24
- "@nextclaw/ncp": "0.6.4-beta.0"
22
+ "@nextclaw/nextclaw-ncp-runtime-codex-sdk": "0.1.55-beta.1",
23
+ "@nextclaw/nextclaw-narp-stdio-runtime-wrapper": "0.2.14-beta.1",
24
+ "@nextclaw/ncp": "0.6.4-beta.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^20.17.6",