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
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* // later: handle.stop();
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { existsSync, openSync, readFileSync,
|
|
21
|
+
import { existsSync, openSync, readFileSync, readSync, fstatSync, closeSync } from "node:fs";
|
|
22
22
|
import { homedir } from "node:os";
|
|
23
23
|
import { join } from "node:path";
|
|
24
24
|
import { classifyMessage, parseNewMessages } from "./parser.js";
|
|
@@ -75,6 +75,7 @@ export async function getVisibleMessages(
|
|
|
75
75
|
* 1. Polls session_index.jsonl to detect active session changes
|
|
76
76
|
* 2. Tracks file position so it only reads new lines (no re-read of full file)
|
|
77
77
|
* 3. Calls onMessages with incremental messages each poll cycle
|
|
78
|
+
* 4. Preserves incomplete JSON lines until a complete newline-delimited record arrives
|
|
78
79
|
*/
|
|
79
80
|
export function startWatcher(options: WatcherOptions = {}): WatcherHandle {
|
|
80
81
|
const {
|
|
@@ -89,6 +90,8 @@ export function startWatcher(options: WatcherOptions = {}): WatcherHandle {
|
|
|
89
90
|
let currentFd: ReturnType<typeof openSync> | null = null;
|
|
90
91
|
let currentPath: string | null = null;
|
|
91
92
|
let currentOrdinal = 0;
|
|
93
|
+
let currentBytePos = 0; // Track byte position we're at in the file
|
|
94
|
+
let pendingBytes: Buffer | null = null; // Raw bytes buffer for UTF-8 safety
|
|
92
95
|
let pollCount = 0;
|
|
93
96
|
const maxIdlePolls = options.maxIdlePolls ?? Infinity;
|
|
94
97
|
|
|
@@ -99,11 +102,11 @@ export function startWatcher(options: WatcherOptions = {}): WatcherHandle {
|
|
|
99
102
|
stopped = true;
|
|
100
103
|
if (currentFd !== null) {
|
|
101
104
|
try {
|
|
102
|
-
const { closeSync } = require("node:fs") as typeof import("node:fs");
|
|
103
105
|
closeSync(currentFd);
|
|
104
106
|
} catch {
|
|
105
107
|
// ignore
|
|
106
108
|
}
|
|
109
|
+
currentFd = null;
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
112
|
|
|
@@ -122,43 +125,76 @@ export function startWatcher(options: WatcherOptions = {}): WatcherHandle {
|
|
|
122
125
|
function openRollout(path: string) {
|
|
123
126
|
if (currentFd !== null && currentPath !== path) {
|
|
124
127
|
try {
|
|
125
|
-
const { closeSync } = require("node:fs") as typeof import("node:fs");
|
|
126
128
|
closeSync(currentFd);
|
|
127
129
|
} catch {
|
|
128
130
|
// ignore
|
|
129
131
|
}
|
|
132
|
+
currentFd = null;
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
//
|
|
133
|
-
const stat = statSync(path);
|
|
135
|
+
// Open the file for reading
|
|
134
136
|
currentFd = openSync(path, "r");
|
|
135
137
|
currentPath = path;
|
|
136
138
|
currentOrdinal = 0;
|
|
137
|
-
|
|
139
|
+
currentBytePos = 0;
|
|
140
|
+
pendingBytes = null; // Reset pending buffer for new file
|
|
141
|
+
return currentFd;
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Read new lines from the file, preserving incomplete records.
|
|
146
|
+
* Uses raw byte buffering to safely handle UTF-8 split across reads.
|
|
147
|
+
* Returns complete lines only; incomplete trailing data is kept for next read.
|
|
148
|
+
*/
|
|
140
149
|
function readNewLines(
|
|
141
150
|
fd: number,
|
|
142
|
-
knownSize: number,
|
|
143
151
|
): {
|
|
144
152
|
lines: string[];
|
|
145
|
-
|
|
153
|
+
newBytePos: number;
|
|
146
154
|
} {
|
|
147
|
-
const { readSync, fstatSync } =
|
|
148
|
-
require("node:fs") as typeof import("node:fs");
|
|
149
155
|
const stat = fstatSync(fd);
|
|
150
|
-
const
|
|
156
|
+
const fileSize = stat.size;
|
|
151
157
|
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
// Read from our tracked position to current end of file
|
|
159
|
+
const bytesToRead = fileSize - currentBytePos;
|
|
160
|
+
if (bytesToRead <= 0) {
|
|
161
|
+
return { lines: [], newBytePos: currentBytePos };
|
|
154
162
|
}
|
|
155
163
|
|
|
156
|
-
const buf = Buffer.alloc(
|
|
157
|
-
const bytesRead = readSync(fd, buf, 0, buf.length,
|
|
158
|
-
const text = buf.subarray(0, bytesRead).toString("utf8");
|
|
159
|
-
const lines = text.split("\n").filter((l) => l.trim());
|
|
164
|
+
const buf = Buffer.alloc(bytesToRead);
|
|
165
|
+
const bytesRead = readSync(fd, buf, 0, buf.length, currentBytePos);
|
|
160
166
|
|
|
161
|
-
|
|
167
|
+
// Buffer raw bytes for UTF-8 safety
|
|
168
|
+
if (pendingBytes) {
|
|
169
|
+
// Combine with previous incomplete buffer
|
|
170
|
+
const combined = Buffer.concat([pendingBytes, buf.subarray(0, bytesRead)]);
|
|
171
|
+
pendingBytes = combined;
|
|
172
|
+
} else {
|
|
173
|
+
pendingBytes = buf.subarray(0, bytesRead);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Decode the complete buffer
|
|
177
|
+
const text = pendingBytes.toString("utf8");
|
|
178
|
+
|
|
179
|
+
// Split by newline to find complete records
|
|
180
|
+
const lines = text.split("\n");
|
|
181
|
+
|
|
182
|
+
// If buffer doesn't end with newline, last element is incomplete
|
|
183
|
+
if (!pendingBytes.toString("utf8").endsWith("\n")) {
|
|
184
|
+
// Keep the incomplete line for next read (already in pendingBytes)
|
|
185
|
+
return { lines: [], newBytePos: currentBytePos };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// All lines are complete - emit them and clear buffer
|
|
189
|
+
pendingBytes = null;
|
|
190
|
+
|
|
191
|
+
// Filter out empty lines
|
|
192
|
+
const completeLines = lines.filter((l) => l.trim());
|
|
193
|
+
|
|
194
|
+
// Update our tracked position by bytes actually read
|
|
195
|
+
const newBytePos = currentBytePos + bytesRead;
|
|
196
|
+
|
|
197
|
+
return { lines: completeLines, newBytePos };
|
|
162
198
|
}
|
|
163
199
|
|
|
164
200
|
async function poll() {
|
|
@@ -198,8 +234,9 @@ export function startWatcher(options: WatcherOptions = {}): WatcherHandle {
|
|
|
198
234
|
return;
|
|
199
235
|
}
|
|
200
236
|
|
|
201
|
-
|
|
202
|
-
const { lines } = readNewLines(currentFd
|
|
237
|
+
// Read new lines from our tracked byte position
|
|
238
|
+
const { lines, newBytePos } = readNewLines(currentFd!);
|
|
239
|
+
currentBytePos = newBytePos; // Update tracked position
|
|
203
240
|
|
|
204
241
|
if (lines.length > 0) {
|
|
205
242
|
pollCount = 0;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Session discovery — reads ~/.codex/session_index.jsonl to find active sessions.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
6
6
|
import { homedir } from "node:os";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import type { CodexSession } from "./types.js";
|
|
@@ -69,51 +69,38 @@ function findRolloutPath(sessionId: string, codexDir?: string): string {
|
|
|
69
69
|
// The rollout path follows: sessions/YYYY/MM/DD/rollout-YYYY-MM-DDTHH-MM-SS-<sessionId>.jsonl
|
|
70
70
|
// We need to find the file whose name ends with <sessionId>.jsonl
|
|
71
71
|
// Since there can be multiple sessions per day, iterate all files.
|
|
72
|
-
try {
|
|
73
|
-
const { readdirSync } = require("node:fs") as typeof import("node:fs");
|
|
74
|
-
for (const dirPath of walkDirs(sessionsDir)) {
|
|
75
|
-
for (const file of readdirSync(dirPath)) {
|
|
76
|
-
if (file.endsWith(`${sessionId}.jsonl`)) {
|
|
77
|
-
return join(dirPath, file);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
// walkSync may not be available on all Node versions; fall back to find
|
|
83
|
-
}
|
|
84
|
-
return findRolloutPathFallback(sessionId, sessionsDir);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function findRolloutPathFallback(
|
|
88
|
-
sessionId: string,
|
|
89
|
-
sessionsDir: string,
|
|
90
|
-
): string {
|
|
91
72
|
const found = walkForSession(sessionsDir, sessionId);
|
|
92
|
-
|
|
73
|
+
if (found) return found;
|
|
74
|
+
return join(sessionsDir, "unknown", `${sessionId}.jsonl`);
|
|
93
75
|
}
|
|
94
76
|
|
|
95
77
|
/** Recursively walk all subdirectories, yielding each directory path. */
|
|
96
78
|
function* walkDirs(dir: string): Generator<string> {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
79
|
+
try {
|
|
80
|
+
for (const entry of readdirSync(dir)) {
|
|
81
|
+
const full = join(dir, entry);
|
|
82
|
+
const stat = statSync(full);
|
|
83
|
+
if (stat.isDirectory()) {
|
|
84
|
+
yield full;
|
|
85
|
+
yield* walkDirs(full);
|
|
86
|
+
}
|
|
105
87
|
}
|
|
88
|
+
} catch {
|
|
89
|
+
// Directory may not exist or be readable
|
|
106
90
|
}
|
|
107
91
|
}
|
|
108
92
|
|
|
109
93
|
/** Find the rollout file for a given session ID by walking directories. */
|
|
110
94
|
function walkForSession(sessionsDir: string, sessionId: string): string | null {
|
|
111
|
-
const { readdirSync } = require("node:fs") as typeof import("node:fs");
|
|
112
95
|
for (const dirPath of walkDirs(sessionsDir)) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
96
|
+
try {
|
|
97
|
+
for (const file of readdirSync(dirPath)) {
|
|
98
|
+
if (file.startsWith("rollout-") && file.endsWith(`${sessionId}.jsonl`)) {
|
|
99
|
+
return join(dirPath, file);
|
|
100
|
+
}
|
|
116
101
|
}
|
|
102
|
+
} catch {
|
|
103
|
+
// Skip unreadable directories
|
|
117
104
|
}
|
|
118
105
|
}
|
|
119
106
|
return null;
|