@pcircle/footprint 1.3.0 → 1.5.0
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/README.md +136 -160
- package/SKILL.md +7 -7
- package/dist/src/analyzers/content-analyzer.d.ts.map +1 -1
- package/dist/src/analyzers/content-analyzer.js +20 -4
- package/dist/src/analyzers/content-analyzer.js.map +1 -1
- package/dist/src/cli/index.js +0 -0
- package/dist/src/cli/setup.d.ts.map +1 -1
- package/dist/src/cli/setup.js +34 -12
- package/dist/src/cli/setup.js.map +1 -1
- package/dist/src/cli/utils/env.d.ts +7 -2
- package/dist/src/cli/utils/env.d.ts.map +1 -1
- package/dist/src/cli/utils/env.js +37 -6
- package/dist/src/cli/utils/env.js.map +1 -1
- package/dist/src/index.d.ts +0 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +41 -28
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/crypto/decrypt.d.ts.map +1 -1
- package/dist/src/lib/crypto/decrypt.js +12 -8
- package/dist/src/lib/crypto/decrypt.js.map +1 -1
- package/dist/src/lib/crypto/encrypt.d.ts.map +1 -1
- package/dist/src/lib/crypto/encrypt.js +6 -3
- package/dist/src/lib/crypto/encrypt.js.map +1 -1
- package/dist/src/lib/crypto/key-derivation.d.ts +1 -1
- package/dist/src/lib/crypto/key-derivation.d.ts.map +1 -1
- package/dist/src/lib/crypto/key-derivation.js +11 -11
- package/dist/src/lib/crypto/key-derivation.js.map +1 -1
- package/dist/src/lib/storage/database.d.ts +46 -3
- package/dist/src/lib/storage/database.d.ts.map +1 -1
- package/dist/src/lib/storage/database.js +175 -80
- package/dist/src/lib/storage/database.js.map +1 -1
- package/dist/src/lib/storage/export.d.ts +1 -2
- package/dist/src/lib/storage/export.d.ts.map +1 -1
- package/dist/src/lib/storage/export.js +46 -33
- package/dist/src/lib/storage/export.js.map +1 -1
- package/dist/src/lib/storage/salt-storage.d.ts +1 -1
- package/dist/src/lib/storage/salt-storage.d.ts.map +1 -1
- package/dist/src/lib/storage/salt-storage.js +26 -18
- package/dist/src/lib/storage/salt-storage.js.map +1 -1
- package/dist/src/lib/storage/schema.d.ts +1 -1
- package/dist/src/lib/storage/schema.d.ts.map +1 -1
- package/dist/src/lib/storage/schema.js +29 -47
- package/dist/src/lib/storage/schema.js.map +1 -1
- package/dist/src/lib/tool-wrapper.d.ts.map +1 -1
- package/dist/src/lib/tool-wrapper.js +2 -2
- package/dist/src/lib/tool-wrapper.js.map +1 -1
- package/dist/src/prompts/skill-prompt.d.ts +6 -0
- package/dist/src/prompts/skill-prompt.d.ts.map +1 -0
- package/dist/src/prompts/skill-prompt.js +125 -0
- package/dist/src/prompts/skill-prompt.js.map +1 -0
- package/dist/src/tools/capture-footprint.d.ts +2 -2
- package/dist/src/tools/capture-footprint.d.ts.map +1 -1
- package/dist/src/tools/capture-footprint.js +52 -11
- package/dist/src/tools/capture-footprint.js.map +1 -1
- package/dist/src/tools/delete-footprints.d.ts +18 -1
- package/dist/src/tools/delete-footprints.d.ts.map +1 -1
- package/dist/src/tools/delete-footprints.js +53 -5
- package/dist/src/tools/delete-footprints.js.map +1 -1
- package/dist/src/tools/export-footprints.d.ts +11 -3
- package/dist/src/tools/export-footprints.d.ts.map +1 -1
- package/dist/src/tools/export-footprints.js +48 -9
- package/dist/src/tools/export-footprints.js.map +1 -1
- package/dist/src/tools/get-footprint.d.ts +1 -7
- package/dist/src/tools/get-footprint.d.ts.map +1 -1
- package/dist/src/tools/get-footprint.js +7 -3
- package/dist/src/tools/get-footprint.js.map +1 -1
- package/dist/src/tools/index.d.ts +1 -3
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +1 -3
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/list-footprints.d.ts +1 -15
- package/dist/src/tools/list-footprints.d.ts.map +1 -1
- package/dist/src/tools/list-footprints.js +17 -6
- package/dist/src/tools/list-footprints.js.map +1 -1
- package/dist/src/tools/manage-tags.d.ts +47 -0
- package/dist/src/tools/manage-tags.d.ts.map +1 -0
- package/dist/src/tools/manage-tags.js +109 -0
- package/dist/src/tools/manage-tags.js.map +1 -0
- package/dist/src/tools/search-footprints.d.ts +2 -16
- package/dist/src/tools/search-footprints.d.ts.map +1 -1
- package/dist/src/tools/search-footprints.js +23 -7
- package/dist/src/tools/search-footprints.js.map +1 -1
- package/dist/src/tools/suggest-capture.d.ts +1 -1
- package/dist/src/tools/suggest-capture.d.ts.map +1 -1
- package/dist/src/tools/suggest-capture.js +6 -2
- package/dist/src/tools/suggest-capture.js.map +1 -1
- package/dist/src/tools/verify-footprint.d.ts +7 -54
- package/dist/src/tools/verify-footprint.d.ts.map +1 -1
- package/dist/src/tools/verify-footprint.js +11 -8
- package/dist/src/tools/verify-footprint.js.map +1 -1
- package/dist/src/types.d.ts +4 -4
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/ui/register.js +1 -1
- package/dist/src/ui/register.js.map +1 -1
- package/dist/ui/dashboard.html +80 -67
- package/dist/ui/detail.html +62 -49
- package/dist/ui/export.html +64 -51
- package/package.json +18 -13
- package/dist/src/lib/errors/base-error.d.ts +0 -15
- package/dist/src/lib/errors/base-error.d.ts.map +0 -1
- package/dist/src/lib/errors/base-error.js +0 -34
- package/dist/src/lib/errors/base-error.js.map +0 -1
- package/dist/src/lib/errors/crypto-error.d.ts +0 -29
- package/dist/src/lib/errors/crypto-error.d.ts.map +0 -1
- package/dist/src/lib/errors/crypto-error.js +0 -43
- package/dist/src/lib/errors/crypto-error.js.map +0 -1
- package/dist/src/lib/errors/index.d.ts +0 -26
- package/dist/src/lib/errors/index.d.ts.map +0 -1
- package/dist/src/lib/errors/index.js +0 -26
- package/dist/src/lib/errors/index.js.map +0 -1
- package/dist/src/lib/errors/storage-error.d.ts +0 -25
- package/dist/src/lib/errors/storage-error.d.ts.map +0 -1
- package/dist/src/lib/errors/storage-error.js +0 -38
- package/dist/src/lib/errors/storage-error.js.map +0 -1
- package/dist/src/lib/errors/validation-error.d.ts +0 -21
- package/dist/src/lib/errors/validation-error.d.ts.map +0 -1
- package/dist/src/lib/errors/validation-error.js +0 -29
- package/dist/src/lib/errors/validation-error.js.map +0 -1
- package/dist/src/test-helpers.d.ts +0 -33
- package/dist/src/test-helpers.d.ts.map +0 -1
- package/dist/src/test-helpers.js +0 -108
- package/dist/src/test-helpers.js.map +0 -1
- package/dist/src/tools/get-tag-stats.d.ts +0 -30
- package/dist/src/tools/get-tag-stats.d.ts.map +0 -1
- package/dist/src/tools/get-tag-stats.js +0 -33
- package/dist/src/tools/get-tag-stats.js.map +0 -1
- package/dist/src/tools/remove-tag.d.ts +0 -22
- package/dist/src/tools/remove-tag.d.ts.map +0 -1
- package/dist/src/tools/remove-tag.js +0 -30
- package/dist/src/tools/remove-tag.js.map +0 -1
- package/dist/src/tools/rename-tag.d.ts +0 -24
- package/dist/src/tools/rename-tag.d.ts.map +0 -1
- package/dist/src/tools/rename-tag.js +0 -34
- package/dist/src/tools/rename-tag.js.map +0 -1
|
@@ -8,26 +8,32 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export function storeSalt(db, salt) {
|
|
10
10
|
if (salt.length !== 16) {
|
|
11
|
-
throw new Error(
|
|
11
|
+
throw new Error("Salt must be 16 bytes");
|
|
12
12
|
}
|
|
13
13
|
try {
|
|
14
|
-
//
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
// Atomic check-and-insert within a transaction to prevent TOCTOU race
|
|
15
|
+
const insertSalt = db.transaction(() => {
|
|
16
|
+
const existing = db
|
|
17
|
+
.prepare("SELECT id FROM crypto_keys WHERE id = 1")
|
|
18
|
+
.get();
|
|
19
|
+
if (existing) {
|
|
20
|
+
throw new Error("Salt already exists in database");
|
|
21
|
+
}
|
|
22
|
+
// Store salt (id=1 ensures singleton via PRIMARY KEY + CHECK constraint)
|
|
23
|
+
const stmt = db.prepare(`
|
|
24
|
+
INSERT INTO crypto_keys (id, salt)
|
|
25
|
+
VALUES (1, ?)
|
|
26
|
+
`);
|
|
27
|
+
stmt.run(Buffer.from(salt));
|
|
28
|
+
});
|
|
29
|
+
insertSalt();
|
|
25
30
|
}
|
|
26
31
|
catch (error) {
|
|
27
|
-
if (error instanceof Error &&
|
|
32
|
+
if (error instanceof Error &&
|
|
33
|
+
error.message === "Salt already exists in database") {
|
|
28
34
|
throw error;
|
|
29
35
|
}
|
|
30
|
-
throw new Error(`Failed to store salt: ${error instanceof Error ? error.message :
|
|
36
|
+
throw new Error(`Failed to store salt: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
@@ -38,14 +44,16 @@ export function storeSalt(db, salt) {
|
|
|
38
44
|
*/
|
|
39
45
|
export function retrieveSalt(db) {
|
|
40
46
|
try {
|
|
41
|
-
const row = db
|
|
47
|
+
const row = db
|
|
48
|
+
.prepare("SELECT salt FROM crypto_keys WHERE id = 1")
|
|
49
|
+
.get();
|
|
42
50
|
if (!row) {
|
|
43
51
|
return null;
|
|
44
52
|
}
|
|
45
53
|
return new Uint8Array(row.salt);
|
|
46
54
|
}
|
|
47
55
|
catch (error) {
|
|
48
|
-
throw new Error(`Failed to retrieve salt: ${error instanceof Error ? error.message :
|
|
56
|
+
throw new Error(`Failed to retrieve salt: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
/**
|
|
@@ -56,10 +64,10 @@ export function retrieveSalt(db) {
|
|
|
56
64
|
*/
|
|
57
65
|
export function hasSalt(db) {
|
|
58
66
|
try {
|
|
59
|
-
const row = db.prepare(
|
|
67
|
+
const row = db.prepare("SELECT id FROM crypto_keys WHERE id = 1").get();
|
|
60
68
|
return row !== undefined;
|
|
61
69
|
}
|
|
62
|
-
catch
|
|
70
|
+
catch {
|
|
63
71
|
return false;
|
|
64
72
|
}
|
|
65
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"salt-storage.js","sourceRoot":"","sources":["../../../../src/lib/storage/salt-storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"salt-storage.js","sourceRoot":"","sources":["../../../../src/lib/storage/salt-storage.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,EAAqB,EAAE,IAAgB;IAC/D,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,CAAC;QACH,sEAAsE;QACtE,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;YACrC,MAAM,QAAQ,GAAG,EAAE;iBAChB,OAAO,CAAC,yCAAyC,CAAC;iBAClD,GAAG,EAAE,CAAC;YACT,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;YAED,yEAAyE;YACzE,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;OAGvB,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,UAAU,EAAE,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IACE,KAAK,YAAY,KAAK;YACtB,KAAK,CAAC,OAAO,KAAK,iCAAiC,EACnD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,MAAM,IAAI,KAAK,CACb,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACpF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CAAC,2CAA2C,CAAC;aACpD,GAAG,EAAkC,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,4BAA4B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CACvF,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EAAqB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,GAAG,EAAE,CAAC;QACxE,OAAO,GAAG,KAAK,SAAS,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,IAAI,CA8DxD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAoD3D"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Current schema version
|
|
3
3
|
*/
|
|
4
|
-
const SCHEMA_VERSION =
|
|
4
|
+
const SCHEMA_VERSION = "1";
|
|
5
5
|
/**
|
|
6
6
|
* Creates the database schema (tables and indexes)
|
|
7
7
|
* This function is idempotent - safe to run multiple times
|
|
@@ -9,16 +9,16 @@ const SCHEMA_VERSION = '1';
|
|
|
9
9
|
* @param db - SQLite database instance
|
|
10
10
|
*/
|
|
11
11
|
export function createSchema(db) {
|
|
12
|
-
try
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
// Note: No try/catch here — on failure, the caller (EvidenceDatabase constructor)
|
|
13
|
+
// owns the db lifecycle and handles cleanup. Previously this function closed the db
|
|
14
|
+
// on error, causing a double-close when the constructor's catch also called db.close().
|
|
15
|
+
// Pragmas must be set outside transactions
|
|
16
|
+
db.pragma("journal_mode = WAL");
|
|
17
|
+
db.pragma("synchronous = NORMAL");
|
|
18
|
+
db.pragma("busy_timeout = 5000");
|
|
19
|
+
db.pragma("foreign_keys = ON");
|
|
20
|
+
// Wrap DDL + DML in transaction for atomicity (prevents partial schema on failure)
|
|
21
|
+
const initSchema = db.transaction(() => {
|
|
22
22
|
db.exec(`
|
|
23
23
|
CREATE TABLE IF NOT EXISTS evidences (
|
|
24
24
|
id TEXT PRIMARY KEY,
|
|
@@ -36,14 +36,12 @@ export function createSchema(db) {
|
|
|
36
36
|
updatedAt TEXT NOT NULL DEFAULT (datetime('now'))
|
|
37
37
|
);
|
|
38
38
|
`);
|
|
39
|
-
// Create metadata table for schema versioning and configuration
|
|
40
39
|
db.exec(`
|
|
41
40
|
CREATE TABLE IF NOT EXISTS metadata (
|
|
42
41
|
key TEXT PRIMARY KEY,
|
|
43
42
|
value TEXT NOT NULL
|
|
44
43
|
);
|
|
45
44
|
`);
|
|
46
|
-
// Create crypto_keys table for master salt storage
|
|
47
45
|
db.exec(`
|
|
48
46
|
CREATE TABLE IF NOT EXISTS crypto_keys (
|
|
49
47
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
@@ -51,28 +49,12 @@ export function createSchema(db) {
|
|
|
51
49
|
createdAt TEXT NOT NULL DEFAULT (datetime('now'))
|
|
52
50
|
);
|
|
53
51
|
`);
|
|
54
|
-
|
|
55
|
-
db.exec(`
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`);
|
|
61
|
-
db.exec(`
|
|
62
|
-
CREATE INDEX IF NOT EXISTS idx_content_hash ON evidences(contentHash);
|
|
63
|
-
`);
|
|
64
|
-
// Set schema version (use INSERT OR IGNORE to make it idempotent)
|
|
65
|
-
const stmt = db.prepare(`
|
|
66
|
-
INSERT OR IGNORE INTO metadata (key, value)
|
|
67
|
-
VALUES ('schema_version', ?)
|
|
68
|
-
`);
|
|
69
|
-
stmt.run(SCHEMA_VERSION);
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
// Clean up database connection on failure to prevent resource leaks
|
|
73
|
-
db.close();
|
|
74
|
-
throw error;
|
|
75
|
-
}
|
|
52
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_timestamp ON evidences(timestamp);`);
|
|
53
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_conversation_id ON evidences(conversationId);`);
|
|
54
|
+
db.exec(`CREATE INDEX IF NOT EXISTS idx_content_hash ON evidences(contentHash);`);
|
|
55
|
+
db.prepare(`INSERT OR IGNORE INTO metadata (key, value) VALUES ('schema_version', ?)`).run(SCHEMA_VERSION);
|
|
56
|
+
});
|
|
57
|
+
initSchema();
|
|
76
58
|
}
|
|
77
59
|
/**
|
|
78
60
|
* Verifies that the database schema is valid
|
|
@@ -84,31 +66,31 @@ export function createSchema(db) {
|
|
|
84
66
|
export function verifySchema(db) {
|
|
85
67
|
try {
|
|
86
68
|
// Check if evidences table exists
|
|
87
|
-
const evidencesTableInfo = db.pragma(
|
|
69
|
+
const evidencesTableInfo = db.pragma("table_info(evidences)");
|
|
88
70
|
if (!evidencesTableInfo || evidencesTableInfo.length === 0) {
|
|
89
71
|
return false;
|
|
90
72
|
}
|
|
91
73
|
// Check if metadata table exists
|
|
92
|
-
const metadataTableInfo = db.pragma(
|
|
74
|
+
const metadataTableInfo = db.pragma("table_info(metadata)");
|
|
93
75
|
if (!metadataTableInfo || metadataTableInfo.length === 0) {
|
|
94
76
|
return false;
|
|
95
77
|
}
|
|
96
78
|
// Check if crypto_keys table exists
|
|
97
|
-
const cryptoKeysTableInfo = db.pragma(
|
|
79
|
+
const cryptoKeysTableInfo = db.pragma("table_info(crypto_keys)");
|
|
98
80
|
if (!cryptoKeysTableInfo || cryptoKeysTableInfo.length === 0) {
|
|
99
81
|
return false;
|
|
100
82
|
}
|
|
101
83
|
// Verify required columns exist in evidences table
|
|
102
84
|
const evidencesColumns = evidencesTableInfo.map((col) => col.name);
|
|
103
85
|
const requiredColumns = [
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
86
|
+
"id",
|
|
87
|
+
"timestamp",
|
|
88
|
+
"encryptedContent",
|
|
89
|
+
"nonce",
|
|
90
|
+
"contentHash",
|
|
91
|
+
"messageCount",
|
|
92
|
+
"createdAt",
|
|
93
|
+
"updatedAt",
|
|
112
94
|
];
|
|
113
95
|
for (const col of requiredColumns) {
|
|
114
96
|
if (!evidencesColumns.includes(col)) {
|
|
@@ -117,7 +99,7 @@ export function verifySchema(db) {
|
|
|
117
99
|
}
|
|
118
100
|
return true;
|
|
119
101
|
}
|
|
120
|
-
catch
|
|
102
|
+
catch {
|
|
121
103
|
return false;
|
|
122
104
|
}
|
|
123
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../src/lib/storage/schema.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,cAAc,GAAG,GAAG,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,kFAAkF;IAClF,oFAAoF;IACpF,wFAAwF;IAExF,2CAA2C;IAC3C,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAClC,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;IACjC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,mFAAmF;IACnF,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QACrC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;KAgBP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;;;;KAKP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CAAC;;;;;;KAMP,CAAC,CAAC;QAEH,EAAE,CAAC,IAAI,CACL,mEAAmE,CACpE,CAAC;QACF,EAAE,CAAC,IAAI,CACL,8EAA8E,CAC/E,CAAC;QACF,EAAE,CAAC,IAAI,CACL,wEAAwE,CACzE,CAAC;QAEF,EAAE,CAAC,OAAO,CACR,0EAA0E,CAC3E,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,UAAU,EAAE,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAqB;IAChD,IAAI,CAAC;QACH,kCAAkC;QAClC,MAAM,kBAAkB,GAAG,EAAE,CAAC,MAAM,CAAC,uBAAuB,CAG1D,CAAC;QACH,IAAI,CAAC,kBAAkB,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,iCAAiC;QACjC,MAAM,iBAAiB,GAAG,EAAE,CAAC,MAAM,CAAC,sBAAsB,CAGxD,CAAC;QACH,IAAI,CAAC,iBAAiB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,oCAAoC;QACpC,MAAM,mBAAmB,GAAG,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAG7D,CAAC;QACH,IAAI,CAAC,mBAAmB,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,mDAAmD;QACnD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnE,MAAM,eAAe,GAAG;YACtB,IAAI;YACJ,WAAW;YACX,kBAAkB;YAClB,OAAO;YACP,aAAa;YACb,cAAc;YACd,WAAW;YACX,WAAW;SACZ,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YAClC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-wrapper.d.ts","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAC9C,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC7C,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"tool-wrapper.d.ts","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAQtD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAC9C,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,GAC7C,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAYvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAClD,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GACpC,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAY9B"}
|
|
@@ -46,7 +46,7 @@ export function wrapToolHandler(toolName, suggestedAction, handler) {
|
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
|
48
48
|
const errorMessage = getErrorMessage(error);
|
|
49
|
-
throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}
|
|
49
|
+
throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`, { cause: error });
|
|
50
50
|
}
|
|
51
51
|
};
|
|
52
52
|
}
|
|
@@ -66,7 +66,7 @@ export function wrapSyncToolHandler(toolName, suggestedAction, handler) {
|
|
|
66
66
|
}
|
|
67
67
|
catch (error) {
|
|
68
68
|
const errorMessage = getErrorMessage(error);
|
|
69
|
-
throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}
|
|
69
|
+
throw new Error(`[Tool: ${toolName}] ${errorMessage}. Suggested action: ${suggestedAction}`, { cause: error });
|
|
70
70
|
}
|
|
71
71
|
};
|
|
72
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-wrapper.js","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,eAAuB,EACvB,OAA8C;IAE9C,OAAO,KAAK,EAAE,MAAe,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"tool-wrapper.js","sourceRoot":"","sources":["../../../src/lib/tool-wrapper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,eAAuB,EACvB,OAA8C;IAE9C,OAAO,KAAK,EAAE,MAAe,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,EAC3E,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,eAAuB,EACvB,OAAqC;IAErC,OAAO,CAAC,MAAe,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;YAC5C,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,KAAK,YAAY,uBAAuB,eAAe,EAAE,EAC3E,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-prompt.d.ts","sourceRoot":"","sources":["../../../src/prompts/skill-prompt.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAiDzE;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyF5D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { fileURLToPath } from "url";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as z from "zod";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Resolve SKILL.md from the package root.
|
|
9
|
+
* Handles both dev (src/prompts/) and built (dist/prompts/) paths.
|
|
10
|
+
*/
|
|
11
|
+
function findSkillMd() {
|
|
12
|
+
const candidates = [
|
|
13
|
+
path.resolve(__dirname, "../../SKILL.md"), // from dist/prompts/ or src/prompts/
|
|
14
|
+
path.resolve(__dirname, "../../../SKILL.md"), // fallback
|
|
15
|
+
];
|
|
16
|
+
for (const p of candidates) {
|
|
17
|
+
if (fs.existsSync(p))
|
|
18
|
+
return fs.readFileSync(p, "utf-8");
|
|
19
|
+
}
|
|
20
|
+
throw new Error("SKILL.md not found");
|
|
21
|
+
}
|
|
22
|
+
const QUICK_REFERENCE = `# Footprint Quick Reference
|
|
23
|
+
|
|
24
|
+
## Decision Tree
|
|
25
|
+
Should I capture this conversation?
|
|
26
|
+
\u251C\u2500 User explicitly asked \u2192 YES (capture immediately)
|
|
27
|
+
\u251C\u2500 High-value content (IP/Legal/Business/Research/Compliance) \u2192 SUGGEST to user
|
|
28
|
+
\u251C\u2500 Casual chat/small talk \u2192 NO
|
|
29
|
+
\u2514\u2500 Uncertain \u2192 ASK user
|
|
30
|
+
|
|
31
|
+
## Tool Selection
|
|
32
|
+
- Save conversation \u2192 capture-footprint
|
|
33
|
+
- Browse/overview \u2192 list-footprints
|
|
34
|
+
- Full content retrieval \u2192 get-footprint
|
|
35
|
+
- Find by query/tags/dates \u2192 search-footprints
|
|
36
|
+
- Legal/audit export \u2192 export-footprints
|
|
37
|
+
- Verify integrity \u2192 verify-footprint
|
|
38
|
+
- Tag management \u2192 manage-tags (stats/rename/remove)
|
|
39
|
+
- Keyword pre-filter \u2192 suggest-capture
|
|
40
|
+
- Semantic assessment \u2192 Use footprint-should-capture prompt
|
|
41
|
+
|
|
42
|
+
## Tag Conventions
|
|
43
|
+
Format: 3-6 tags, comma-separated
|
|
44
|
+
Types: decision, milestone, research, review, approval
|
|
45
|
+
Domains: api, ui, database, security, legal, business
|
|
46
|
+
Status: draft, finalized, approved, rejected
|
|
47
|
+
|
|
48
|
+
## conversationId Format
|
|
49
|
+
{topic-type}-{descriptive-name}-{YYYY-MM-DD}`;
|
|
50
|
+
/**
|
|
51
|
+
* Register all Footprint MCP prompts on the server.
|
|
52
|
+
*/
|
|
53
|
+
export function registerSkillPrompts(server) {
|
|
54
|
+
const skillContent = findSkillMd();
|
|
55
|
+
// Full SKILL.md content
|
|
56
|
+
server.registerPrompt("footprint-skill", {
|
|
57
|
+
description: "Complete Footprint agent skill guide — decision tree, tool reference, best practices, error recovery, and workflow examples",
|
|
58
|
+
}, async () => ({
|
|
59
|
+
messages: [
|
|
60
|
+
{
|
|
61
|
+
role: "user",
|
|
62
|
+
content: { type: "text", text: skillContent },
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}));
|
|
66
|
+
// Condensed quick reference
|
|
67
|
+
server.registerPrompt("footprint-quick-ref", {
|
|
68
|
+
description: "Condensed quick reference for Footprint — decision tree, tool selection, tag conventions",
|
|
69
|
+
}, async () => ({
|
|
70
|
+
messages: [
|
|
71
|
+
{
|
|
72
|
+
role: "user",
|
|
73
|
+
content: { type: "text", text: QUICK_REFERENCE },
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
}));
|
|
77
|
+
// Semantic capture decision framework
|
|
78
|
+
server.registerPrompt("footprint-should-capture", {
|
|
79
|
+
description: "Semantic decision framework for whether to capture a conversation as evidence. Provides structured criteria for the AI to assess, unlike suggest-capture which uses keyword matching.",
|
|
80
|
+
argsSchema: {
|
|
81
|
+
conversationSummary: z
|
|
82
|
+
.string()
|
|
83
|
+
.min(1, "Conversation summary cannot be empty")
|
|
84
|
+
.max(10000, "Conversation summary too long (max 10000 characters)")
|
|
85
|
+
.describe("Brief summary of the conversation content to evaluate"),
|
|
86
|
+
},
|
|
87
|
+
}, async ({ conversationSummary }) => ({
|
|
88
|
+
messages: [
|
|
89
|
+
{
|
|
90
|
+
role: "user",
|
|
91
|
+
content: {
|
|
92
|
+
type: "text",
|
|
93
|
+
text: `Evaluate whether this conversation should be captured as evidence using Footprint.
|
|
94
|
+
|
|
95
|
+
## Conversation Summary
|
|
96
|
+
${conversationSummary}
|
|
97
|
+
|
|
98
|
+
## Decision Criteria
|
|
99
|
+
Rate each category 0-3 (0=none, 1=low, 2=medium, 3=high):
|
|
100
|
+
|
|
101
|
+
1. **Intellectual Property Value**: Does it contain inventions, algorithms, novel approaches, patents, trade secrets?
|
|
102
|
+
2. **Legal Significance**: Does it involve contracts, agreements, licenses, legal obligations, regulatory requirements?
|
|
103
|
+
3. **Business Decision Impact**: Does it record decisions, approvals, milestones, deliverables, strategic direction?
|
|
104
|
+
4. **Research Value**: Does it contain hypotheses, findings, experimental results, data analysis, methodology?
|
|
105
|
+
5. **Compliance/Audit Need**: Does it need to be documented for audit trails, regulatory compliance, evidence preservation?
|
|
106
|
+
|
|
107
|
+
## Decision Rules
|
|
108
|
+
- Any category >= 2 \u2192 RECOMMEND CAPTURE
|
|
109
|
+
- Multiple categories >= 1 \u2192 RECOMMEND CAPTURE
|
|
110
|
+
- All categories = 0 \u2192 DO NOT CAPTURE
|
|
111
|
+
- Uncertain \u2192 ASK USER
|
|
112
|
+
|
|
113
|
+
## Response Format
|
|
114
|
+
Respond with:
|
|
115
|
+
- **Capture**: yes/no/ask
|
|
116
|
+
- **Confidence**: 0.0-1.0
|
|
117
|
+
- **Primary Reason**: One sentence
|
|
118
|
+
- **Suggested Tags**: comma-separated
|
|
119
|
+
- **Suggested conversationId**: {topic}-{descriptor}-{YYYY-MM-DD} format`,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=skill-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-prompt.js","sourceRoot":"","sources":["../../../src/prompts/skill-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAGzB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,qCAAqC;QAChF,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,mBAAmB,CAAC,EAAE,WAAW;KAC1D,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;6CA2BqB,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,YAAY,GAAG,WAAW,EAAE,CAAC;IAEnC,wBAAwB;IACxB,MAAM,CAAC,cAAc,CACnB,iBAAiB,EACjB;QACE,WAAW,EACT,6HAA6H;KAChI,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,YAAY,EAAE;aACvD;SACF;KACF,CAAC,CACH,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,cAAc,CACnB,qBAAqB,EACrB;QACE,WAAW,EACT,0FAA0F;KAC7F,EACD,KAAK,IAAI,EAAE,CAAC,CAAC;QACX,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,eAAe,EAAE;aAC1D;SACF;KACF,CAAC,CACH,CAAC;IAEF,sCAAsC;IACtC,MAAM,CAAC,cAAc,CACnB,0BAA0B,EAC1B;QACE,WAAW,EACT,uLAAuL;QACzL,UAAU,EAAE;YACV,mBAAmB,EAAE,CAAC;iBACnB,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,EAAE,sCAAsC,CAAC;iBAC9C,GAAG,CAAC,KAAK,EAAE,sDAAsD,CAAC;iBAClE,QAAQ,CAAC,uDAAuD,CAAC;SACrE;KACF,EACD,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAE,EAAE,CAAC,CAAC;QAClC,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAe;gBACrB,OAAO,EAAE;oBACP,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE;;;EAGhB,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;yEAuBoD;iBAC9D;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -4,9 +4,9 @@ import type { CaptureEvidenceParams } from "../types.js";
|
|
|
4
4
|
export declare const captureFootprintSchema: {
|
|
5
5
|
inputSchema: {
|
|
6
6
|
conversationId: z.ZodString;
|
|
7
|
-
llmProvider: z.ZodString
|
|
7
|
+
llmProvider: z.ZodDefault<z.ZodString>;
|
|
8
8
|
content: z.ZodString;
|
|
9
|
-
messageCount: z.ZodNumber
|
|
9
|
+
messageCount: z.ZodOptional<z.ZodNumber>;
|
|
10
10
|
tags: z.ZodOptional<z.ZodString>;
|
|
11
11
|
};
|
|
12
12
|
outputSchema: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-footprint.d.ts","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"capture-footprint.d.ts","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAKzB,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;CAyClC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;CAIpC,CAAC;AAEF,wBAAgB,6BAA6B,CAC3C,EAAE,EAAE,gBAAgB,EACpB,aAAa,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC;;;;;IAyHzC"}
|
|
@@ -6,15 +6,28 @@ import { encrypt } from "../lib/crypto/index.js";
|
|
|
6
6
|
import { getCurrentCommit, } from "../lib/storage/index.js";
|
|
7
7
|
export const captureFootprintSchema = {
|
|
8
8
|
inputSchema: {
|
|
9
|
-
conversationId: z
|
|
9
|
+
conversationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.max(500, "Conversation ID too long (max 500 chars)")
|
|
12
|
+
.describe("Unique conversation identifier. Recommended format: {topic}-{descriptor}-{YYYY-MM-DD} (e.g., api-auth-decision-2026-01-28)"),
|
|
10
13
|
llmProvider: z
|
|
11
14
|
.string()
|
|
12
|
-
.
|
|
15
|
+
.default("unknown")
|
|
16
|
+
.describe("LLM provider name (e.g., Claude Sonnet 4.5). Defaults to 'unknown' if not specified."),
|
|
13
17
|
content: z
|
|
14
18
|
.string()
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
.max(10 * 1024 * 1024, "Content exceeds 10MB limit")
|
|
20
|
+
.describe("Full conversation text including both human and assistant messages. Include complete message history for accurate evidence preservation."),
|
|
21
|
+
messageCount: z
|
|
22
|
+
.number()
|
|
23
|
+
.int()
|
|
24
|
+
.positive()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Number of messages in the conversation. If omitted, auto-calculated by counting conversation turn markers (Human:/Assistant:/User:/AI:/System:)."),
|
|
27
|
+
tags: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Comma-separated tags for categorization (e.g., 'ip,patent,decision'). Use 3-6 tags. Common types: decision, milestone, research, legal, compliance."),
|
|
18
31
|
},
|
|
19
32
|
outputSchema: {
|
|
20
33
|
id: z.string(),
|
|
@@ -25,7 +38,7 @@ export const captureFootprintSchema = {
|
|
|
25
38
|
};
|
|
26
39
|
export const captureFootprintMetadata = {
|
|
27
40
|
title: "Capture Footprint",
|
|
28
|
-
description: "Capture and encrypt LLM conversation as footprint",
|
|
41
|
+
description: "Capture and encrypt an LLM conversation as a tamper-evident footprint. Use when: user explicitly asks to save, or high-value content detected (IP, legal, business, research, compliance). Creates encrypted record with SHA-256 hash and Git timestamp anchor.",
|
|
29
42
|
};
|
|
30
43
|
export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
31
44
|
return wrapToolHandler("capture-footprint", "Check content is not empty, messageCount is positive, and tags format is valid.", async (params) => {
|
|
@@ -33,7 +46,14 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
|
33
46
|
if (!params.content || params.content.trim().length === 0) {
|
|
34
47
|
throw new Error("Content cannot be empty");
|
|
35
48
|
}
|
|
36
|
-
|
|
49
|
+
const MAX_CONTENT_LENGTH = 10 * 1024 * 1024; // 10MB
|
|
50
|
+
if (params.content.length > MAX_CONTENT_LENGTH) {
|
|
51
|
+
throw new Error(`Content too large (${(params.content.length / (1024 * 1024)).toFixed(1)}MB). Maximum 10MB allowed.`);
|
|
52
|
+
}
|
|
53
|
+
if (params.conversationId.length > 500) {
|
|
54
|
+
throw new Error("Conversation ID too long (max 500 chars)");
|
|
55
|
+
}
|
|
56
|
+
if (params.messageCount !== undefined && params.messageCount <= 0) {
|
|
37
57
|
throw new Error("Message count must be positive");
|
|
38
58
|
}
|
|
39
59
|
// eslint-disable-next-line no-control-regex
|
|
@@ -42,6 +62,8 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
|
42
62
|
}
|
|
43
63
|
// Validate and sanitize tags if provided
|
|
44
64
|
if (params.tags) {
|
|
65
|
+
const MAX_TAG_LENGTH = 100;
|
|
66
|
+
const MAX_TAGS_COUNT = 20;
|
|
45
67
|
const tags = params.tags
|
|
46
68
|
.split(",")
|
|
47
69
|
.map((t) => t.trim())
|
|
@@ -49,14 +71,33 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
|
49
71
|
if (tags.length === 0) {
|
|
50
72
|
throw new Error("All provided tags are empty or whitespace");
|
|
51
73
|
}
|
|
74
|
+
if (tags.length > MAX_TAGS_COUNT) {
|
|
75
|
+
throw new Error(`Too many tags (${tags.length}). Maximum ${MAX_TAGS_COUNT} tags allowed.`);
|
|
76
|
+
}
|
|
52
77
|
for (const tag of tags) {
|
|
78
|
+
if (tag.length > MAX_TAG_LENGTH) {
|
|
79
|
+
throw new Error(`Tag too long (${tag.length} chars). Maximum ${MAX_TAG_LENGTH} characters per tag.`);
|
|
80
|
+
}
|
|
53
81
|
// eslint-disable-next-line no-control-regex
|
|
54
82
|
if (/[\x00\n\r,]/.test(tag)) {
|
|
55
83
|
throw new Error(`Invalid tag format: "${tag}". Tags cannot contain null bytes, newlines, or commas.`);
|
|
56
84
|
}
|
|
57
85
|
}
|
|
58
|
-
|
|
86
|
+
// Use sanitized tags without mutating original params
|
|
87
|
+
params = { ...params, tags: tags.join(",") };
|
|
88
|
+
}
|
|
89
|
+
// Auto-calculate messageCount if not provided
|
|
90
|
+
let messageCount = params.messageCount;
|
|
91
|
+
if (!messageCount) {
|
|
92
|
+
const turnPattern = /^(Human|Assistant|User|System|AI):/im;
|
|
93
|
+
const lines = params.content.split("\n");
|
|
94
|
+
messageCount = lines.filter((line) => turnPattern.test(line.trim())).length;
|
|
95
|
+
if (messageCount === 0)
|
|
96
|
+
messageCount = 1; // Default to 1 if no turns detected
|
|
59
97
|
}
|
|
98
|
+
// Apply runtime defaults for parameters with Zod schema defaults
|
|
99
|
+
// (Zod defaults only apply through MCP SDK transport layer)
|
|
100
|
+
const llmProvider = params.llmProvider || "unknown";
|
|
60
101
|
// Encrypt and capture
|
|
61
102
|
const key = await getDerivedKey();
|
|
62
103
|
const encrypted = await encrypt(params.content, key);
|
|
@@ -69,11 +110,11 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
|
69
110
|
const id = db.create({
|
|
70
111
|
timestamp,
|
|
71
112
|
conversationId: params.conversationId,
|
|
72
|
-
llmProvider
|
|
113
|
+
llmProvider,
|
|
73
114
|
encryptedContent: encrypted.ciphertext,
|
|
74
115
|
nonce: encrypted.nonce,
|
|
75
116
|
contentHash,
|
|
76
|
-
messageCount
|
|
117
|
+
messageCount,
|
|
77
118
|
gitCommitHash: gitInfo?.commitHash || null,
|
|
78
119
|
gitTimestamp: gitInfo?.timestamp || null,
|
|
79
120
|
tags: params.tags || null,
|
|
@@ -82,7 +123,7 @@ export function createCaptureFootprintHandler(db, getDerivedKey) {
|
|
|
82
123
|
ID: id,
|
|
83
124
|
Timestamp: timestamp,
|
|
84
125
|
"Git Commit": gitInfo?.commitHash || "N/A",
|
|
85
|
-
"Message Count":
|
|
126
|
+
"Message Count": messageCount,
|
|
86
127
|
}, {
|
|
87
128
|
id,
|
|
88
129
|
timestamp,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-footprint.js","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"capture-footprint.js","sourceRoot":"","sources":["../../../src/tools/capture-footprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,17 @@ import * as z from "zod";
|
|
|
2
2
|
import type { EvidenceDatabase } from "../lib/storage/index.js";
|
|
3
3
|
export declare const deleteFootprintsSchema: {
|
|
4
4
|
inputSchema: {
|
|
5
|
-
evidenceIds: z.ZodArray<z.ZodString
|
|
5
|
+
evidenceIds: z.ZodArray<z.ZodString>;
|
|
6
|
+
confirmDelete: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
6
7
|
};
|
|
7
8
|
outputSchema: {
|
|
8
9
|
deletedCount: z.ZodNumber;
|
|
10
|
+
previewed: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
conversationId: z.ZodString;
|
|
13
|
+
timestamp: z.ZodString;
|
|
14
|
+
}, z.core.$strip>>>;
|
|
15
|
+
notFoundIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
9
16
|
success: z.ZodBoolean;
|
|
10
17
|
};
|
|
11
18
|
};
|
|
@@ -15,8 +22,18 @@ export declare const deleteFootprintsMetadata: {
|
|
|
15
22
|
};
|
|
16
23
|
export declare function createDeleteFootprintsHandler(db: EvidenceDatabase): (params: {
|
|
17
24
|
evidenceIds: string[];
|
|
25
|
+
confirmDelete?: boolean;
|
|
18
26
|
}) => Promise<import("../lib/tool-response.js").ToolResponse<{
|
|
19
27
|
deletedCount: number;
|
|
28
|
+
previewed: {
|
|
29
|
+
id: string;
|
|
30
|
+
conversationId: string | null;
|
|
31
|
+
timestamp: string;
|
|
32
|
+
}[];
|
|
33
|
+
success: boolean;
|
|
34
|
+
}> | import("../lib/tool-response.js").ToolResponse<{
|
|
35
|
+
deletedCount: number;
|
|
36
|
+
notFoundIds: string[];
|
|
20
37
|
success: boolean;
|
|
21
38
|
}>>;
|
|
22
39
|
//# sourceMappingURL=delete-footprints.d.ts.map
|