labgate 0.5.31 → 0.5.32

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 (70) hide show
  1. package/README.md +48 -0
  2. package/dist/cli.js +533 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/lib/config.d.ts +11 -0
  5. package/dist/lib/config.js +44 -0
  6. package/dist/lib/config.js.map +1 -1
  7. package/dist/lib/container.d.ts +3 -3
  8. package/dist/lib/container.js +117 -8
  9. package/dist/lib/container.js.map +1 -1
  10. package/dist/lib/display-mcp.d.ts +10 -0
  11. package/dist/lib/display-mcp.js +160 -0
  12. package/dist/lib/display-mcp.js.map +1 -0
  13. package/dist/lib/display-store.d.ts +24 -0
  14. package/dist/lib/display-store.js +150 -0
  15. package/dist/lib/display-store.js.map +1 -0
  16. package/dist/lib/explorer-autopilot.d.ts +16 -0
  17. package/dist/lib/explorer-autopilot.js +573 -0
  18. package/dist/lib/explorer-autopilot.js.map +1 -0
  19. package/dist/lib/explorer-claude.d.ts +16 -0
  20. package/dist/lib/explorer-claude.js +361 -0
  21. package/dist/lib/explorer-claude.js.map +1 -0
  22. package/dist/lib/explorer-compare.d.ts +9 -0
  23. package/dist/lib/explorer-compare.js +190 -0
  24. package/dist/lib/explorer-compare.js.map +1 -0
  25. package/dist/lib/explorer-eval.d.ts +23 -0
  26. package/dist/lib/explorer-eval.js +161 -0
  27. package/dist/lib/explorer-eval.js.map +1 -0
  28. package/dist/lib/explorer-gc.d.ts +11 -0
  29. package/dist/lib/explorer-gc.js +304 -0
  30. package/dist/lib/explorer-gc.js.map +1 -0
  31. package/dist/lib/explorer-git.d.ts +14 -0
  32. package/dist/lib/explorer-git.js +136 -0
  33. package/dist/lib/explorer-git.js.map +1 -0
  34. package/dist/lib/explorer-lock.d.ts +5 -0
  35. package/dist/lib/explorer-lock.js +100 -0
  36. package/dist/lib/explorer-lock.js.map +1 -0
  37. package/dist/lib/explorer-mcp.d.ts +11 -0
  38. package/dist/lib/explorer-mcp.js +611 -0
  39. package/dist/lib/explorer-mcp.js.map +1 -0
  40. package/dist/lib/explorer-retention.d.ts +4 -0
  41. package/dist/lib/explorer-retention.js +58 -0
  42. package/dist/lib/explorer-retention.js.map +1 -0
  43. package/dist/lib/explorer-store.d.ts +77 -0
  44. package/dist/lib/explorer-store.js +950 -0
  45. package/dist/lib/explorer-store.js.map +1 -0
  46. package/dist/lib/explorer-types.d.ts +161 -0
  47. package/dist/lib/explorer-types.js +3 -0
  48. package/dist/lib/explorer-types.js.map +1 -0
  49. package/dist/lib/explorer.d.ts +31 -0
  50. package/dist/lib/explorer.js +247 -0
  51. package/dist/lib/explorer.js.map +1 -0
  52. package/dist/lib/results-store.js +37 -3
  53. package/dist/lib/results-store.js.map +1 -1
  54. package/dist/lib/test/integration-harness.js +1 -1
  55. package/dist/lib/test/integration-harness.js.map +1 -1
  56. package/dist/lib/ui.html +4800 -1997
  57. package/dist/lib/ui.js +893 -30
  58. package/dist/lib/ui.js.map +1 -1
  59. package/dist/mcp-bundles/display-mcp.bundle.mjs +30209 -0
  60. package/dist/mcp-bundles/explorer-mcp.bundle.mjs +40044 -0
  61. package/dist/mcp-bundles/results-mcp.bundle.mjs +30 -4
  62. package/package.json +3 -2
  63. package/templates/tsp-lab/API_CONTRACT.md +20 -0
  64. package/templates/tsp-lab/EVAL.md +20 -0
  65. package/templates/tsp-lab/PROBLEM.md +18 -0
  66. package/templates/tsp-lab/data/generate_instances.py +51 -0
  67. package/templates/tsp-lab/data/instances.jsonl +12 -0
  68. package/templates/tsp-lab/eval.py +148 -0
  69. package/templates/tsp-lab/solver.py +88 -0
  70. package/templates/tsp-lab/stub-patches/enable_two_opt.patch +14 -0
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * LabGate Display MCP Server
4
+ *
5
+ * A Model Context Protocol server that allows Claude to render rich
6
+ * interactive content (markdown, tables, plots, molecular structures,
7
+ * DNA/protein sequences) directly in the LabGate web UI.
8
+ *
9
+ * Usage: node dist/lib/display-mcp.js [--db /path/to/display.json]
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.main = main;
13
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
14
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
15
+ const zod_1 = require("zod");
16
+ const display_store_js_1 = require("./display-store.js");
17
+ function asText(text) {
18
+ return {
19
+ content: [{ type: 'text', text }],
20
+ };
21
+ }
22
+ function asError(text) {
23
+ return {
24
+ content: [{ type: 'text', text }],
25
+ isError: true,
26
+ };
27
+ }
28
+ function parseDbPathFromArgs(args) {
29
+ let dbPath;
30
+ for (let i = 0; i < args.length; i++) {
31
+ const arg = args[i];
32
+ if (arg === '--db') {
33
+ const next = args[i + 1];
34
+ if (!next)
35
+ throw new Error('Missing value for --db');
36
+ dbPath = next;
37
+ i++;
38
+ continue;
39
+ }
40
+ if (arg.startsWith('--db=')) {
41
+ const inline = arg.slice('--db='.length);
42
+ if (!inline)
43
+ throw new Error('Missing value for --db');
44
+ dbPath = inline;
45
+ }
46
+ }
47
+ return dbPath;
48
+ }
49
+ const WIDGET_TYPES = [
50
+ 'markdown',
51
+ 'table',
52
+ 'plot',
53
+ 'image',
54
+ 'pdf',
55
+ 'molecule',
56
+ 'sequence',
57
+ 'alignment',
58
+ 'file_preview',
59
+ 'tree',
60
+ 'heatmap',
61
+ 'tracks',
62
+ 'domains',
63
+ 'network',
64
+ ];
65
+ async function main(args = process.argv.slice(2)) {
66
+ const dbPath = parseDbPathFromArgs(args);
67
+ if (!dbPath)
68
+ throw new Error('--db argument is required');
69
+ const store = new display_store_js_1.DisplayStore(dbPath);
70
+ const server = new mcp_js_1.McpServer({
71
+ name: 'labgate-display',
72
+ version: '1.0.0',
73
+ }, {
74
+ capabilities: {
75
+ tools: {},
76
+ },
77
+ instructions: 'LabGate display widgets. Use display_widget to render rich interactive content ' +
78
+ 'directly in the LabGate web UI — markdown with formatting, data tables, Plotly charts, ' +
79
+ '3D molecular structures (PDB), PDF documents, DNA/RNA/protein sequences with coloring, ' +
80
+ 'multiple sequence alignments, phylogenetic trees, clustered heatmaps, ' +
81
+ 'genome feature tracks, protein domain architectures, network graphs, ' +
82
+ 'images, and file previews. ' +
83
+ 'The widget appears inline in the chat transcript for the researcher to interact with.',
84
+ });
85
+ // ── Tool: display_widget ──────────────────────────────
86
+ server.registerTool('display_widget', {
87
+ title: 'Display Widget',
88
+ description: 'Render rich interactive content in the LabGate web UI. ' +
89
+ 'Supported widget types:\n' +
90
+ '- markdown: Formatted text with headings, code blocks, tables, math\n' +
91
+ '- table: Structured data table with sortable columns\n' +
92
+ '- plot: Interactive chart (Plotly.js specification)\n' +
93
+ '- image: Display an image from the container filesystem\n' +
94
+ '- pdf: PDF document viewer with page navigation\n' +
95
+ '- molecule: 3D molecular structure viewer (PDB ID, inline data, or file)\n' +
96
+ '- sequence: Colored DNA/RNA/protein sequence display\n' +
97
+ '- alignment: Multiple sequence alignment with conservation highlighting\n' +
98
+ '- file_preview: Preview of CSV, TSV, FASTA, or other data files\n' +
99
+ '- tree: Phylogenetic tree from Newick format string\n' +
100
+ '- heatmap: Clustered heatmap with optional dendrograms\n' +
101
+ '- tracks: Genome feature track viewer (GFF3, BED, VCF via igv.js)\n' +
102
+ '- domains: Protein domain/feature architecture diagram\n' +
103
+ '- network: Interactive network/graph visualization\n\n' +
104
+ 'Data shapes per widget type:\n' +
105
+ ' markdown: { content: string }\n' +
106
+ ' table: { columns: string[], rows: (string|number)[][], caption?: string }\n' +
107
+ ' plot: { plotly: { data: PlotlyTrace[], layout?: PlotlyLayout } }\n' +
108
+ ' image: { path: string, alt?: string, caption?: string }\n' +
109
+ ' pdf: { path: string, page?: number }\n' +
110
+ ' molecule: { pdb_id?: string, pdb_data?: string, path?: string, style?: "cartoon"|"ball-and-stick"|"surface" }\n' +
111
+ ' sequence: { sequence: string, type: "dna"|"rna"|"protein", label?: string }\n' +
112
+ ' alignment: { sequences: { id: string, seq: string }[], format?: "clustal"|"fasta" }\n' +
113
+ ' file_preview: { path: string, format?: string, head_lines?: number }\n' +
114
+ ' tree: { newick: string, layout?: "rectangular"|"radial" }\n' +
115
+ ' heatmap: { matrix: number[][], row_labels?: string[], col_labels?: string[], colorscale?: "viridis"|"inferno"|"plasma"|"blues"|"reds", cluster_rows?: boolean, cluster_cols?: boolean }\n' +
116
+ ' tracks: { genome?: string, locus?: string, tracks: { name: string, path?: string, url?: string, format: string }[] }\n' +
117
+ ' domains: { length: number, label?: string, features: { type: string, name: string, start: number, end: number, color?: string }[] }\n' +
118
+ ' network: { nodes: { id: string, label?: string, color?: string }[], edges: { source: string, target: string, label?: string, weight?: number }[], layout?: "cose"|"circle"|"grid"|"concentric"|"breadthfirst", directed?: boolean }',
119
+ inputSchema: {
120
+ widget: zod_1.z.enum(WIDGET_TYPES).describe('Widget type to render'),
121
+ title: zod_1.z.string().optional().describe('Optional title displayed above the widget'),
122
+ data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).describe('Widget-specific data payload (see tool description for shapes per widget type)'),
123
+ },
124
+ }, async ({ widget, title, data }) => {
125
+ try {
126
+ // Validate payload size — reject oversized inline data
127
+ const payloadSize = JSON.stringify(data).length;
128
+ if (payloadSize > 256_000) {
129
+ return asError(`Widget data too large (${Math.round(payloadSize / 1024)}KB). ` +
130
+ 'For large files, use a path reference instead of inline data.');
131
+ }
132
+ const event = store.appendEvent({
133
+ widget,
134
+ title: title || null,
135
+ data: data,
136
+ session_id: null,
137
+ });
138
+ const label = title ? `"${title}"` : widget;
139
+ return asText(`Widget ${label} displayed (id: ${event.id}).`);
140
+ }
141
+ catch (err) {
142
+ return asError(`Failed to display widget: ${err.message}`);
143
+ }
144
+ });
145
+ const transport = new stdio_js_1.StdioServerTransport();
146
+ await server.connect(transport);
147
+ process.on('SIGINT', () => process.exit(0));
148
+ process.on('SIGTERM', () => process.exit(0));
149
+ }
150
+ function isDirectRun() {
151
+ const argv1 = process.argv[1] || '';
152
+ return /(?:^|\/|\\)display-mcp(?:\.bundle)?(?:\.(?:js|mjs))?$/.test(argv1);
153
+ }
154
+ if (isDirectRun()) {
155
+ main(process.argv.slice(2)).catch((err) => {
156
+ console.error('Display MCP server error:', err);
157
+ process.exit(1);
158
+ });
159
+ }
160
+ //# sourceMappingURL=display-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-mcp.js","sourceRoot":"","sources":["../../src/lib/display-mcp.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;AAyDH,oBAoGC;AA3JD,oEAAoE;AACpE,wEAAiF;AACjF,6BAAwB;AACxB,yDAAkD;AAElD,SAAS,MAAM,CAAC,IAAY;IAC1B,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAa;KACvB,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAc;IACzC,IAAI,MAA0B,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACrD,MAAM,GAAG,IAAI,CAAC;YACd,CAAC,EAAE,CAAC;YACJ,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACvD,MAAM,GAAG,MAAM,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,YAAY,GAAG;IACnB,UAAU;IACV,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,UAAU;IACV,UAAU;IACV,WAAW;IACX,cAAc;IACd,MAAM;IACN,SAAS;IACT,QAAQ;IACR,SAAS;IACT,SAAS;CACD,CAAC;AAEJ,KAAK,UAAU,IAAI,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,+BAAY,CAAC,MAAM,CAAC,CAAC;IAEvC,MAAM,MAAM,GAAG,IAAI,kBAAS,CAC1B;QACE,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE,OAAO;KACjB,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;QACD,YAAY,EACV,iFAAiF;YACjF,yFAAyF;YACzF,yFAAyF;YACzF,wEAAwE;YACxE,uEAAuE;YACvE,6BAA6B;YAC7B,uFAAuF;KAC1F,CACF,CAAC;IAEF,yDAAyD;IAEzD,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,yDAAyD;YACzD,2BAA2B;YAC3B,uEAAuE;YACvE,wDAAwD;YACxD,uDAAuD;YACvD,2DAA2D;YAC3D,mDAAmD;YACnD,4EAA4E;YAC5E,wDAAwD;YACxD,2EAA2E;YAC3E,mEAAmE;YACnE,uDAAuD;YACvD,0DAA0D;YAC1D,qEAAqE;YACrE,0DAA0D;YAC1D,wDAAwD;YACxD,gCAAgC;YAChC,mCAAmC;YACnC,+EAA+E;YAC/E,sEAAsE;YACtE,6DAA6D;YAC7D,0CAA0C;YAC1C,mHAAmH;YACnH,iFAAiF;YACjF,yFAAyF;YACzF,0EAA0E;YAC1E,+DAA+D;YAC/D,6LAA6L;YAC7L,0HAA0H;YAC1H,yIAAyI;YACzI,uOAAuO;QACzO,WAAW,EAAE;YACX,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YAC9D,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YAClF,IAAI,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,gFAAgF,CAAC;SACnI;KACF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;QAChC,IAAI,CAAC;YACH,uDAAuD;YACvD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YAChD,IAAI,WAAW,GAAG,OAAO,EAAE,CAAC;gBAC1B,OAAO,OAAO,CACZ,0BAA0B,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO;oBAC/D,+DAA+D,CAChE,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC;gBAC9B,MAAM;gBACN,KAAK,EAAE,KAAK,IAAI,IAAI;gBACpB,IAAI,EAAE,IAA+B;gBACrC,UAAU,EAAE,IAAI;aACjB,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;YAC5C,OAAO,MAAM,CAAC,UAAU,KAAK,mBAAmB,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QAChE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,OAAO,CAAC,6BAA6B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW;IAClB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,OAAO,uDAAuD,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7E,CAAC;AAED,IAAI,WAAW,EAAE,EAAE,CAAC;IAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface DisplayEvent {
2
+ id: string;
3
+ widget: string;
4
+ title: string | null;
5
+ data: Record<string, unknown>;
6
+ session_id: string | null;
7
+ created_at: string;
8
+ }
9
+ export declare class DisplayStore {
10
+ private readonly dbPath;
11
+ constructor(dbPath: string);
12
+ getPath(): string;
13
+ appendEvent(input: {
14
+ widget: string;
15
+ title?: string | null;
16
+ data?: Record<string, unknown>;
17
+ session_id?: string | null;
18
+ }): DisplayEvent;
19
+ listEvents(sessionId?: string): DisplayEvent[];
20
+ clearEvents(): void;
21
+ private ensureFile;
22
+ private readFile;
23
+ private writeFile;
24
+ }
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DisplayStore = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const fs_1 = require("fs");
6
+ const path_1 = require("path");
7
+ const config_js_1 = require("./config.js");
8
+ function isRenameFallbackError(err) {
9
+ const code = err?.code;
10
+ return code === 'EBUSY' || code === 'EXDEV';
11
+ }
12
+ function nowIso() {
13
+ return new Date().toISOString();
14
+ }
15
+ function sanitizeString(value, maxLen) {
16
+ if (typeof value !== 'string')
17
+ return '';
18
+ const trimmed = value.trim();
19
+ return trimmed.length > maxLen ? trimmed.slice(0, maxLen) : trimmed;
20
+ }
21
+ function sanitizeNullableString(value, maxLen) {
22
+ if (value === null || value === undefined)
23
+ return null;
24
+ const normalized = sanitizeString(value, maxLen);
25
+ return normalized || null;
26
+ }
27
+ class DisplayStore {
28
+ dbPath;
29
+ constructor(dbPath) {
30
+ this.dbPath = dbPath;
31
+ this.ensureFile();
32
+ }
33
+ getPath() {
34
+ return this.dbPath;
35
+ }
36
+ appendEvent(input) {
37
+ const widget = sanitizeString(input.widget, 64);
38
+ if (!widget)
39
+ throw new Error('widget type is required');
40
+ const file = this.readFile();
41
+ const event = {
42
+ id: (0, crypto_1.randomUUID)(),
43
+ widget,
44
+ title: sanitizeNullableString(input.title, 240),
45
+ data: (input.data && typeof input.data === 'object' && !Array.isArray(input.data))
46
+ ? input.data
47
+ : {},
48
+ session_id: sanitizeNullableString(input.session_id, 128),
49
+ created_at: nowIso(),
50
+ };
51
+ file.events.push(event);
52
+ // Keep last 200 events to prevent unbounded growth
53
+ if (file.events.length > 200) {
54
+ file.events = file.events.slice(-200);
55
+ }
56
+ this.writeFile(file);
57
+ return event;
58
+ }
59
+ listEvents(sessionId) {
60
+ const events = this.readFile().events;
61
+ if (sessionId) {
62
+ const normalized = sanitizeString(sessionId, 128);
63
+ return events.filter((e) => e.session_id === normalized);
64
+ }
65
+ return events;
66
+ }
67
+ clearEvents() {
68
+ this.writeFile({ version: 1, events: [] });
69
+ }
70
+ ensureFile() {
71
+ (0, config_js_1.ensurePrivateDir)((0, path_1.dirname)(this.dbPath));
72
+ if (!(0, fs_1.existsSync)(this.dbPath)) {
73
+ const initial = { version: 1, events: [] };
74
+ (0, fs_1.writeFileSync)(this.dbPath, JSON.stringify(initial, null, 2) + '\n', {
75
+ encoding: 'utf-8',
76
+ mode: config_js_1.PRIVATE_FILE_MODE,
77
+ });
78
+ (0, config_js_1.ensurePrivateFile)(this.dbPath);
79
+ return;
80
+ }
81
+ (0, config_js_1.ensurePrivateFile)(this.dbPath);
82
+ }
83
+ readFile() {
84
+ this.ensureFile();
85
+ try {
86
+ const raw = (0, fs_1.readFileSync)(this.dbPath, 'utf-8');
87
+ const parsed = JSON.parse(raw || '{}');
88
+ if (!parsed || typeof parsed !== 'object') {
89
+ return { version: 1, events: [] };
90
+ }
91
+ const rows = Array.isArray(parsed.events) ? parsed.events : [];
92
+ const normalized = rows
93
+ .filter((r) => r && typeof r === 'object')
94
+ .map((r) => {
95
+ const id = sanitizeString(r.id, 128);
96
+ const widget = sanitizeString(r.widget, 64);
97
+ if (!id || !widget)
98
+ return null;
99
+ return {
100
+ id,
101
+ widget,
102
+ title: sanitizeNullableString(r.title, 240),
103
+ data: (r.data && typeof r.data === 'object' && !Array.isArray(r.data)) ? r.data : {},
104
+ session_id: sanitizeNullableString(r.session_id, 128),
105
+ created_at: sanitizeString(r.created_at, 64) || nowIso(),
106
+ };
107
+ })
108
+ .filter((r) => r !== null);
109
+ return { version: 1, events: normalized };
110
+ }
111
+ catch {
112
+ return { version: 1, events: [] };
113
+ }
114
+ }
115
+ writeFile(next) {
116
+ const payload = JSON.stringify(next, null, 2) + '\n';
117
+ const tmpPath = (0, path_1.join)((0, path_1.dirname)(this.dbPath), `.${Date.now()}.${process.pid}.${(0, crypto_1.randomUUID)()}.display.tmp`);
118
+ (0, fs_1.writeFileSync)(tmpPath, payload, {
119
+ encoding: 'utf-8',
120
+ mode: config_js_1.PRIVATE_FILE_MODE,
121
+ });
122
+ try {
123
+ (0, fs_1.renameSync)(tmpPath, this.dbPath);
124
+ }
125
+ catch (err) {
126
+ if (!isRenameFallbackError(err)) {
127
+ try {
128
+ (0, fs_1.unlinkSync)(tmpPath);
129
+ }
130
+ catch { /* Best effort cleanup. */ }
131
+ throw err;
132
+ }
133
+ try {
134
+ (0, fs_1.writeFileSync)(this.dbPath, payload, {
135
+ encoding: 'utf-8',
136
+ mode: config_js_1.PRIVATE_FILE_MODE,
137
+ });
138
+ }
139
+ finally {
140
+ try {
141
+ (0, fs_1.unlinkSync)(tmpPath);
142
+ }
143
+ catch { /* Best effort cleanup. */ }
144
+ }
145
+ }
146
+ (0, config_js_1.ensurePrivateFile)(this.dbPath);
147
+ }
148
+ }
149
+ exports.DisplayStore = DisplayStore;
150
+ //# sourceMappingURL=display-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"display-store.js","sourceRoot":"","sources":["../../src/lib/display-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ExplorerStore } from './explorer-store.js';
2
+ import type { RunStatus } from './explorer-types.js';
3
+ export interface AutopilotTickInput {
4
+ experiment_id: string;
5
+ store?: ExplorerStore;
6
+ random?: () => number;
7
+ }
8
+ export interface AutopilotTickResult {
9
+ did_work: boolean;
10
+ message: string;
11
+ run_id?: string;
12
+ status?: RunStatus;
13
+ score?: number;
14
+ is_error?: boolean;
15
+ }
16
+ export declare function autopilotTick(input: AutopilotTickInput): AutopilotTickResult;