context-mode 1.0.147 → 1.0.149
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/build/adapters/codex/index.d.ts +7 -0
- package/build/adapters/codex/index.js +33 -2
- package/build/adapters/types.d.ts +4 -1
- package/build/cli.js +5 -1
- package/build/executor.d.ts +9 -0
- package/build/executor.js +6 -2
- package/build/server.d.ts +12 -0
- package/build/server.js +109 -5
- package/build/session/analytics.d.ts +19 -0
- package/build/session/analytics.js +71 -21
- package/build/session/db.d.ts +44 -0
- package/build/session/db.js +85 -18
- package/build/store-directory.d.ts +56 -0
- package/build/store-directory.js +254 -0
- package/build/store.d.ts +29 -0
- package/build/store.js +46 -0
- package/build/util/project-dir.d.ts +43 -0
- package/build/util/project-dir.js +102 -1
- package/cli.bundle.mjs +165 -152
- package/hooks/session-db.bundle.mjs +5 -5
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server.bundle.mjs +146 -133
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
2
3
|
import * as path from "node:path";
|
|
3
4
|
import { workspaceEnvVarsFor } from "../adapters/detect.js";
|
|
4
5
|
/**
|
|
@@ -156,6 +157,94 @@ export function resolveProjectDirFromTranscript(opts) {
|
|
|
156
157
|
catch { /* file vanished mid-read */ }
|
|
157
158
|
return undefined;
|
|
158
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Issue #45 / c4529042182 — recover the project-cwd from a Codex CLI
|
|
162
|
+
* session log when the spawned MCP child inherits a non-project cwd
|
|
163
|
+
* (e.g. $HOME when Codex was launched from anywhere outside the project).
|
|
164
|
+
*
|
|
165
|
+
* Codex writes its session transcripts to
|
|
166
|
+
* `${CODEX_HOME ?? ~/.codex}/sessions/<uuid>.jsonl`. The first line is a
|
|
167
|
+
* `SessionMeta` JSON struct whose `meta.cwd` field carries the literal
|
|
168
|
+
* project directory the CLI was launched from (see refs/platforms/codex/
|
|
169
|
+
* codex-rs SessionMeta). Codex publishes NO workspace env var to its child
|
|
170
|
+
* MCP processes — so unlike Claude/Pi/Cursor, we have no env signal at all.
|
|
171
|
+
* The session log is the strongest available signal.
|
|
172
|
+
*
|
|
173
|
+
* Mirror of `resolveProjectDirFromTranscript` for Claude Code; differences:
|
|
174
|
+
* • Sessions live flat in `${codexHome}/sessions/*.jsonl` (no per-project
|
|
175
|
+
* encoded subdir like Claude's `~/.claude/projects/<encoded>/`).
|
|
176
|
+
* • The cwd is on `meta.cwd` (nested), not top-level `cwd`.
|
|
177
|
+
*
|
|
178
|
+
* Returns `null` when:
|
|
179
|
+
* • `codexHome` or its `sessions/` subdir does not exist.
|
|
180
|
+
* • No `.jsonl` files exist or none has a parseable `meta.cwd` string.
|
|
181
|
+
* • The newest log is older than `transcriptMaxAgeMs` (multi-window guard).
|
|
182
|
+
* • The resolved `meta.cwd` points at a plugin install path (poisoned).
|
|
183
|
+
*/
|
|
184
|
+
export function resolveCodexSessionCwd(opts) {
|
|
185
|
+
const codexHome = opts?.codexHome ?? process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
|
|
186
|
+
const sessionsDir = path.join(codexHome, "sessions");
|
|
187
|
+
if (!fs.existsSync(sessionsDir))
|
|
188
|
+
return null;
|
|
189
|
+
let bestPath;
|
|
190
|
+
let bestMtime = 0;
|
|
191
|
+
try {
|
|
192
|
+
for (const f of fs.readdirSync(sessionsDir)) {
|
|
193
|
+
if (!f.endsWith(".jsonl"))
|
|
194
|
+
continue;
|
|
195
|
+
const fp = path.join(sessionsDir, f);
|
|
196
|
+
try {
|
|
197
|
+
const m = fs.statSync(fp).mtimeMs;
|
|
198
|
+
if (m > bestMtime) {
|
|
199
|
+
bestMtime = m;
|
|
200
|
+
bestPath = fp;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch { /* skip */ }
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
if (!bestPath)
|
|
210
|
+
return null;
|
|
211
|
+
if (typeof opts?.transcriptMaxAgeMs === "number") {
|
|
212
|
+
const nowMs = opts.now ?? Date.now();
|
|
213
|
+
if (nowMs - bestMtime > opts.transcriptMaxAgeMs)
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
// Read first ~8KB; the SessionMeta JSON is line 1 and small. Stream-cap
|
|
217
|
+
// mirrors `resolveProjectDirFromTranscript` for memory safety on long logs.
|
|
218
|
+
try {
|
|
219
|
+
const fd = fs.openSync(bestPath, "r");
|
|
220
|
+
try {
|
|
221
|
+
const buf = Buffer.alloc(8192);
|
|
222
|
+
const bytes = fs.readSync(fd, buf, 0, buf.length, 0);
|
|
223
|
+
const text = buf.subarray(0, bytes).toString("utf-8");
|
|
224
|
+
const firstLine = text.split("\n", 1)[0];
|
|
225
|
+
if (!firstLine || !firstLine.trim())
|
|
226
|
+
return null;
|
|
227
|
+
try {
|
|
228
|
+
const obj = JSON.parse(firstLine);
|
|
229
|
+
const cwd = obj?.meta?.cwd;
|
|
230
|
+
if (typeof cwd !== "string" || cwd.length === 0)
|
|
231
|
+
return null;
|
|
232
|
+
if (isPluginInstallPath(cwd))
|
|
233
|
+
return null;
|
|
234
|
+
return cwd;
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return null; /* malformed first line */
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
fs.closeSync(fd);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
return null; /* file vanished mid-read */
|
|
246
|
+
}
|
|
247
|
+
}
|
|
159
248
|
/**
|
|
160
249
|
* Pure project-dir resolver. Mirror of the env-var chain inside
|
|
161
250
|
* `src/server.ts getProjectDir()`, but takes its inputs explicitly so the
|
|
@@ -177,7 +266,7 @@ export function resolveProjectDirFromTranscript(opts) {
|
|
|
177
266
|
* operation of project-independent tools (sandbox execute, fetch).
|
|
178
267
|
*/
|
|
179
268
|
export function resolveProjectDir(opts) {
|
|
180
|
-
const { env, cwd, pwd, transcriptsRoot, transcriptMaxAgeMs, nowMs, strictPlatform } = opts;
|
|
269
|
+
const { env, cwd, pwd, transcriptsRoot, transcriptMaxAgeMs, nowMs, strictPlatform, codexHome, } = opts;
|
|
181
270
|
// Build candidate list. Strict path: own workspace vars + universal escape
|
|
182
271
|
// hatch — NO foreign workspace vars, in any order, can win. Non-strict
|
|
183
272
|
// path: frozen legacy literal order for backwards compatibility.
|
|
@@ -198,6 +287,18 @@ export function resolveProjectDir(opts) {
|
|
|
198
287
|
if (fromTranscript && !isPluginInstallPath(fromTranscript))
|
|
199
288
|
return fromTranscript;
|
|
200
289
|
}
|
|
290
|
+
// Issue #45 — Codex has no workspace env var, so when running under
|
|
291
|
+
// strictPlatform="codex" we fall back to the session-log heuristic
|
|
292
|
+
// between env and PWD. Non-codex platforms skip this branch entirely.
|
|
293
|
+
if (strictPlatform === "codex") {
|
|
294
|
+
const fromCodex = resolveCodexSessionCwd({
|
|
295
|
+
codexHome,
|
|
296
|
+
transcriptMaxAgeMs,
|
|
297
|
+
now: nowMs,
|
|
298
|
+
});
|
|
299
|
+
if (fromCodex)
|
|
300
|
+
return fromCodex;
|
|
301
|
+
}
|
|
201
302
|
if (pwd && !isPluginInstallPath(pwd))
|
|
202
303
|
return pwd;
|
|
203
304
|
return cwd;
|