pi-harness-runtime 1.1.252 → 1.1.255
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/index.ts +63 -23
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/dist/src/index.d.ts +1 -0
- package/packages/codex-watcher/dist/src/index.d.ts.map +1 -1
- package/packages/codex-watcher/dist/src/index.js +51 -18
- package/packages/codex-watcher/dist/src/index.js.map +1 -1
- package/packages/codex-watcher/dist/src/session.js +23 -29
- package/packages/codex-watcher/dist/src/session.js.map +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/codex-watcher/src/index.ts +57 -20
- package/packages/codex-watcher/src/session.ts +20 -33
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
package/index.ts
CHANGED
|
@@ -1977,52 +1977,92 @@ export default function (pi: ExtensionAPI) {
|
|
|
1977
1977
|
// Collect promise so we can wait for initialization before showing startup notification
|
|
1978
1978
|
asyncInitPromises.push(initTelegram(pi));
|
|
1979
1979
|
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1980
|
+
// --- codex-watcher: Inject Codex plans into pi.dev + Telegram --------------
|
|
1981
|
+
// Lightweight: polls ~/.codex/sessions/ every 5s, no LangChain daemon.
|
|
1982
|
+
// On plan detected: sends Telegram alert + steer message to pi.dev.
|
|
1983
|
+
try {
|
|
1984
|
+
// Pending delivery queue: messages waiting to be delivered to Pi
|
|
1985
|
+
// Keyed by sessionId, value is array of {ordinal, text, delivered}
|
|
1986
|
+
const pendingDelivery = new Map<string, Array<{ordinal: number; text: string; delivered: boolean}>>();
|
|
1987
|
+
let currentSessionId: string | null = null;
|
|
1988
|
+
|
|
1989
|
+
// Process pending delivery queue - try to deliver queued messages
|
|
1990
|
+
function processDeliveryQueue(sessionId: string) {
|
|
1991
|
+
const queue = pendingDelivery.get(sessionId);
|
|
1992
|
+
if (!queue || queue.length === 0) return;
|
|
1993
|
+
|
|
1994
|
+
// Try to deliver pending messages
|
|
1995
|
+
for (const item of queue) {
|
|
1996
|
+
if (item.delivered) continue;
|
|
1997
|
+
|
|
1998
|
+
try {
|
|
1999
|
+
const planContent = `[Codex plan detected — ordinal ${item.ordinal}]\n\n${item.text}`;
|
|
2000
|
+
pi.sendUserMessage(planContent, { deliverAs: "steer" });
|
|
2001
|
+
item.delivered = true;
|
|
2002
|
+
logToFile("[codex]", `Delivered queued ordinal ${item.ordinal} to Pi`);
|
|
2003
|
+
} catch {
|
|
2004
|
+
// Still failing, will retry on next poll
|
|
2005
|
+
logToFile("[codex]", `Retry failed for ordinal ${item.ordinal}`);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
// Clean up delivered messages from the front of the queue
|
|
2010
|
+
while (queue.length > 0 && queue[0].delivered) {
|
|
2011
|
+
queue.shift();
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
1985
2014
|
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
2015
|
+
const codexHandle = startWatcher({
|
|
2016
|
+
pollIntervalMs: 5000,
|
|
2017
|
+
maxIdlePolls: Infinity,
|
|
2018
|
+
onSessionChange: (session) => {
|
|
1990
2019
|
if (session) {
|
|
1991
2020
|
logToFile("[codex]", `Session started: ${session.threadName}`);
|
|
2021
|
+
currentSessionId = session.id;
|
|
2022
|
+
// Initialize queue for new session
|
|
2023
|
+
if (!pendingDelivery.has(session.id)) {
|
|
2024
|
+
pendingDelivery.set(session.id, []);
|
|
2025
|
+
}
|
|
1992
2026
|
nc("CodexSessionStarted", {
|
|
1993
2027
|
requirement: session.threadName || "Codex session",
|
|
1994
2028
|
taskTitle: session.id,
|
|
1995
2029
|
});
|
|
2030
|
+
} else {
|
|
2031
|
+
currentSessionId = null;
|
|
1996
2032
|
}
|
|
1997
2033
|
},
|
|
1998
2034
|
onMessages: (msgs) => {
|
|
2035
|
+
const sessionId = currentSessionId;
|
|
2036
|
+
if (!sessionId) return;
|
|
2037
|
+
|
|
2038
|
+
// First, try to deliver any pending messages
|
|
2039
|
+
processDeliveryQueue(sessionId);
|
|
2040
|
+
|
|
1999
2041
|
for (const msg of msgs) {
|
|
2000
2042
|
// Skip user messages — only track assistant plans
|
|
2001
2043
|
if (msg.role !== "assistant") continue;
|
|
2002
2044
|
|
|
2003
2045
|
const classification = classifyMessage(msg.text);
|
|
2004
2046
|
if (classification !== "plan" && classification !== "mixed") continue;
|
|
2005
|
-
if (msg.ordinal <= latestPlanOrdinal) continue;
|
|
2006
|
-
|
|
2007
|
-
latestPlanOrdinal = msg.ordinal;
|
|
2008
2047
|
|
|
2009
|
-
// Emit Telegram alert
|
|
2048
|
+
// Emit Telegram alert with preview (include more of the plan)
|
|
2049
|
+
const planPreview = msg.text.slice(0, 800) + (msg.text.length > 800 ? "\n... (full plan forwarded to Pi)" : "");
|
|
2010
2050
|
nc("CodexPlanDetected", {
|
|
2011
|
-
requirement:
|
|
2051
|
+
requirement: planPreview,
|
|
2012
2052
|
taskTitle: `Ordinal ${msg.ordinal}`,
|
|
2013
2053
|
});
|
|
2014
2054
|
|
|
2015
|
-
// Inject plan into pi.dev as a steer message
|
|
2016
|
-
const
|
|
2055
|
+
// Inject full plan into pi.dev as a steer message
|
|
2056
|
+
const planContent = `[Codex plan detected — ordinal ${msg.ordinal}]\n\n${msg.text}`;
|
|
2017
2057
|
try {
|
|
2018
|
-
pi.sendUserMessage(
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
${planPreview}`,
|
|
2022
|
-
{ deliverAs: "steer" },
|
|
2023
|
-
);
|
|
2058
|
+
pi.sendUserMessage(planContent, { deliverAs: "steer" });
|
|
2059
|
+
logToFile("[codex]", `Delivered ordinal ${msg.ordinal} to Pi`);
|
|
2024
2060
|
} catch {
|
|
2025
|
-
//
|
|
2061
|
+
// Add to pending queue for retry
|
|
2062
|
+
const queue = pendingDelivery.get(sessionId) ?? [];
|
|
2063
|
+
queue.push({ ordinal: msg.ordinal, text: msg.text, delivered: false });
|
|
2064
|
+
pendingDelivery.set(sessionId, queue);
|
|
2065
|
+
logToFile("[codex]", `Delivery failed for ordinal ${msg.ordinal}, queued for retry`);
|
|
2026
2066
|
}
|
|
2027
2067
|
}
|
|
2028
2068
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.255",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -37,6 +37,7 @@ export declare function getVisibleMessages(rolloutPath: string, options?: {
|
|
|
37
37
|
* 1. Polls session_index.jsonl to detect active session changes
|
|
38
38
|
* 2. Tracks file position so it only reads new lines (no re-read of full file)
|
|
39
39
|
* 3. Calls onMessages with incremental messages each poll cycle
|
|
40
|
+
* 4. Preserves incomplete JSON lines until a complete newline-delimited record arrives
|
|
40
41
|
*/
|
|
41
42
|
export declare function startWatcher(options?: WatcherOptions): WatcherHandle;
|
|
42
43
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AAM7D,oFAAoF;AACpF,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,OAAO,CAAC,YAAY,EAAE,CAAC,CAkBzB;AAMD
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAE,eAAe,EAAoB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EACX,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,cAAc,EACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC;AAM7D,oFAAoF;AACpF,wBAAsB,kBAAkB,CACvC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,OAAO,CAAC,YAAY,EAAE,CAAC,CAkBzB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,cAAmB,GAAG,aAAa,CAiMxE"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* });
|
|
18
18
|
* // later: handle.stop();
|
|
19
19
|
*/
|
|
20
|
-
import { existsSync, openSync, readFileSync,
|
|
20
|
+
import { existsSync, openSync, readFileSync, readSync, fstatSync, closeSync } from "node:fs";
|
|
21
21
|
import { homedir } from "node:os";
|
|
22
22
|
import { join } from "node:path";
|
|
23
23
|
import { classifyMessage, parseNewMessages } from "./parser.js";
|
|
@@ -57,6 +57,7 @@ export async function getVisibleMessages(rolloutPath, options = {}) {
|
|
|
57
57
|
* 1. Polls session_index.jsonl to detect active session changes
|
|
58
58
|
* 2. Tracks file position so it only reads new lines (no re-read of full file)
|
|
59
59
|
* 3. Calls onMessages with incremental messages each poll cycle
|
|
60
|
+
* 4. Preserves incomplete JSON lines until a complete newline-delimited record arrives
|
|
60
61
|
*/
|
|
61
62
|
export function startWatcher(options = {}) {
|
|
62
63
|
const { pollIntervalMs = 2000, codexDir, onMessages, onSessionChange, } = options;
|
|
@@ -65,6 +66,8 @@ export function startWatcher(options = {}) {
|
|
|
65
66
|
let currentFd = null;
|
|
66
67
|
let currentPath = null;
|
|
67
68
|
let currentOrdinal = 0;
|
|
69
|
+
let currentBytePos = 0; // Track byte position we're at in the file
|
|
70
|
+
let pendingBytes = null; // Raw bytes buffer for UTF-8 safety
|
|
68
71
|
let pollCount = 0;
|
|
69
72
|
const maxIdlePolls = options.maxIdlePolls ?? Infinity;
|
|
70
73
|
// Track last known session to detect changes
|
|
@@ -73,12 +76,12 @@ export function startWatcher(options = {}) {
|
|
|
73
76
|
stopped = true;
|
|
74
77
|
if (currentFd !== null) {
|
|
75
78
|
try {
|
|
76
|
-
const { closeSync } = require("node:fs");
|
|
77
79
|
closeSync(currentFd);
|
|
78
80
|
}
|
|
79
81
|
catch {
|
|
80
82
|
// ignore
|
|
81
83
|
}
|
|
84
|
+
currentFd = null;
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
function isRunning() {
|
|
@@ -93,32 +96,61 @@ export function startWatcher(options = {}) {
|
|
|
93
96
|
function openRollout(path) {
|
|
94
97
|
if (currentFd !== null && currentPath !== path) {
|
|
95
98
|
try {
|
|
96
|
-
const { closeSync } = require("node:fs");
|
|
97
99
|
closeSync(currentFd);
|
|
98
100
|
}
|
|
99
101
|
catch {
|
|
100
102
|
// ignore
|
|
101
103
|
}
|
|
104
|
+
currentFd = null;
|
|
102
105
|
}
|
|
103
|
-
//
|
|
104
|
-
const stat = statSync(path);
|
|
106
|
+
// Open the file for reading
|
|
105
107
|
currentFd = openSync(path, "r");
|
|
106
108
|
currentPath = path;
|
|
107
109
|
currentOrdinal = 0;
|
|
108
|
-
|
|
110
|
+
currentBytePos = 0;
|
|
111
|
+
pendingBytes = null; // Reset pending buffer for new file
|
|
112
|
+
return currentFd;
|
|
109
113
|
}
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Read new lines from the file, preserving incomplete records.
|
|
116
|
+
* Uses raw byte buffering to safely handle UTF-8 split across reads.
|
|
117
|
+
* Returns complete lines only; incomplete trailing data is kept for next read.
|
|
118
|
+
*/
|
|
119
|
+
function readNewLines(fd) {
|
|
112
120
|
const stat = fstatSync(fd);
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
121
|
+
const fileSize = stat.size;
|
|
122
|
+
// Read from our tracked position to current end of file
|
|
123
|
+
const bytesToRead = fileSize - currentBytePos;
|
|
124
|
+
if (bytesToRead <= 0) {
|
|
125
|
+
return { lines: [], newBytePos: currentBytePos };
|
|
116
126
|
}
|
|
117
|
-
const buf = Buffer.alloc(
|
|
118
|
-
const bytesRead = readSync(fd, buf, 0, buf.length,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
127
|
+
const buf = Buffer.alloc(bytesToRead);
|
|
128
|
+
const bytesRead = readSync(fd, buf, 0, buf.length, currentBytePos);
|
|
129
|
+
// Buffer raw bytes for UTF-8 safety
|
|
130
|
+
if (pendingBytes) {
|
|
131
|
+
// Combine with previous incomplete buffer
|
|
132
|
+
const combined = Buffer.concat([pendingBytes, buf.subarray(0, bytesRead)]);
|
|
133
|
+
pendingBytes = combined;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
pendingBytes = buf.subarray(0, bytesRead);
|
|
137
|
+
}
|
|
138
|
+
// Decode the complete buffer
|
|
139
|
+
const text = pendingBytes.toString("utf8");
|
|
140
|
+
// Split by newline to find complete records
|
|
141
|
+
const lines = text.split("\n");
|
|
142
|
+
// If buffer doesn't end with newline, last element is incomplete
|
|
143
|
+
if (!pendingBytes.toString("utf8").endsWith("\n")) {
|
|
144
|
+
// Keep the incomplete line for next read (already in pendingBytes)
|
|
145
|
+
return { lines: [], newBytePos: currentBytePos };
|
|
146
|
+
}
|
|
147
|
+
// All lines are complete - emit them and clear buffer
|
|
148
|
+
pendingBytes = null;
|
|
149
|
+
// Filter out empty lines
|
|
150
|
+
const completeLines = lines.filter((l) => l.trim());
|
|
151
|
+
// Update our tracked position by bytes actually read
|
|
152
|
+
const newBytePos = currentBytePos + bytesRead;
|
|
153
|
+
return { lines: completeLines, newBytePos };
|
|
122
154
|
}
|
|
123
155
|
async function poll() {
|
|
124
156
|
if (stopped)
|
|
@@ -155,8 +187,9 @@ export function startWatcher(options = {}) {
|
|
|
155
187
|
}
|
|
156
188
|
return;
|
|
157
189
|
}
|
|
158
|
-
|
|
159
|
-
const { lines } = readNewLines(currentFd
|
|
190
|
+
// Read new lines from our tracked byte position
|
|
191
|
+
const { lines, newBytePos } = readNewLines(currentFd);
|
|
192
|
+
currentBytePos = newBytePos; // Update tracked position
|
|
160
193
|
if (lines.length > 0) {
|
|
161
194
|
pollCount = 0;
|
|
162
195
|
const messages = parseNewMessages(lines, currentOrdinal);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session discovery — reads ~/.codex/session_index.jsonl to find active sessions.
|
|
3
3
|
*/
|
|
4
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
/** Find the most recently active Codex session. */
|
|
@@ -60,46 +60,40 @@ function findRolloutPath(sessionId, codexDir) {
|
|
|
60
60
|
// The rollout path follows: sessions/YYYY/MM/DD/rollout-YYYY-MM-DDTHH-MM-SS-<sessionId>.jsonl
|
|
61
61
|
// We need to find the file whose name ends with <sessionId>.jsonl
|
|
62
62
|
// Since there can be multiple sessions per day, iterate all files.
|
|
63
|
-
try {
|
|
64
|
-
const { readdirSync } = require("node:fs");
|
|
65
|
-
for (const dirPath of walkDirs(sessionsDir)) {
|
|
66
|
-
for (const file of readdirSync(dirPath)) {
|
|
67
|
-
if (file.endsWith(`${sessionId}.jsonl`)) {
|
|
68
|
-
return join(dirPath, file);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// walkSync may not be available on all Node versions; fall back to find
|
|
75
|
-
}
|
|
76
|
-
return findRolloutPathFallback(sessionId, sessionsDir);
|
|
77
|
-
}
|
|
78
|
-
function findRolloutPathFallback(sessionId, sessionsDir) {
|
|
79
63
|
const found = walkForSession(sessionsDir, sessionId);
|
|
80
|
-
|
|
64
|
+
if (found)
|
|
65
|
+
return found;
|
|
66
|
+
return join(sessionsDir, "unknown", `${sessionId}.jsonl`);
|
|
81
67
|
}
|
|
82
68
|
/** Recursively walk all subdirectories, yielding each directory path. */
|
|
83
69
|
function* walkDirs(dir) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
70
|
+
try {
|
|
71
|
+
for (const entry of readdirSync(dir)) {
|
|
72
|
+
const full = join(dir, entry);
|
|
73
|
+
const stat = statSync(full);
|
|
74
|
+
if (stat.isDirectory()) {
|
|
75
|
+
yield full;
|
|
76
|
+
yield* walkDirs(full);
|
|
77
|
+
}
|
|
91
78
|
}
|
|
92
79
|
}
|
|
80
|
+
catch {
|
|
81
|
+
// Directory may not exist or be readable
|
|
82
|
+
}
|
|
93
83
|
}
|
|
94
84
|
/** Find the rollout file for a given session ID by walking directories. */
|
|
95
85
|
function walkForSession(sessionsDir, sessionId) {
|
|
96
|
-
const { readdirSync } = require("node:fs");
|
|
97
86
|
for (const dirPath of walkDirs(sessionsDir)) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
87
|
+
try {
|
|
88
|
+
for (const file of readdirSync(dirPath)) {
|
|
89
|
+
if (file.startsWith("rollout-") && file.endsWith(`${sessionId}.jsonl`)) {
|
|
90
|
+
return join(dirPath, file);
|
|
91
|
+
}
|
|
101
92
|
}
|
|
102
93
|
}
|
|
94
|
+
catch {
|
|
95
|
+
// Skip unreadable directories
|
|
96
|
+
}
|
|
103
97
|
}
|
|
104
98
|
return null;
|
|
105
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
|