pi-harness-runtime 0.10.23 → 0.10.25

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/package.json +1 -1
  3. package/packages/file-copy-helper/src/extension.js +98 -0
  4. package/packages/file-copy-helper/src/extension.ts +60 -12
  5. package/packages/todo-bd-sync/dist/src/detector.js +108 -0
  6. package/packages/todo-bd-sync/src/detector.ts +1 -1
  7. package/packages/auth/src/minimax-browser-auth.js +0 -889
  8. package/packages/capability-registry/src/types.js +0 -10
  9. package/packages/checkpoint/src/checkpoint-manager.js +0 -29
  10. package/packages/clipboard/src/copy-sync.js +0 -169
  11. package/packages/clipboard/src/gist-relay.js +0 -185
  12. package/packages/clipboard/src/github-login.js +0 -68
  13. package/packages/config-capture/src/index.js +0 -268
  14. package/packages/cookie-sanitizer/src/atomic-write.js +0 -66
  15. package/packages/cookie-sanitizer/src/detect-format.js +0 -87
  16. package/packages/cookie-sanitizer/src/index.js +0 -38
  17. package/packages/cookie-sanitizer/src/infer-provider.js +0 -95
  18. package/packages/cookie-sanitizer/src/normalize.js +0 -74
  19. package/packages/cookie-sanitizer/src/parse-json.js +0 -107
  20. package/packages/cookie-sanitizer/src/parse-netscape.js +0 -98
  21. package/packages/cookie-sanitizer/src/sync.js +0 -268
  22. package/packages/cookie-sanitizer/src/types.js +0 -12
  23. package/packages/cookie-sanitizer/src/watcher.js +0 -147
  24. package/packages/evaluation-engine/src/engine.js +0 -343
  25. package/packages/evaluation-engine/src/index.js +0 -7
  26. package/packages/evaluation-engine/src/types.js +0 -14
  27. package/packages/event-store/src/types.js +0 -5
  28. package/packages/experience-replay/src/index.js +0 -6
  29. package/packages/experience-replay/src/replay.js +0 -228
  30. package/packages/experience-replay/src/types.js +0 -6
  31. package/packages/learning-engine/src/engine.js +0 -294
  32. package/packages/learning-engine/src/index.js +0 -7
  33. package/packages/learning-engine/src/types.js +0 -63
  34. package/packages/memory-engine/src/engine.js +0 -507
  35. package/packages/memory-engine/src/index.js +0 -7
  36. package/packages/memory-engine/src/types.js +0 -39
  37. package/packages/model-registry/src/types.js +0 -5
  38. package/packages/performance-optimizer/src/index.js +0 -6
  39. package/packages/performance-optimizer/src/optimizer.js +0 -304
  40. package/packages/performance-optimizer/src/types.js +0 -6
  41. package/packages/projection-engine/src/types.js +0 -5
  42. package/packages/providers/src/provider-id.js +0 -112
  43. package/packages/quota-manager/src/quota-manager.js +0 -259
  44. package/packages/quota-manager/src/tui-usage-monitor.js +0 -267
  45. package/packages/todo-bd-sync/src/detector.js +0 -131
  46. package/packages/todo-bd-sync/src/extension.js +0 -104
  47. package/packages/todo-bd-sync/src/sync.js +0 -289
  48. package/packages/todo-bd-sync/src/task-analyzer.js +0 -239
  49. package/packages/todo-bd-sync/src/types.js +0 -66
  50. package/packages/token-estimation/src/index.js +0 -114
  51. package/packages/workflow-events/src/types.js +0 -5
  52. package/packages/write-review/src/blackboard.js +0 -228
  53. package/packages/write-review/src/gate.js +0 -137
  54. package/packages/write-review/src/index.js +0 -17
  55. package/packages/write-review/src/injection.js +0 -141
  56. package/packages/write-review/src/review.js +0 -153
  57. package/packages/write-review/src/trigger.js +0 -106
  58. package/packages/write-review/src/types.js +0 -25
@@ -1,507 +0,0 @@
1
- /**
2
- * Memory Engine (RFC-0060)
3
- *
4
- * Manages durable knowledge using Google's Open Knowledge Format (OKF).
5
- */
6
- import { randomUUID } from "node:crypto";
7
- import * as fs from "node:fs/promises";
8
- import * as path from "node:path";
9
- import { RESERVED_FILES } from "./types.js";
10
- import { filterSecrets, AUTHORITY_PRIORITY } from "./types.js";
11
- // --- YAML Frontmatter Parsing -------------------------------------------------
12
- function parseFrontmatter(content) {
13
- const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
14
- if (!match) {
15
- return null;
16
- }
17
- const [, yamlStr, body] = match;
18
- const frontmatter = { type: "" };
19
- const lines = yamlStr.split("\n");
20
- for (const line of lines) {
21
- const colonIdx = line.indexOf(":");
22
- if (colonIdx === -1)
23
- continue;
24
- const key = line.slice(0, colonIdx).trim();
25
- const value = line.slice(colonIdx + 1).trim();
26
- if (value.startsWith("[") && value.endsWith("]")) {
27
- // Array
28
- frontmatter[key] = value
29
- .slice(1, -1)
30
- .split(",")
31
- .map((s) => s.trim());
32
- }
33
- else if (value === "true") {
34
- frontmatter[key] = true;
35
- }
36
- else if (value === "false") {
37
- frontmatter[key] = false;
38
- }
39
- else {
40
- frontmatter[key] = value.replace(/^["']|["']$/g, "");
41
- }
42
- }
43
- return { frontmatter, body: body.trim(), raw: yamlStr };
44
- }
45
- function serializeFrontmatter(data) {
46
- const lines = [];
47
- for (const [key, value] of Object.entries(data)) {
48
- if (value === undefined || value === null)
49
- continue;
50
- if (Array.isArray(value)) {
51
- lines.push(`${key}: [${value.join(", ")}]`);
52
- }
53
- else if (typeof value === "boolean") {
54
- lines.push(`${key}: ${value}`);
55
- }
56
- else if (typeof value === "object") {
57
- lines.push(`${key}: ${JSON.stringify(value)}`);
58
- }
59
- else {
60
- lines.push(`${key}: ${value}`);
61
- }
62
- }
63
- return lines.join("\n");
64
- }
65
- // --- Concept Parsing --------------------------------------------------------
66
- // --- Link Extraction ---------------------------------------------------------
67
- /**
68
- * Extract markdown links from content
69
- * Used for link validation and concept parsing
70
- */
71
- export function extractLinks(markdown) {
72
- const links = [];
73
- // Extract markdown links
74
- const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
75
- let match;
76
- while ((match = linkRegex.exec(markdown)) !== null) {
77
- links.push({
78
- href: match[2],
79
- title: match[1],
80
- });
81
- }
82
- return links;
83
- }
84
- // --- Validation --------------------------------------------------------------
85
- export function validateConcept(content, path) {
86
- const errors = [];
87
- const warnings = [];
88
- // Check for YAML frontmatter
89
- if (!content.startsWith("---")) {
90
- errors.push({
91
- path,
92
- message: "Missing YAML frontmatter",
93
- severity: "error",
94
- });
95
- return { valid: false, errors, warnings };
96
- }
97
- // Parse frontmatter
98
- const parsed = parseFrontmatter(content);
99
- if (!parsed) {
100
- errors.push({
101
- path,
102
- message: "Invalid YAML frontmatter",
103
- severity: "error",
104
- });
105
- return { valid: false, errors, warnings };
106
- }
107
- // Check for required type field
108
- if (!parsed.frontmatter.type) {
109
- errors.push({
110
- path,
111
- message: "Missing required 'type' field in frontmatter",
112
- severity: "error",
113
- });
114
- }
115
- // Check for broken links - extractLinks would be used for validation
116
- // Note: link validation would be done here with filesystem access
117
- return {
118
- valid: errors.length === 0,
119
- errors,
120
- warnings,
121
- };
122
- }
123
- // --- Index Generation ---------------------------------------------------------
124
- function generateIndex(concepts) {
125
- const lines = [
126
- "# Knowledge Index",
127
- "",
128
- `Last updated: ${new Date().toISOString()}`,
129
- "",
130
- "## By Type",
131
- "",
132
- ];
133
- // Group by type
134
- const byType = new Map();
135
- for (const concept of concepts) {
136
- const existing = byType.get(concept.type) || [];
137
- existing.push(concept);
138
- byType.set(concept.type, existing);
139
- }
140
- for (const [type, typeConcepts] of byType) {
141
- lines.push(`### ${type}`);
142
- for (const concept of typeConcepts) {
143
- const title = concept.title || concept.id;
144
- lines.push(`- [[${title}]]`);
145
- }
146
- lines.push("");
147
- }
148
- // Group by tag
149
- lines.push("## By Tag");
150
- lines.push("");
151
- const byTag = new Map();
152
- for (const concept of concepts) {
153
- for (const tag of concept.tags) {
154
- const existing = byTag.get(tag) || [];
155
- existing.push(concept);
156
- byTag.set(tag, existing);
157
- }
158
- }
159
- for (const [tag, tagConcepts] of byTag) {
160
- lines.push(`### #${tag}`);
161
- for (const concept of tagConcepts) {
162
- const title = concept.title || concept.id;
163
- lines.push(`- [[${title}]]`);
164
- }
165
- lines.push("");
166
- }
167
- return lines.join("\n");
168
- }
169
- // --- Search ------------------------------------------------------------------
170
- function calculateRelevance(concept, query) {
171
- let score = 0;
172
- const matchedOn = [];
173
- // Title match
174
- if (query.text &&
175
- concept.title?.toLowerCase().includes(query.text.toLowerCase())) {
176
- score += 30;
177
- matchedOn.push("title");
178
- }
179
- // Tag match
180
- if (query.tags) {
181
- for (const tag of query.tags) {
182
- if (concept.tags.includes(tag)) {
183
- score += 20;
184
- matchedOn.push("tags");
185
- break;
186
- }
187
- }
188
- }
189
- // Type match
190
- if (query.types && query.types.includes(concept.type)) {
191
- score += 15;
192
- matchedOn.push("type");
193
- }
194
- // Authority match
195
- const authority = concept.metadata?.authority || "unverified";
196
- if (query.authority && query.authority.includes(authority)) {
197
- score += 10 * AUTHORITY_PRIORITY[authority];
198
- matchedOn.push("authority");
199
- }
200
- // Body match
201
- if (query.text &&
202
- concept.body.toLowerCase().includes(query.text.toLowerCase())) {
203
- score += 5;
204
- }
205
- return score;
206
- }
207
- // --- Main Engine -------------------------------------------------------------
208
- export class MemoryEngine {
209
- bundle = null;
210
- ensureBundle() {
211
- if (!this.bundle) {
212
- this.bundle = {
213
- path: "memory://in-memory",
214
- concepts: [],
215
- index: "",
216
- log: "",
217
- directories: [],
218
- };
219
- }
220
- return this.bundle;
221
- }
222
- /**
223
- * Load an OKF bundle from a directory path.
224
- * Recursively reads all .md files, parses frontmatter + body,
225
- * and builds the in-memory concept index.
226
- */
227
- async loadBundle(bundlePath) {
228
- const concepts = [];
229
- const directories = [];
230
- // Walk directory recursively for .md files
231
- async function walkDir(dir) {
232
- let entries;
233
- try {
234
- entries = await fs.readdir(dir, { withFileTypes: true });
235
- }
236
- catch {
237
- return; // Ignore missing directories
238
- }
239
- for (const entry of entries) {
240
- const fullPath = path.join(dir, entry.name);
241
- if (entry.isDirectory()) {
242
- if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
243
- directories.push({
244
- path: path.relative(bundlePath, fullPath),
245
- name: entry.name,
246
- files: [],
247
- subdirectories: [],
248
- });
249
- await walkDir(fullPath);
250
- }
251
- }
252
- else if (entry.name.endsWith(".md") &&
253
- !RESERVED_FILES.includes(entry.name)) {
254
- const content = await fs.readFile(fullPath, "utf-8").catch(() => "");
255
- const parsed = parseFrontmatter(content);
256
- if (parsed && parsed.frontmatter.type) {
257
- const id = path.relative(bundlePath, fullPath).replace(/\.md$/, "");
258
- concepts.push({
259
- id,
260
- type: parsed.frontmatter.type,
261
- title: parsed.frontmatter.title,
262
- description: parsed.frontmatter.description,
263
- resource: parsed.frontmatter.resource,
264
- tags: parsed.frontmatter.tags || [],
265
- timestamp: parsed.frontmatter.timestamp,
266
- metadata: { ...parsed.frontmatter },
267
- body: parsed.body,
268
- links: extractLinks(parsed.body),
269
- });
270
- // Prune OKF-reserved fields from metadata (they are top-level on OkfConcept)
271
- delete concepts[concepts.length - 1].metadata["type"];
272
- delete concepts[concepts.length - 1].metadata["title"];
273
- delete concepts[concepts.length - 1].metadata["tags"];
274
- delete concepts[concepts.length - 1].metadata["timestamp"];
275
- }
276
- }
277
- }
278
- }
279
- await walkDir(bundlePath);
280
- const bundle = {
281
- path: bundlePath,
282
- concepts,
283
- index: "",
284
- log: "",
285
- directories,
286
- };
287
- // Load reserved files: index.md and log.md
288
- const [indexPath, logPath] = ["index.md", "log.md"].map((f) => path.join(bundlePath, f));
289
- try {
290
- bundle.index = await fs.readFile(indexPath, "utf-8");
291
- }
292
- catch {
293
- // No index yet — generate fresh
294
- bundle.index = generateIndex(concepts);
295
- }
296
- try {
297
- bundle.log = await fs.readFile(logPath, "utf-8");
298
- }
299
- catch {
300
- // No log yet — that's fine
301
- }
302
- this.bundle = bundle;
303
- return bundle;
304
- }
305
- /**
306
- * Validate a bundle
307
- */
308
- validateBundle(bundle) {
309
- const errors = [];
310
- const warnings = [];
311
- for (const concept of bundle.concepts) {
312
- if (!concept.type) {
313
- errors.push({
314
- path: concept.id,
315
- message: "Concept missing required 'type' field",
316
- severity: "error",
317
- });
318
- }
319
- }
320
- return {
321
- valid: errors.length === 0,
322
- errors,
323
- warnings,
324
- };
325
- }
326
- /**
327
- * Search for concepts matching a query
328
- */
329
- search(query) {
330
- const bundle = this.ensureBundle();
331
- const results = [];
332
- for (const concept of bundle.concepts) {
333
- // Filter by authority
334
- if (query.authority) {
335
- const authority = concept.metadata?.authority || "unverified";
336
- if (!query.authority.includes(authority)) {
337
- continue;
338
- }
339
- }
340
- // Filter by type
341
- if (query.types && !query.types.includes(concept.type)) {
342
- continue;
343
- }
344
- // Filter by tags
345
- if (query.tags) {
346
- const hasTag = query.tags.some((t) => concept.tags.includes(t));
347
- if (!hasTag) {
348
- continue;
349
- }
350
- }
351
- const relevance = calculateRelevance(concept, query);
352
- if (relevance > 0 || !query.text) {
353
- results.push({
354
- concept,
355
- relevance,
356
- matchedOn: [],
357
- });
358
- }
359
- }
360
- // Sort by relevance
361
- results.sort((a, b) => b.relevance - a.relevance);
362
- // Apply limit
363
- if (query.limit) {
364
- return results.slice(0, query.limit);
365
- }
366
- return results;
367
- }
368
- /**
369
- * Write a new concept (RFC-0060)
370
- *
371
- * Persists to disk at {bundle.path}/{id}.md and updates bundle index.
372
- * File name is derived from the title slug (first 64 chars).
373
- */
374
- async writeConcept(request) {
375
- const id = request.title
376
- ? request.title
377
- .toLowerCase()
378
- .replace(/[^a-z0-9]+/g, "-")
379
- .replace(/^-|-$/g, "")
380
- .slice(0, 64) +
381
- "-" +
382
- randomUUID().slice(0, 8)
383
- : randomUUID();
384
- const timestamp = new Date().toISOString();
385
- const concept = {
386
- id,
387
- type: request.type,
388
- title: request.title,
389
- tags: request.tags || [],
390
- timestamp,
391
- metadata: {
392
- ...request.metadata,
393
- authority: request.authority || "generated",
394
- },
395
- body: request.body,
396
- links: request.links || [],
397
- };
398
- const bundle = this.ensureBundle();
399
- // Persist to disk
400
- if (bundle.path && bundle.path !== "memory://in-memory") {
401
- const filePath = path.join(bundle.path, `${id}.md`);
402
- const okfContent = this.exportToOkf(concept);
403
- await fs.mkdir(bundle.path, { recursive: true });
404
- await fs.writeFile(filePath, okfContent, "utf-8");
405
- }
406
- bundle.concepts.push(concept);
407
- bundle.index = generateIndex(bundle.concepts);
408
- return concept;
409
- }
410
- /**
411
- * Promote a concept from the blackboard
412
- */
413
- promoteFromBlackboard(blackboardContent, metadata) {
414
- // Filter secrets before promoting
415
- const filteredContent = filterSecrets(blackboardContent);
416
- return {
417
- type: metadata.type || "knowledge",
418
- title: metadata.title,
419
- body: filteredContent,
420
- tags: metadata.tags || [],
421
- authority: metadata.authority || "unverified",
422
- metadata,
423
- };
424
- }
425
- /**
426
- * Rebuild the index from disk and persist index.md to bundle directory.
427
- */
428
- async rebuildIndex(bundlePath) {
429
- const targetPath = bundlePath ?? this.bundle?.path;
430
- if (!targetPath || targetPath === "memory://in-memory") {
431
- if (this.bundle) {
432
- this.bundle.index = generateIndex(this.bundle.concepts);
433
- }
434
- return;
435
- }
436
- if (!this.bundle || this.bundle.path !== targetPath) {
437
- await this.loadBundle(targetPath);
438
- }
439
- if (this.bundle) {
440
- this.bundle.index = generateIndex(this.bundle.concepts);
441
- const indexPath = path.join(targetPath, "index.md");
442
- await fs.writeFile(indexPath, this.bundle.index, "utf-8");
443
- }
444
- }
445
- /**
446
- * Get the current bundle
447
- */
448
- getBundle() {
449
- return this.bundle;
450
- }
451
- /**
452
- * Export a concept to OKF format (RFC-0060)
453
- *
454
- * Excludes bundle-level metadata fields (index, log, directories)
455
- * from the concept frontmatter to ensure clean round-trip parsing.
456
- */
457
- exportToOkf(concept) {
458
- // Collect concept-level metadata only, excluding top-level OKF fields
459
- // and any bundle-level reserved fields that might be present.
460
- const reserved = new Set([
461
- "id",
462
- "type",
463
- "title",
464
- "description",
465
- "resource",
466
- "tags",
467
- "timestamp",
468
- "body",
469
- "links",
470
- "index",
471
- "log",
472
- "directories",
473
- ]);
474
- const conceptMetadata = {};
475
- const meta = concept.metadata ?? {};
476
- for (const [k, v] of Object.entries(meta)) {
477
- if (!reserved.has(k)) {
478
- conceptMetadata[k] = v;
479
- }
480
- }
481
- const lines = [
482
- "---",
483
- serializeFrontmatter({
484
- type: concept.type,
485
- title: concept.title,
486
- tags: concept.tags,
487
- timestamp: concept.timestamp,
488
- ...conceptMetadata,
489
- }),
490
- "---",
491
- "",
492
- concept.body,
493
- ];
494
- if (concept.links.length > 0) {
495
- lines.push("");
496
- lines.push("## Links");
497
- for (const link of concept.links) {
498
- lines.push(`- [${link.title || link.href}](${link.href})`);
499
- }
500
- }
501
- return lines.join("\n");
502
- }
503
- }
504
- // --- Factory -----------------------------------------------------------------
505
- export function createMemoryEngine() {
506
- return new MemoryEngine();
507
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Memory Engine (RFC-0060)
3
- *
4
- * Re-exports all public types and classes.
5
- */
6
- export { MemoryEngine, createMemoryEngine, extractLinks } from "./engine.js";
7
- export { validateConcept } from "./engine.js";
@@ -1,39 +0,0 @@
1
- /**
2
- * Memory Engine Types (RFC-0060)
3
- *
4
- * Interfaces for OKF-based knowledge management.
5
- */
6
- // --- Reserved Files -----------------------------------------------------------
7
- export const RESERVED_FILES = ["index.md", "log.md"];
8
- export function isReservedFile(filename) {
9
- return RESERVED_FILES.includes(filename);
10
- }
11
- // --- Secret Detection ---------------------------------------------------------
12
- export const SECRET_PATTERNS = [
13
- /api[_-]?key/i,
14
- /password/i,
15
- /secret/i,
16
- /token/i,
17
- /bearer/i,
18
- /auth/i,
19
- /credential/i,
20
- /private[_-]?key/i,
21
- /access[_-]?token/i,
22
- /refresh[_-]?token/i,
23
- ];
24
- export function containsSecret(value) {
25
- return SECRET_PATTERNS.some((pattern) => pattern.test(value));
26
- }
27
- export function filterSecrets(content) {
28
- return content.replace(/([A-Za-z_][A-Za-z0-9_]*)\s*=\s*([^\n]+)/g, (match, key) => {
29
- if (containsSecret(key)) {
30
- return `${key}=[REDACTED]`;
31
- }
32
- return match;
33
- });
34
- }
35
- export const AUTHORITY_PRIORITY = {
36
- approved: 3,
37
- generated: 2,
38
- unverified: 1,
39
- };
@@ -1,5 +0,0 @@
1
- /**
2
- * Model Registry Types (RFC-0053)
3
- */
4
- export {};
5
- //# sourceMappingURL=types.js.map
@@ -1,6 +0,0 @@
1
- /**
2
- * Performance Optimizer (RFC-0056)
3
- *
4
- * Re-exports all public types and classes.
5
- */
6
- export { PerformanceOptimizer, createPerformanceOptimizer, } from "./optimizer.js";