@spences10/pi-context 0.0.2
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/LICENSE +21 -0
- package/README.md +28 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +202 -0
- package/dist/index.js.map +1 -0
- package/dist/store.d.ts +89 -0
- package/dist/store.js +462 -0
- package/dist/store.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scott Spence
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# @spences10/pi-context
|
|
2
|
+
|
|
3
|
+
Local SQLite context sidecar for Pi. Oversized tool output is stored
|
|
4
|
+
in an FTS5-backed database and replaced with a compact receipt that
|
|
5
|
+
the agent can search or retrieve later.
|
|
6
|
+
|
|
7
|
+
## Local development
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pnpm --filter @spences10/pi-context run build
|
|
11
|
+
pi install ./packages/pi-context
|
|
12
|
+
# or for one run only
|
|
13
|
+
pi -e ./packages/pi-context
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Commands/tools
|
|
17
|
+
|
|
18
|
+
- `context_search` — search indexed tool output
|
|
19
|
+
- `context_get` — retrieve exact stored chunks
|
|
20
|
+
- `context_stats` / `/context-stats` — byte accounting and DB stats
|
|
21
|
+
- `context_purge` — delete old indexed output
|
|
22
|
+
|
|
23
|
+
The default DB path is
|
|
24
|
+
`${PI_CODING_AGENT_DIR:-~/.pi/agent}/context.db`. Set
|
|
25
|
+
`MY_PI_CONTEXT_DB` to override it.
|
|
26
|
+
|
|
27
|
+
This is context retrieval/isolation, not a security sandbox. Stored
|
|
28
|
+
text is redacted with `@spences10/pi-redact` before persistence.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ExtensionAPI } from '@mariozechner/pi-coding-agent';
|
|
2
|
+
export default function context_sidecar(pi: ExtensionAPI): void;
|
|
3
|
+
export { get_context_store, is_context_sidecar_enabled, maybe_store_context_output, set_context_sidecar_enabled, should_index_text, } from './store.js';
|
|
4
|
+
export type { ContextSearchResult, ContextStats, StoreContextInput, StoredContextOutput, } from './store.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Type } from 'typebox';
|
|
2
|
+
import { get_context_store, is_context_sidecar_enabled, maybe_store_context_output, set_context_sidecar_enabled, should_index_text, } from './store.js';
|
|
3
|
+
function is_text_content(item) {
|
|
4
|
+
return (!!item &&
|
|
5
|
+
typeof item === 'object' &&
|
|
6
|
+
item.type === 'text' &&
|
|
7
|
+
typeof item.text === 'string');
|
|
8
|
+
}
|
|
9
|
+
function summarize_tool_input(input) {
|
|
10
|
+
if (!input || typeof input !== 'object')
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const json = JSON.stringify(input);
|
|
14
|
+
return json.length > 500 ? `${json.slice(0, 497)}...` : json;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function should_skip_tool(tool_name) {
|
|
21
|
+
return (tool_name === 'context_search' ||
|
|
22
|
+
tool_name === 'context_get' ||
|
|
23
|
+
tool_name === 'context_stats' ||
|
|
24
|
+
tool_name === 'context_purge' ||
|
|
25
|
+
tool_name === 'team');
|
|
26
|
+
}
|
|
27
|
+
function format_search_results(results) {
|
|
28
|
+
if (results.length === 0)
|
|
29
|
+
return 'No indexed context matched.';
|
|
30
|
+
return results
|
|
31
|
+
.map((result, index) => [
|
|
32
|
+
`## ${index + 1}. ${result.title ?? result.chunk_id}`,
|
|
33
|
+
`Source: ${result.source_id} • Chunk: ${result.chunk_id} • Tool: ${result.tool_name}`,
|
|
34
|
+
'',
|
|
35
|
+
result.content,
|
|
36
|
+
].join('\n'))
|
|
37
|
+
.join('\n\n---\n\n');
|
|
38
|
+
}
|
|
39
|
+
function format_stats(stats) {
|
|
40
|
+
return [
|
|
41
|
+
'## context-sidecar stats',
|
|
42
|
+
'',
|
|
43
|
+
`- Enabled: ${is_context_sidecar_enabled()}`,
|
|
44
|
+
`- Sources: ${stats.sources}`,
|
|
45
|
+
`- Chunks: ${stats.chunks}`,
|
|
46
|
+
`- Raw bytes stored: ${stats.bytes_stored}`,
|
|
47
|
+
`- Bytes returned: ${stats.bytes_returned}`,
|
|
48
|
+
`- Bytes saved: ${stats.bytes_saved}`,
|
|
49
|
+
`- Reduction: ${stats.reduction_pct}%`,
|
|
50
|
+
`- DB bytes: ${stats.total_bytes}`,
|
|
51
|
+
].join('\n');
|
|
52
|
+
}
|
|
53
|
+
export default function context_sidecar(pi) {
|
|
54
|
+
set_context_sidecar_enabled(true, { project_path: process.cwd() });
|
|
55
|
+
pi.on('session_start', async (_event, ctx) => {
|
|
56
|
+
set_context_sidecar_enabled(true, {
|
|
57
|
+
project_path: ctx.cwd,
|
|
58
|
+
session_id: undefined,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
pi.on('session_shutdown', async () => {
|
|
62
|
+
set_context_sidecar_enabled(false);
|
|
63
|
+
});
|
|
64
|
+
pi.on('tool_result', async (event) => {
|
|
65
|
+
const tool_name = String(event.toolName ?? 'tool');
|
|
66
|
+
if (should_skip_tool(tool_name))
|
|
67
|
+
return;
|
|
68
|
+
if (!Array.isArray(event.content))
|
|
69
|
+
return;
|
|
70
|
+
const text_items = event.content.filter(is_text_content);
|
|
71
|
+
if (text_items.length === 0)
|
|
72
|
+
return;
|
|
73
|
+
const text = text_items.map((item) => item.text).join('\n');
|
|
74
|
+
if (text.includes('[context-sidecar]'))
|
|
75
|
+
return;
|
|
76
|
+
if (!should_index_text(text))
|
|
77
|
+
return;
|
|
78
|
+
try {
|
|
79
|
+
const stored = maybe_store_context_output({
|
|
80
|
+
text,
|
|
81
|
+
tool_name,
|
|
82
|
+
input_summary: summarize_tool_input(event.input),
|
|
83
|
+
});
|
|
84
|
+
if (!stored)
|
|
85
|
+
return;
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: 'text', text: stored.receipt }],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
pi.registerTool({
|
|
95
|
+
name: 'context_search',
|
|
96
|
+
label: 'Context Search',
|
|
97
|
+
description: 'Search large tool output stored in the local SQLite context sidecar.',
|
|
98
|
+
promptSnippet: 'Search oversized tool output that was indexed into the local context sidecar',
|
|
99
|
+
parameters: Type.Object({
|
|
100
|
+
query: Type.String({ description: 'FTS search query' }),
|
|
101
|
+
source_id: Type.Optional(Type.String({
|
|
102
|
+
description: 'Limit to one indexed source id',
|
|
103
|
+
})),
|
|
104
|
+
tool_name: Type.Optional(Type.String({ description: 'Limit to one tool name' })),
|
|
105
|
+
limit: Type.Optional(Type.Number({
|
|
106
|
+
description: 'Maximum chunks to return, default 5',
|
|
107
|
+
})),
|
|
108
|
+
}),
|
|
109
|
+
async execute(_toolCallId, params) {
|
|
110
|
+
const results = get_context_store().search(params.query, {
|
|
111
|
+
source_id: params.source_id,
|
|
112
|
+
tool_name: params.tool_name,
|
|
113
|
+
limit: params.limit,
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: 'text',
|
|
119
|
+
text: format_search_results(results),
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
details: { count: results.length },
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
pi.registerTool({
|
|
127
|
+
name: 'context_get',
|
|
128
|
+
label: 'Context Get',
|
|
129
|
+
description: 'Retrieve exact chunks from the local SQLite context sidecar.',
|
|
130
|
+
promptSnippet: 'Retrieve exact stored output chunks by source id',
|
|
131
|
+
parameters: Type.Object({
|
|
132
|
+
source_id: Type.String({ description: 'Indexed source id' }),
|
|
133
|
+
chunk_id: Type.Optional(Type.String({ description: 'Optional exact chunk id' })),
|
|
134
|
+
}),
|
|
135
|
+
async execute(_toolCallId, params) {
|
|
136
|
+
const chunks = get_context_store().get(params.source_id, params.chunk_id);
|
|
137
|
+
const text = chunks.length
|
|
138
|
+
? chunks
|
|
139
|
+
.map((chunk) => [
|
|
140
|
+
`## ${chunk.id}`,
|
|
141
|
+
`Source: ${chunk.source_id} • Chunk ${chunk.ordinal}`,
|
|
142
|
+
'',
|
|
143
|
+
chunk.content,
|
|
144
|
+
].join('\n'))
|
|
145
|
+
.join('\n\n---\n\n')
|
|
146
|
+
: 'No chunks found.';
|
|
147
|
+
return {
|
|
148
|
+
content: [{ type: 'text', text }],
|
|
149
|
+
details: { count: chunks.length },
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
pi.registerTool({
|
|
154
|
+
name: 'context_stats',
|
|
155
|
+
label: 'Context Stats',
|
|
156
|
+
description: 'Show byte accounting for the local SQLite context sidecar.',
|
|
157
|
+
parameters: Type.Object({}),
|
|
158
|
+
async execute() {
|
|
159
|
+
const stats = get_context_store().stats();
|
|
160
|
+
return {
|
|
161
|
+
content: [
|
|
162
|
+
{ type: 'text', text: format_stats(stats) },
|
|
163
|
+
],
|
|
164
|
+
details: stats,
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
pi.registerTool({
|
|
169
|
+
name: 'context_purge',
|
|
170
|
+
label: 'Context Purge',
|
|
171
|
+
description: 'Delete indexed context-sidecar output by age or source id.',
|
|
172
|
+
parameters: Type.Object({
|
|
173
|
+
older_than_days: Type.Optional(Type.Number({
|
|
174
|
+
description: 'Delete sources older than this many days; default 14',
|
|
175
|
+
})),
|
|
176
|
+
source_id: Type.Optional(Type.String({ description: 'Delete one source id' })),
|
|
177
|
+
}),
|
|
178
|
+
async execute(_toolCallId, params) {
|
|
179
|
+
const deleted = get_context_store().purge({
|
|
180
|
+
older_than_days: params.older_than_days,
|
|
181
|
+
source_id: params.source_id,
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
content: [
|
|
185
|
+
{
|
|
186
|
+
type: 'text',
|
|
187
|
+
text: `Deleted ${deleted} context source(s).`,
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
details: { deleted },
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
pi.registerCommand('context-stats', {
|
|
195
|
+
description: 'Show context sidecar byte accounting',
|
|
196
|
+
handler: async (_args, ctx) => {
|
|
197
|
+
ctx.ui.notify(format_stats(get_context_store().stats()), 'info');
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
export { get_context_store, is_context_sidecar_enabled, maybe_store_context_output, set_context_sidecar_enabled, should_index_text, } from './store.js';
|
|
202
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export declare const DEFAULT_CONTEXT_MAX_BYTES: number;
|
|
2
|
+
export declare const DEFAULT_CONTEXT_MAX_LINES = 300;
|
|
3
|
+
export interface ContextStoreOptions {
|
|
4
|
+
db_path?: string;
|
|
5
|
+
project_path?: string;
|
|
6
|
+
session_id?: string | null;
|
|
7
|
+
max_bytes?: number;
|
|
8
|
+
max_lines?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface StoreContextInput {
|
|
11
|
+
text: string;
|
|
12
|
+
tool_name: string;
|
|
13
|
+
input_summary?: string | null;
|
|
14
|
+
session_id?: string | null;
|
|
15
|
+
project_path?: string | null;
|
|
16
|
+
force?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface StoredContextOutput {
|
|
19
|
+
source_id: string;
|
|
20
|
+
bytes: number;
|
|
21
|
+
lines: number;
|
|
22
|
+
preview: string;
|
|
23
|
+
receipt: string;
|
|
24
|
+
chunk_count: number;
|
|
25
|
+
returned_bytes: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ContextSearchResult {
|
|
28
|
+
source_id: string;
|
|
29
|
+
chunk_id: string;
|
|
30
|
+
ordinal: number;
|
|
31
|
+
title: string | null;
|
|
32
|
+
content: string;
|
|
33
|
+
tool_name: string;
|
|
34
|
+
created_at: number;
|
|
35
|
+
bytes: number;
|
|
36
|
+
lines: number;
|
|
37
|
+
rank: number;
|
|
38
|
+
}
|
|
39
|
+
export interface ContextStats {
|
|
40
|
+
sources: number;
|
|
41
|
+
chunks: number;
|
|
42
|
+
bytes_stored: number;
|
|
43
|
+
bytes_returned: number;
|
|
44
|
+
bytes_saved: number;
|
|
45
|
+
reduction_pct: number;
|
|
46
|
+
db_bytes: number;
|
|
47
|
+
wal_bytes: number;
|
|
48
|
+
total_bytes: number;
|
|
49
|
+
}
|
|
50
|
+
interface ChunkRow {
|
|
51
|
+
id: string;
|
|
52
|
+
source_id: string;
|
|
53
|
+
ordinal: number;
|
|
54
|
+
title: string | null;
|
|
55
|
+
content: string;
|
|
56
|
+
byte_count: number;
|
|
57
|
+
}
|
|
58
|
+
export declare function default_context_db_path(): string;
|
|
59
|
+
export declare function set_context_sidecar_enabled(enabled: boolean, options?: ContextStoreOptions): void;
|
|
60
|
+
export declare function is_context_sidecar_enabled(): boolean;
|
|
61
|
+
export declare function get_context_store(options?: ContextStoreOptions): ContextStore;
|
|
62
|
+
export declare function maybe_store_context_output(input: StoreContextInput, options?: ContextStoreOptions): StoredContextOutput | null;
|
|
63
|
+
export declare function count_lines(text: string): number;
|
|
64
|
+
export declare function should_index_text(text: string, options?: Pick<ContextStoreOptions, 'max_bytes' | 'max_lines'>): boolean;
|
|
65
|
+
export declare function escape_fts5_query(query: string): string;
|
|
66
|
+
export declare function make_preview(text: string, max_lines?: number, max_bytes?: number): string;
|
|
67
|
+
export declare class ContextStore {
|
|
68
|
+
readonly db_path: string;
|
|
69
|
+
private db;
|
|
70
|
+
private project_path;
|
|
71
|
+
private session_id;
|
|
72
|
+
private max_bytes;
|
|
73
|
+
private max_lines;
|
|
74
|
+
constructor(options?: ContextStoreOptions);
|
|
75
|
+
store(input: StoreContextInput): StoredContextOutput | null;
|
|
76
|
+
search(query: string, options?: {
|
|
77
|
+
source_id?: string;
|
|
78
|
+
limit?: number;
|
|
79
|
+
tool_name?: string;
|
|
80
|
+
}): ContextSearchResult[];
|
|
81
|
+
get(source_id: string, chunk_id?: string): ChunkRow[];
|
|
82
|
+
stats(): ContextStats;
|
|
83
|
+
purge(options?: {
|
|
84
|
+
older_than_days?: number;
|
|
85
|
+
source_id?: string;
|
|
86
|
+
}): number;
|
|
87
|
+
close(): void;
|
|
88
|
+
}
|
|
89
|
+
export {};
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import { redact_text } from '@spences10/pi-redact';
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
3
|
+
import { existsSync, mkdirSync, statSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
7
|
+
export const DEFAULT_CONTEXT_MAX_BYTES = 24 * 1024;
|
|
8
|
+
export const DEFAULT_CONTEXT_MAX_LINES = 300;
|
|
9
|
+
const DEFAULT_PREVIEW_LINES = 80;
|
|
10
|
+
const DEFAULT_PREVIEW_BYTES = 8 * 1024;
|
|
11
|
+
const SCHEMA = `
|
|
12
|
+
PRAGMA foreign_keys = ON;
|
|
13
|
+
PRAGMA journal_mode = WAL;
|
|
14
|
+
PRAGMA busy_timeout = 5000;
|
|
15
|
+
|
|
16
|
+
CREATE TABLE IF NOT EXISTS context_sources (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
session_id TEXT,
|
|
19
|
+
project_path TEXT,
|
|
20
|
+
tool_name TEXT NOT NULL,
|
|
21
|
+
input_summary TEXT,
|
|
22
|
+
created_at INTEGER NOT NULL,
|
|
23
|
+
byte_count INTEGER NOT NULL,
|
|
24
|
+
line_count INTEGER NOT NULL,
|
|
25
|
+
content_hash TEXT NOT NULL,
|
|
26
|
+
preview_byte_count INTEGER NOT NULL DEFAULT 0,
|
|
27
|
+
returned_byte_count INTEGER NOT NULL DEFAULT 0
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
CREATE TABLE IF NOT EXISTS context_chunks (
|
|
31
|
+
id TEXT PRIMARY KEY,
|
|
32
|
+
source_id TEXT NOT NULL REFERENCES context_sources(id) ON DELETE CASCADE,
|
|
33
|
+
ordinal INTEGER NOT NULL,
|
|
34
|
+
title TEXT,
|
|
35
|
+
content TEXT NOT NULL,
|
|
36
|
+
byte_count INTEGER NOT NULL
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS context_chunks_fts USING fts5(
|
|
40
|
+
title,
|
|
41
|
+
content,
|
|
42
|
+
content='context_chunks',
|
|
43
|
+
content_rowid='rowid'
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
CREATE TRIGGER IF NOT EXISTS context_chunks_ai AFTER INSERT ON context_chunks BEGIN
|
|
47
|
+
INSERT INTO context_chunks_fts(rowid, title, content) VALUES (new.rowid, new.title, new.content);
|
|
48
|
+
END;
|
|
49
|
+
|
|
50
|
+
CREATE TRIGGER IF NOT EXISTS context_chunks_ad AFTER DELETE ON context_chunks BEGIN
|
|
51
|
+
INSERT INTO context_chunks_fts(context_chunks_fts, rowid, title, content)
|
|
52
|
+
VALUES('delete', old.rowid, old.title, old.content);
|
|
53
|
+
END;
|
|
54
|
+
|
|
55
|
+
CREATE TRIGGER IF NOT EXISTS context_chunks_au AFTER UPDATE ON context_chunks BEGIN
|
|
56
|
+
INSERT INTO context_chunks_fts(context_chunks_fts, rowid, title, content)
|
|
57
|
+
VALUES('delete', old.rowid, old.title, old.content);
|
|
58
|
+
INSERT INTO context_chunks_fts(rowid, title, content) VALUES (new.rowid, new.title, new.content);
|
|
59
|
+
END;
|
|
60
|
+
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_context_sources_created ON context_sources(created_at);
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_context_sources_session ON context_sources(session_id);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_context_sources_project ON context_sources(project_path);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_context_chunks_source ON context_chunks(source_id, ordinal);
|
|
65
|
+
`;
|
|
66
|
+
let global_options = {};
|
|
67
|
+
let global_enabled = false;
|
|
68
|
+
let global_store = null;
|
|
69
|
+
export function default_context_db_path() {
|
|
70
|
+
if (process.env.MY_PI_CONTEXT_DB)
|
|
71
|
+
return process.env.MY_PI_CONTEXT_DB;
|
|
72
|
+
const agent_dir = process.env.PI_CODING_AGENT_DIR ??
|
|
73
|
+
join(process.env.HOME ?? process.env.USERPROFILE ?? homedir(), '.pi', 'agent');
|
|
74
|
+
return join(agent_dir, 'context.db');
|
|
75
|
+
}
|
|
76
|
+
export function set_context_sidecar_enabled(enabled, options = {}) {
|
|
77
|
+
global_enabled = enabled;
|
|
78
|
+
global_options = { ...global_options, ...options };
|
|
79
|
+
if (!enabled)
|
|
80
|
+
global_store = null;
|
|
81
|
+
}
|
|
82
|
+
export function is_context_sidecar_enabled() {
|
|
83
|
+
return global_enabled;
|
|
84
|
+
}
|
|
85
|
+
export function get_context_store(options = {}) {
|
|
86
|
+
const merged = { ...global_options, ...options };
|
|
87
|
+
const db_path = merged.db_path ?? default_context_db_path();
|
|
88
|
+
if (!global_store || global_store.db_path !== db_path) {
|
|
89
|
+
global_store = new ContextStore({ ...merged, db_path });
|
|
90
|
+
}
|
|
91
|
+
return global_store;
|
|
92
|
+
}
|
|
93
|
+
export function maybe_store_context_output(input, options = {}) {
|
|
94
|
+
if (!global_enabled)
|
|
95
|
+
return null;
|
|
96
|
+
return get_context_store(options).store(input);
|
|
97
|
+
}
|
|
98
|
+
export function count_lines(text) {
|
|
99
|
+
if (!text)
|
|
100
|
+
return 0;
|
|
101
|
+
return text.split('\n').length;
|
|
102
|
+
}
|
|
103
|
+
export function should_index_text(text, options = {}) {
|
|
104
|
+
const max_bytes = options.max_bytes ?? DEFAULT_CONTEXT_MAX_BYTES;
|
|
105
|
+
const max_lines = options.max_lines ?? DEFAULT_CONTEXT_MAX_LINES;
|
|
106
|
+
return (Buffer.byteLength(text, 'utf8') > max_bytes ||
|
|
107
|
+
count_lines(text) > max_lines);
|
|
108
|
+
}
|
|
109
|
+
export function escape_fts5_query(query) {
|
|
110
|
+
const trimmed = query.trim();
|
|
111
|
+
if (!trimmed)
|
|
112
|
+
return '""';
|
|
113
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"')) {
|
|
114
|
+
return trimmed.replace(/"(.*)"/s, (_match, inner) => `"${inner.replace(/"/g, '""')}"`);
|
|
115
|
+
}
|
|
116
|
+
const tokens = trimmed
|
|
117
|
+
.split(/\s+/)
|
|
118
|
+
.map((token) => token.trim())
|
|
119
|
+
.filter(Boolean)
|
|
120
|
+
.map((token) => {
|
|
121
|
+
const is_prefix = token.endsWith('*');
|
|
122
|
+
const base = is_prefix ? token.slice(0, -1) : token;
|
|
123
|
+
const safe = base
|
|
124
|
+
.replace(/["'(){}[\]^:./\\+-]/g, ' ')
|
|
125
|
+
.trim()
|
|
126
|
+
.replace(/\s+/g, ' ');
|
|
127
|
+
if (!safe)
|
|
128
|
+
return '';
|
|
129
|
+
const quoted = `"${safe.replace(/"/g, '""')}"`;
|
|
130
|
+
return is_prefix ? `${quoted}*` : quoted;
|
|
131
|
+
})
|
|
132
|
+
.filter(Boolean);
|
|
133
|
+
return tokens.length > 0 ? tokens.join(' ') : '""';
|
|
134
|
+
}
|
|
135
|
+
export function make_preview(text, max_lines = DEFAULT_PREVIEW_LINES, max_bytes = DEFAULT_PREVIEW_BYTES) {
|
|
136
|
+
const lines = text.split('\n');
|
|
137
|
+
let preview;
|
|
138
|
+
if (lines.length <= max_lines) {
|
|
139
|
+
preview = text;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const head_count = Math.ceil(max_lines / 2);
|
|
143
|
+
const tail_count = Math.floor(max_lines / 2);
|
|
144
|
+
const omitted = lines.length - head_count - tail_count;
|
|
145
|
+
preview = [
|
|
146
|
+
...lines.slice(0, head_count),
|
|
147
|
+
``,
|
|
148
|
+
`[... ${omitted} lines omitted; indexed in context sidecar ...]`,
|
|
149
|
+
``,
|
|
150
|
+
...lines.slice(-tail_count),
|
|
151
|
+
].join('\n');
|
|
152
|
+
}
|
|
153
|
+
return take_utf8_bytes(preview, max_bytes);
|
|
154
|
+
}
|
|
155
|
+
function take_utf8_bytes(text, max_bytes) {
|
|
156
|
+
if (Buffer.byteLength(text, 'utf8') <= max_bytes)
|
|
157
|
+
return text;
|
|
158
|
+
let bytes = 0;
|
|
159
|
+
let output = '';
|
|
160
|
+
for (const char of text) {
|
|
161
|
+
const char_bytes = Buffer.byteLength(char, 'utf8');
|
|
162
|
+
if (bytes + char_bytes > max_bytes)
|
|
163
|
+
break;
|
|
164
|
+
bytes += char_bytes;
|
|
165
|
+
output += char;
|
|
166
|
+
}
|
|
167
|
+
return `${output}\n[... preview truncated at ${format_bytes(max_bytes)} ...]`;
|
|
168
|
+
}
|
|
169
|
+
function chunk_text(text, source_id) {
|
|
170
|
+
const paragraphs = text.split(/\n{2,}/);
|
|
171
|
+
const chunks = [];
|
|
172
|
+
let current = '';
|
|
173
|
+
const target_bytes = 4096;
|
|
174
|
+
for (const paragraph of paragraphs) {
|
|
175
|
+
if (Buffer.byteLength(paragraph, 'utf8') > target_bytes) {
|
|
176
|
+
if (current)
|
|
177
|
+
chunks.push(current);
|
|
178
|
+
chunks.push(...split_large_chunk(paragraph, target_bytes));
|
|
179
|
+
current = '';
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const next = current ? `${current}\n\n${paragraph}` : paragraph;
|
|
183
|
+
if (Buffer.byteLength(next, 'utf8') > target_bytes && current) {
|
|
184
|
+
chunks.push(current);
|
|
185
|
+
current = paragraph;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
current = next;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (current)
|
|
192
|
+
chunks.push(current);
|
|
193
|
+
if (chunks.length === 0)
|
|
194
|
+
chunks.push(text);
|
|
195
|
+
return chunks.map((content, index) => ({
|
|
196
|
+
id: `${source_id}_${String(index + 1).padStart(4, '0')}`,
|
|
197
|
+
source_id,
|
|
198
|
+
ordinal: index + 1,
|
|
199
|
+
title: first_non_empty_line(content),
|
|
200
|
+
content,
|
|
201
|
+
byte_count: Buffer.byteLength(content, 'utf8'),
|
|
202
|
+
}));
|
|
203
|
+
}
|
|
204
|
+
function split_large_chunk(text, target_bytes) {
|
|
205
|
+
const chunks = [];
|
|
206
|
+
let current = '';
|
|
207
|
+
for (const line of text.split('\n')) {
|
|
208
|
+
const next = current ? `${current}\n${line}` : line;
|
|
209
|
+
if (Buffer.byteLength(next, 'utf8') <= target_bytes) {
|
|
210
|
+
current = next;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (current)
|
|
214
|
+
chunks.push(current);
|
|
215
|
+
if (Buffer.byteLength(line, 'utf8') <= target_bytes) {
|
|
216
|
+
current = line;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
let rest = line;
|
|
220
|
+
while (Buffer.byteLength(rest, 'utf8') > target_bytes) {
|
|
221
|
+
const [head, tail] = split_utf8_at_byte(rest, target_bytes);
|
|
222
|
+
chunks.push(head);
|
|
223
|
+
rest = tail;
|
|
224
|
+
}
|
|
225
|
+
current = rest;
|
|
226
|
+
}
|
|
227
|
+
if (current)
|
|
228
|
+
chunks.push(current);
|
|
229
|
+
return chunks;
|
|
230
|
+
}
|
|
231
|
+
function split_utf8_at_byte(text, max_bytes) {
|
|
232
|
+
let bytes = 0;
|
|
233
|
+
let index = 0;
|
|
234
|
+
for (const char of text) {
|
|
235
|
+
const char_bytes = Buffer.byteLength(char, 'utf8');
|
|
236
|
+
if (bytes + char_bytes > max_bytes)
|
|
237
|
+
break;
|
|
238
|
+
bytes += char_bytes;
|
|
239
|
+
index += char.length;
|
|
240
|
+
}
|
|
241
|
+
return [text.slice(0, index), text.slice(index)];
|
|
242
|
+
}
|
|
243
|
+
function first_non_empty_line(text) {
|
|
244
|
+
const line = text
|
|
245
|
+
.split('\n')
|
|
246
|
+
.map((value) => value.trim())
|
|
247
|
+
.find(Boolean);
|
|
248
|
+
return line ? line.slice(0, 120) : null;
|
|
249
|
+
}
|
|
250
|
+
function format_bytes(bytes) {
|
|
251
|
+
if (bytes < 1024)
|
|
252
|
+
return `${bytes} B`;
|
|
253
|
+
if (bytes < 1024 * 1024)
|
|
254
|
+
return `${(bytes / 1024).toFixed(1)} KiB`;
|
|
255
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MiB`;
|
|
256
|
+
}
|
|
257
|
+
function summarize_source(result, tool_name) {
|
|
258
|
+
return [
|
|
259
|
+
`[context-sidecar] Large ${tool_name} output indexed locally`,
|
|
260
|
+
``,
|
|
261
|
+
`Source: ${result.source_id}`,
|
|
262
|
+
`Size: ${format_bytes(result.bytes)}, ${result.lines} lines, ${result.chunk_count} chunks`,
|
|
263
|
+
`Use context_search query:"..." source_id:"${result.source_id}" to inspect it.`,
|
|
264
|
+
`Use context_get source_id:"${result.source_id}" for exact chunks.`,
|
|
265
|
+
``,
|
|
266
|
+
result.preview,
|
|
267
|
+
].join('\n');
|
|
268
|
+
}
|
|
269
|
+
export class ContextStore {
|
|
270
|
+
db_path;
|
|
271
|
+
db;
|
|
272
|
+
project_path;
|
|
273
|
+
session_id;
|
|
274
|
+
max_bytes;
|
|
275
|
+
max_lines;
|
|
276
|
+
constructor(options = {}) {
|
|
277
|
+
this.db_path = options.db_path ?? default_context_db_path();
|
|
278
|
+
this.project_path = options.project_path ?? process.cwd();
|
|
279
|
+
this.session_id = options.session_id ?? null;
|
|
280
|
+
this.max_bytes = options.max_bytes ?? DEFAULT_CONTEXT_MAX_BYTES;
|
|
281
|
+
this.max_lines = options.max_lines ?? DEFAULT_CONTEXT_MAX_LINES;
|
|
282
|
+
const dir = dirname(this.db_path);
|
|
283
|
+
if (!existsSync(dir))
|
|
284
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
285
|
+
this.db = new DatabaseSync(this.db_path, {
|
|
286
|
+
enableForeignKeyConstraints: true,
|
|
287
|
+
});
|
|
288
|
+
this.db.exec(SCHEMA);
|
|
289
|
+
}
|
|
290
|
+
store(input) {
|
|
291
|
+
const redaction = redact_text(input.text);
|
|
292
|
+
const text = redaction.redacted;
|
|
293
|
+
if (!input.force &&
|
|
294
|
+
!should_index_text(text, {
|
|
295
|
+
max_bytes: this.max_bytes,
|
|
296
|
+
max_lines: this.max_lines,
|
|
297
|
+
}))
|
|
298
|
+
return null;
|
|
299
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
300
|
+
const lines = count_lines(text);
|
|
301
|
+
const source_id = `ctx_${Date.now().toString(36)}_${randomUUID().slice(0, 8)}`;
|
|
302
|
+
const created_at = Date.now();
|
|
303
|
+
const content_hash = createHash('sha256')
|
|
304
|
+
.update(text)
|
|
305
|
+
.digest('hex');
|
|
306
|
+
const chunks = chunk_text(text, source_id);
|
|
307
|
+
const preview = make_preview(text);
|
|
308
|
+
const preview_bytes = Buffer.byteLength(preview, 'utf8');
|
|
309
|
+
const insert = this.db.prepare(`
|
|
310
|
+
INSERT INTO context_sources (
|
|
311
|
+
id, session_id, project_path, tool_name, input_summary, created_at,
|
|
312
|
+
byte_count, line_count, content_hash, preview_byte_count, returned_byte_count
|
|
313
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0)
|
|
314
|
+
`);
|
|
315
|
+
const insert_chunk = this.db.prepare(`
|
|
316
|
+
INSERT INTO context_chunks (id, source_id, ordinal, title, content, byte_count)
|
|
317
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
318
|
+
`);
|
|
319
|
+
const update_returned = this.db.prepare(`
|
|
320
|
+
UPDATE context_sources SET returned_byte_count = ? WHERE id = ?
|
|
321
|
+
`);
|
|
322
|
+
this.db.exec('BEGIN');
|
|
323
|
+
try {
|
|
324
|
+
insert.run(source_id, input.session_id ?? this.session_id, input.project_path ?? this.project_path, input.tool_name, input.input_summary ?? null, created_at, bytes, lines, content_hash, preview_bytes);
|
|
325
|
+
for (const chunk of chunks) {
|
|
326
|
+
insert_chunk.run(chunk.id, chunk.source_id, chunk.ordinal, chunk.title, chunk.content, chunk.byte_count);
|
|
327
|
+
}
|
|
328
|
+
const provisional = {
|
|
329
|
+
source_id,
|
|
330
|
+
bytes,
|
|
331
|
+
lines,
|
|
332
|
+
preview,
|
|
333
|
+
receipt: '',
|
|
334
|
+
chunk_count: chunks.length,
|
|
335
|
+
returned_bytes: 0,
|
|
336
|
+
};
|
|
337
|
+
const receipt = summarize_source(provisional, input.tool_name);
|
|
338
|
+
const returned_bytes = Buffer.byteLength(receipt, 'utf8');
|
|
339
|
+
update_returned.run(returned_bytes, source_id);
|
|
340
|
+
this.db.exec('COMMIT');
|
|
341
|
+
return { ...provisional, receipt, returned_bytes };
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
this.db.exec('ROLLBACK');
|
|
345
|
+
throw error;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
search(query, options = {}) {
|
|
349
|
+
const limit = Math.max(1, Math.min(options.limit ?? 5, 25));
|
|
350
|
+
const match = escape_fts5_query(query);
|
|
351
|
+
const filters = [];
|
|
352
|
+
const params = [match];
|
|
353
|
+
if (options.source_id) {
|
|
354
|
+
filters.push('context_sources.id = ?');
|
|
355
|
+
params.push(options.source_id);
|
|
356
|
+
}
|
|
357
|
+
if (options.tool_name) {
|
|
358
|
+
filters.push('context_sources.tool_name = ?');
|
|
359
|
+
params.push(options.tool_name);
|
|
360
|
+
}
|
|
361
|
+
params.push(limit);
|
|
362
|
+
const where_filters = filters.length
|
|
363
|
+
? ` AND ${filters.join(' AND ')}`
|
|
364
|
+
: '';
|
|
365
|
+
const stmt = this.db.prepare(`
|
|
366
|
+
SELECT
|
|
367
|
+
context_sources.id,
|
|
368
|
+
context_sources.tool_name,
|
|
369
|
+
context_sources.created_at,
|
|
370
|
+
context_sources.byte_count,
|
|
371
|
+
context_sources.line_count,
|
|
372
|
+
context_chunks.id as chunk_id,
|
|
373
|
+
context_chunks.ordinal,
|
|
374
|
+
context_chunks.title,
|
|
375
|
+
context_chunks.content,
|
|
376
|
+
bm25(context_chunks_fts, 5.0, 1.0) as rank
|
|
377
|
+
FROM context_chunks_fts
|
|
378
|
+
JOIN context_chunks ON context_chunks.rowid = context_chunks_fts.rowid
|
|
379
|
+
JOIN context_sources ON context_sources.id = context_chunks.source_id
|
|
380
|
+
WHERE context_chunks_fts MATCH ?${where_filters}
|
|
381
|
+
ORDER BY rank
|
|
382
|
+
LIMIT ?
|
|
383
|
+
`);
|
|
384
|
+
return stmt.all(...params).map((row) => ({
|
|
385
|
+
source_id: row.id,
|
|
386
|
+
chunk_id: row.chunk_id,
|
|
387
|
+
ordinal: row.ordinal,
|
|
388
|
+
title: row.title,
|
|
389
|
+
content: row.content,
|
|
390
|
+
tool_name: row.tool_name,
|
|
391
|
+
created_at: row.created_at,
|
|
392
|
+
bytes: row.byte_count,
|
|
393
|
+
lines: row.line_count,
|
|
394
|
+
rank: row.rank,
|
|
395
|
+
}));
|
|
396
|
+
}
|
|
397
|
+
get(source_id, chunk_id) {
|
|
398
|
+
const stmt = chunk_id
|
|
399
|
+
? this.db.prepare(`
|
|
400
|
+
SELECT id, source_id, ordinal, title, content, byte_count
|
|
401
|
+
FROM context_chunks WHERE source_id = ? AND id = ? ORDER BY ordinal
|
|
402
|
+
`)
|
|
403
|
+
: this.db.prepare(`
|
|
404
|
+
SELECT id, source_id, ordinal, title, content, byte_count
|
|
405
|
+
FROM context_chunks WHERE source_id = ? ORDER BY ordinal
|
|
406
|
+
`);
|
|
407
|
+
const params = chunk_id ? [source_id, chunk_id] : [source_id];
|
|
408
|
+
return stmt.all(...params);
|
|
409
|
+
}
|
|
410
|
+
stats() {
|
|
411
|
+
const source = this.db
|
|
412
|
+
.prepare(`
|
|
413
|
+
SELECT
|
|
414
|
+
COUNT(*) as sources,
|
|
415
|
+
COALESCE(SUM(byte_count), 0) as bytes_stored,
|
|
416
|
+
COALESCE(SUM(returned_byte_count), 0) as bytes_returned
|
|
417
|
+
FROM context_sources
|
|
418
|
+
`)
|
|
419
|
+
.get();
|
|
420
|
+
const chunks = this.db
|
|
421
|
+
.prepare('SELECT COUNT(*) as chunks FROM context_chunks')
|
|
422
|
+
.get();
|
|
423
|
+
const bytes_saved = source.bytes_stored - source.bytes_returned;
|
|
424
|
+
const reduction_pct = source.bytes_stored > 0
|
|
425
|
+
? Math.round((bytes_saved / source.bytes_stored) * 1000) / 10
|
|
426
|
+
: 0;
|
|
427
|
+
const db_bytes = file_size(this.db_path);
|
|
428
|
+
const wal_bytes = file_size(`${this.db_path}-wal`);
|
|
429
|
+
return {
|
|
430
|
+
sources: source.sources,
|
|
431
|
+
chunks: chunks.chunks,
|
|
432
|
+
bytes_stored: source.bytes_stored,
|
|
433
|
+
bytes_returned: source.bytes_returned,
|
|
434
|
+
bytes_saved,
|
|
435
|
+
reduction_pct,
|
|
436
|
+
db_bytes,
|
|
437
|
+
wal_bytes,
|
|
438
|
+
total_bytes: db_bytes + wal_bytes,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
purge(options = {}) {
|
|
442
|
+
if (options.source_id) {
|
|
443
|
+
const result = this.db
|
|
444
|
+
.prepare('DELETE FROM context_sources WHERE id = ?')
|
|
445
|
+
.run(options.source_id);
|
|
446
|
+
return Number(result.changes ?? 0);
|
|
447
|
+
}
|
|
448
|
+
const days = options.older_than_days ?? 14;
|
|
449
|
+
const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
450
|
+
const result = this.db
|
|
451
|
+
.prepare('DELETE FROM context_sources WHERE created_at < ?')
|
|
452
|
+
.run(cutoff);
|
|
453
|
+
return Number(result.changes ?? 0);
|
|
454
|
+
}
|
|
455
|
+
close() {
|
|
456
|
+
this.db.close();
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function file_size(path) {
|
|
460
|
+
return existsSync(path) ? statSync(path).size : 0;
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@spences10/pi-context",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Pi extension for local SQLite context sidecar storage and retrieval of large tool output",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"context",
|
|
7
|
+
"evals",
|
|
8
|
+
"fts5",
|
|
9
|
+
"pi",
|
|
10
|
+
"pi-package",
|
|
11
|
+
"sqlite"
|
|
12
|
+
],
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "Scott Spence <me@scottspence.com>",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/spences10/my-pi.git",
|
|
18
|
+
"directory": "packages/pi-context"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./store": {
|
|
33
|
+
"types": "./dist/store.d.ts",
|
|
34
|
+
"import": "./dist/store.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@mariozechner/pi-coding-agent": "^0.72.0",
|
|
39
|
+
"typebox": "^1.1.37",
|
|
40
|
+
"@spences10/pi-redact": "0.0.3"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^25.6.0",
|
|
44
|
+
"typescript": "^6.0.3",
|
|
45
|
+
"vitest": "^4.1.5"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=22.0.0"
|
|
49
|
+
},
|
|
50
|
+
"pi": {
|
|
51
|
+
"extensions": [
|
|
52
|
+
"./dist/index.js"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "pnpm --filter @spences10/pi-redact run build && tsc -p tsconfig.build.json",
|
|
57
|
+
"check": "pnpm --filter @spences10/pi-redact run build && tsc --noEmit",
|
|
58
|
+
"test": "pnpm --filter @spences10/pi-redact run build && vitest run"
|
|
59
|
+
}
|
|
60
|
+
}
|