@papyruslabsai/seshat-mcp 0.20.0 → 0.20.1
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 +87 -0
- package/package.json +41 -48
- package/dist/bootstrap.d.ts +0 -29
- package/dist/bootstrap.js +0 -190
- package/dist/graph.d.ts +0 -42
- package/dist/graph.js +0 -272
- package/dist/index.d.ts +0 -9
- package/dist/loader.d.ts +0 -62
- package/dist/loader.js +0 -264
- package/dist/supabase.d.ts +0 -99
- package/dist/supabase.js +0 -132
- package/dist/tools/dbops.d.ts +0 -24
- package/dist/tools/dbops.js +0 -78
- package/dist/tools/diff.d.ts +0 -28
- package/dist/tools/diff.js +0 -604
- package/dist/tools/functors.d.ts +0 -150
- package/dist/tools/functors.js +0 -1727
- package/dist/tools/index.d.ts +0 -66
- package/dist/tools/index.js +0 -389
- package/dist/types.d.ts +0 -174
- package/dist/types.js +0 -8
package/dist/supabase.d.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight Supabase REST client for the calibration feedback loop.
|
|
3
|
-
*
|
|
4
|
-
* Uses Node 20+ native fetch — zero external dependencies.
|
|
5
|
-
* Gracefully degrades: if SESHAT_SUPABASE_URL / SESHAT_SUPABASE_KEY are not set,
|
|
6
|
-
* all operations silently no-op so the MCP server works offline.
|
|
7
|
-
*
|
|
8
|
-
* Environment variables (checks both prefixed and standard names):
|
|
9
|
-
* SUPABASE_URL — e.g. https://nlsrjceluztfllbqfpkm.supabase.co
|
|
10
|
-
* SUPABASE_SERVICE_ROLE_KEY — service_role key (preferred)
|
|
11
|
-
* SESHAT_SUPABASE_URL — override (optional)
|
|
12
|
-
* SESHAT_SUPABASE_KEY — override (optional)
|
|
13
|
-
*/
|
|
14
|
-
/** Whether Supabase logging is available. */
|
|
15
|
-
export declare function isSupabaseConfigured(): boolean;
|
|
16
|
-
export interface TokenPredictionInsert {
|
|
17
|
-
project: string;
|
|
18
|
-
target_entities: string[];
|
|
19
|
-
predicted_context_load: number;
|
|
20
|
-
predicted_iteration_mult: number;
|
|
21
|
-
predicted_total: number;
|
|
22
|
-
affected_entities: number;
|
|
23
|
-
affected_files: number;
|
|
24
|
-
affected_layers: string[];
|
|
25
|
-
estimator_used: 'syntactic' | 'charDiv4' | 'heuristic';
|
|
26
|
-
context_budget: number;
|
|
27
|
-
session_id?: string;
|
|
28
|
-
}
|
|
29
|
-
export interface ActualBurnUpdate {
|
|
30
|
-
actual_input_tokens: number;
|
|
31
|
-
actual_output_tokens: number;
|
|
32
|
-
actual_total_tokens: number;
|
|
33
|
-
model: string;
|
|
34
|
-
notes?: string;
|
|
35
|
-
}
|
|
36
|
-
export interface TokenPredictionRow {
|
|
37
|
-
id: string;
|
|
38
|
-
created_at: string;
|
|
39
|
-
project: string;
|
|
40
|
-
target_entities: string[];
|
|
41
|
-
predicted_context_load: number;
|
|
42
|
-
predicted_iteration_mult: number;
|
|
43
|
-
predicted_total: number;
|
|
44
|
-
affected_entities: number;
|
|
45
|
-
affected_files: number;
|
|
46
|
-
affected_layers: string[];
|
|
47
|
-
estimator_used: string;
|
|
48
|
-
context_budget: number;
|
|
49
|
-
actual_input_tokens: number | null;
|
|
50
|
-
actual_output_tokens: number | null;
|
|
51
|
-
actual_total_tokens: number | null;
|
|
52
|
-
model: string | null;
|
|
53
|
-
drift_ratio: number | null;
|
|
54
|
-
status: string;
|
|
55
|
-
session_id: string | null;
|
|
56
|
-
notes: string | null;
|
|
57
|
-
}
|
|
58
|
-
export interface McpTelemetryLog {
|
|
59
|
-
user_id?: string;
|
|
60
|
-
tool_name: string;
|
|
61
|
-
project_hash: string;
|
|
62
|
-
execution_ms: number;
|
|
63
|
-
}
|
|
64
|
-
export interface JstfSnapshotInsert {
|
|
65
|
-
user_id?: string;
|
|
66
|
-
project_hash: string;
|
|
67
|
-
commit_sha: string;
|
|
68
|
-
language_primary: string;
|
|
69
|
-
total_entities: number;
|
|
70
|
-
metric_typeless_interfaces: number;
|
|
71
|
-
metric_max_in_degree: number;
|
|
72
|
-
metric_circular_dependencies: number;
|
|
73
|
-
metric_untracked_data_transformations: number;
|
|
74
|
-
metric_exposure_leaks: number;
|
|
75
|
-
metric_layer_violations: number;
|
|
76
|
-
metric_ownership_violations: number;
|
|
77
|
-
metric_impure_ratio: number;
|
|
78
|
-
metric_runtime_violations: number;
|
|
79
|
-
metric_semantic_clones: number;
|
|
80
|
-
metric_core_fragility_score: number;
|
|
81
|
-
bundle_payload: unknown;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Insert a prediction row. Returns the row ID or null on failure.
|
|
85
|
-
*/
|
|
86
|
-
export declare function insertPrediction(row: TokenPredictionInsert): Promise<string | null>;
|
|
87
|
-
/**
|
|
88
|
-
* Report actual token burn for a prediction. Computes drift and sets status=completed.
|
|
89
|
-
*/
|
|
90
|
-
export declare function updateActualBurn(predictionId: string, actual: ActualBurnUpdate): Promise<TokenPredictionRow | null>;
|
|
91
|
-
/**
|
|
92
|
-
* Abandon a prediction (task was cancelled or not completed).
|
|
93
|
-
*/
|
|
94
|
-
export declare function abandonPrediction(predictionId: string): Promise<boolean>;
|
|
95
|
-
/**
|
|
96
|
-
* List recent predictions for a project (for calibration analysis).
|
|
97
|
-
*/
|
|
98
|
-
export declare function logTelemetry(log: McpTelemetryLog): Promise<void>;
|
|
99
|
-
export declare function insertJstfSnapshot(snapshot: JstfSnapshotInsert): Promise<boolean>;
|
package/dist/supabase.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lightweight Supabase REST client for the calibration feedback loop.
|
|
3
|
-
*
|
|
4
|
-
* Uses Node 20+ native fetch — zero external dependencies.
|
|
5
|
-
* Gracefully degrades: if SESHAT_SUPABASE_URL / SESHAT_SUPABASE_KEY are not set,
|
|
6
|
-
* all operations silently no-op so the MCP server works offline.
|
|
7
|
-
*
|
|
8
|
-
* Environment variables (checks both prefixed and standard names):
|
|
9
|
-
* SUPABASE_URL — e.g. https://nlsrjceluztfllbqfpkm.supabase.co
|
|
10
|
-
* SUPABASE_SERVICE_ROLE_KEY — service_role key (preferred)
|
|
11
|
-
* SESHAT_SUPABASE_URL — override (optional)
|
|
12
|
-
* SESHAT_SUPABASE_KEY — override (optional)
|
|
13
|
-
*/
|
|
14
|
-
const SUPABASE_URL = (process.env.SESHAT_SUPABASE_URL || process.env.SUPABASE_URL || '').replace(/\/$/, '');
|
|
15
|
-
const SUPABASE_KEY = process.env.SESHAT_SUPABASE_KEY || process.env.SUPABASE_SERVICE_ROLE_KEY || '';
|
|
16
|
-
/** Whether Supabase logging is available. */
|
|
17
|
-
export function isSupabaseConfigured() {
|
|
18
|
-
return SUPABASE_URL.length > 0 && SUPABASE_KEY.length > 0;
|
|
19
|
-
}
|
|
20
|
-
// ─── REST helpers ────────────────────────────────────────────────
|
|
21
|
-
const TABLE_PREDICTIONS = 'mcp_token_predictions';
|
|
22
|
-
const TABLE_TELEMETRY = 'mcp_telemetry_logs';
|
|
23
|
-
const TABLE_SNAPSHOTS = 'jstf_snapshots';
|
|
24
|
-
async function supabaseRequest(method, path, body, headers) {
|
|
25
|
-
if (!isSupabaseConfigured()) {
|
|
26
|
-
return { ok: false, status: 0, error: 'Supabase not configured' };
|
|
27
|
-
}
|
|
28
|
-
const url = `${SUPABASE_URL}/rest/v1/${path}`;
|
|
29
|
-
const reqHeaders = {
|
|
30
|
-
'apikey': SUPABASE_KEY,
|
|
31
|
-
'Authorization': `Bearer ${SUPABASE_KEY}`,
|
|
32
|
-
'Content-Type': 'application/json',
|
|
33
|
-
'Prefer': 'return=representation',
|
|
34
|
-
...headers,
|
|
35
|
-
};
|
|
36
|
-
try {
|
|
37
|
-
const res = await fetch(url, {
|
|
38
|
-
method,
|
|
39
|
-
headers: reqHeaders,
|
|
40
|
-
body: body ? JSON.stringify(body) : undefined,
|
|
41
|
-
});
|
|
42
|
-
const text = await res.text();
|
|
43
|
-
let data;
|
|
44
|
-
try {
|
|
45
|
-
data = JSON.parse(text);
|
|
46
|
-
}
|
|
47
|
-
catch {
|
|
48
|
-
data = text;
|
|
49
|
-
}
|
|
50
|
-
if (!res.ok) {
|
|
51
|
-
return { ok: false, status: res.status, error: `${res.status}: ${text}` };
|
|
52
|
-
}
|
|
53
|
-
return { ok: true, status: res.status, data };
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
return { ok: false, status: 0, error: err.message };
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// ─── Public API ──────────────────────────────────────────────────
|
|
60
|
-
/**
|
|
61
|
-
* Insert a prediction row. Returns the row ID or null on failure.
|
|
62
|
-
*/
|
|
63
|
-
export async function insertPrediction(row) {
|
|
64
|
-
const result = await supabaseRequest('POST', TABLE_PREDICTIONS, row);
|
|
65
|
-
if (!result.ok) {
|
|
66
|
-
process.stderr.write(`[seshat] Prediction log failed: ${result.error}\n`);
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
const rows = result.data;
|
|
70
|
-
return rows?.[0]?.id ?? null;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Report actual token burn for a prediction. Computes drift and sets status=completed.
|
|
74
|
-
*/
|
|
75
|
-
export async function updateActualBurn(predictionId, actual) {
|
|
76
|
-
// First fetch the prediction to compute drift
|
|
77
|
-
const fetchResult = await supabaseRequest('GET', `${TABLE_PREDICTIONS}?id=eq.${predictionId}&select=predicted_total,status`);
|
|
78
|
-
if (!fetchResult.ok) {
|
|
79
|
-
process.stderr.write(`[seshat] Fetch prediction failed: ${fetchResult.error}\n`);
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
const rows = fetchResult.data;
|
|
83
|
-
if (!rows || rows.length === 0) {
|
|
84
|
-
return null; // not found
|
|
85
|
-
}
|
|
86
|
-
const predicted = rows[0];
|
|
87
|
-
if (predicted.status !== 'predicted') {
|
|
88
|
-
return null; // already completed or abandoned
|
|
89
|
-
}
|
|
90
|
-
// Compute drift ratio
|
|
91
|
-
const driftRatio = predicted.predicted_total > 0
|
|
92
|
-
? Math.round(((actual.actual_total_tokens - predicted.predicted_total) / predicted.predicted_total) * 1000) / 1000
|
|
93
|
-
: null;
|
|
94
|
-
const updateBody = {
|
|
95
|
-
actual_input_tokens: actual.actual_input_tokens,
|
|
96
|
-
actual_output_tokens: actual.actual_output_tokens,
|
|
97
|
-
actual_total_tokens: actual.actual_total_tokens,
|
|
98
|
-
model: actual.model,
|
|
99
|
-
drift_ratio: driftRatio,
|
|
100
|
-
status: 'completed',
|
|
101
|
-
...(actual.notes ? { notes: actual.notes } : {}),
|
|
102
|
-
};
|
|
103
|
-
const updateResult = await supabaseRequest('PATCH', `${TABLE_PREDICTIONS}?id=eq.${predictionId}`, updateBody);
|
|
104
|
-
if (!updateResult.ok) {
|
|
105
|
-
process.stderr.write(`[seshat] Update actual burn failed: ${updateResult.error}\n`);
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
return updateResult.data?.[0] ?? null;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Abandon a prediction (task was cancelled or not completed).
|
|
112
|
-
*/
|
|
113
|
-
export async function abandonPrediction(predictionId) {
|
|
114
|
-
const result = await supabaseRequest('PATCH', `${TABLE_PREDICTIONS}?id=eq.${predictionId}&status=eq.predicted`, { status: 'abandoned' });
|
|
115
|
-
return result.ok;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* List recent predictions for a project (for calibration analysis).
|
|
119
|
-
*/
|
|
120
|
-
export async function logTelemetry(log) {
|
|
121
|
-
const result = await supabaseRequest('POST', TABLE_TELEMETRY, log);
|
|
122
|
-
if (!result.ok) {
|
|
123
|
-
process.stderr.write(`[seshat] Telemetry log failed: ${result.error}\n`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
export async function insertJstfSnapshot(snapshot) {
|
|
127
|
-
const result = await supabaseRequest('POST', TABLE_SNAPSHOTS, snapshot);
|
|
128
|
-
if (!result.ok) {
|
|
129
|
-
process.stderr.write(`[seshat] JSTF snapshot failed: ${result.error}\n`);
|
|
130
|
-
}
|
|
131
|
-
return result.ok;
|
|
132
|
-
}
|
package/dist/tools/dbops.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Database operation extraction from entity coordinates.
|
|
3
|
-
*
|
|
4
|
-
* Parses Supabase/Prisma call targets in the edge set and db statements in
|
|
5
|
-
* the semantics dimension to answer: which tables does this entity read or
|
|
6
|
-
* write? This is the δ-contract surface that conflict_matrix uses to detect
|
|
7
|
-
* tasks that collide through shared data even when their symbols and files
|
|
8
|
-
* are disjoint (the "spawner oscillation" class of conflict).
|
|
9
|
-
*
|
|
10
|
-
* Ported from apps/api/routes/mcp.js extractDbOperations so the package's
|
|
11
|
-
* own tools (conflict_matrix) can use it without the cloud layer.
|
|
12
|
-
*/
|
|
13
|
-
import type { JstfEntity } from '../types.js';
|
|
14
|
-
export interface DbOperation {
|
|
15
|
-
table: string;
|
|
16
|
-
operation: string;
|
|
17
|
-
type: 'db_query' | 'db_mutate';
|
|
18
|
-
}
|
|
19
|
-
export declare function extractDbOps(entity: JstfEntity): DbOperation[];
|
|
20
|
-
/** Aggregate db ops for a set of entities into read/write table sets. */
|
|
21
|
-
export declare function tableContract(entities: JstfEntity[]): {
|
|
22
|
-
reads: Set<string>;
|
|
23
|
-
writes: Set<string>;
|
|
24
|
-
};
|
package/dist/tools/dbops.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Database operation extraction from entity coordinates.
|
|
3
|
-
*
|
|
4
|
-
* Parses Supabase/Prisma call targets in the edge set and db statements in
|
|
5
|
-
* the semantics dimension to answer: which tables does this entity read or
|
|
6
|
-
* write? This is the δ-contract surface that conflict_matrix uses to detect
|
|
7
|
-
* tasks that collide through shared data even when their symbols and files
|
|
8
|
-
* are disjoint (the "spawner oscillation" class of conflict).
|
|
9
|
-
*
|
|
10
|
-
* Ported from apps/api/routes/mcp.js extractDbOperations so the package's
|
|
11
|
-
* own tools (conflict_matrix) can use it without the cloud layer.
|
|
12
|
-
*/
|
|
13
|
-
const WRITE_OPS = new Set(['insert', 'update', 'delete', 'upsert', 'create']);
|
|
14
|
-
export function extractDbOps(entity) {
|
|
15
|
-
const ops = [];
|
|
16
|
-
const seen = new Set();
|
|
17
|
-
const push = (table, operation, isWrite) => {
|
|
18
|
-
const key = `${table}:${operation}`;
|
|
19
|
-
if (seen.has(key))
|
|
20
|
-
return;
|
|
21
|
-
seen.add(key);
|
|
22
|
-
ops.push({ table, operation, type: isWrite ? 'db_mutate' : 'db_query' });
|
|
23
|
-
};
|
|
24
|
-
const edges = entity.edges;
|
|
25
|
-
const callees = (edges?.callees || edges?.calls || []);
|
|
26
|
-
for (const callee of callees) {
|
|
27
|
-
const target = typeof callee === 'string' ? callee : callee?.target || callee?.id || '';
|
|
28
|
-
const fromMatch = target.match(/\.from\s*\(\s*['"`](\w+)['"`]\s*\)/);
|
|
29
|
-
if (fromMatch) {
|
|
30
|
-
const opMatch = target.match(/\.(insert|update|delete|select|upsert|rpc)\s*\(/);
|
|
31
|
-
const operation = opMatch ? opMatch[1] : 'query';
|
|
32
|
-
push(fromMatch[1], operation, WRITE_OPS.has(operation));
|
|
33
|
-
}
|
|
34
|
-
const prismaMatch = target.match(/prisma\.(\w+)\.(findMany|findUnique|findFirst|create|update|delete|upsert|count|aggregate)\s*\(/);
|
|
35
|
-
if (prismaMatch) {
|
|
36
|
-
push(prismaMatch[1], prismaMatch[2], WRITE_OPS.has(prismaMatch[2]));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function scanSemantics(stmts) {
|
|
40
|
-
if (!Array.isArray(stmts))
|
|
41
|
-
return;
|
|
42
|
-
for (const stmt of stmts) {
|
|
43
|
-
if (!stmt || typeof stmt !== 'object')
|
|
44
|
-
continue;
|
|
45
|
-
if (stmt.type === 'db_query' || stmt.type === 'db_mutate') {
|
|
46
|
-
push(String(stmt.model || 'unknown'), String(stmt.operation || 'unknown'), stmt.type === 'db_mutate');
|
|
47
|
-
}
|
|
48
|
-
if (stmt.then)
|
|
49
|
-
scanSemantics(stmt.then);
|
|
50
|
-
if (stmt.else)
|
|
51
|
-
scanSemantics(stmt.else);
|
|
52
|
-
if (stmt.body)
|
|
53
|
-
scanSemantics(stmt.body);
|
|
54
|
-
if (stmt.catch?.body)
|
|
55
|
-
scanSemantics(stmt.catch.body);
|
|
56
|
-
if (stmt.finally)
|
|
57
|
-
scanSemantics(stmt.finally);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
scanSemantics(entity.semantics);
|
|
61
|
-
return ops;
|
|
62
|
-
}
|
|
63
|
-
/** Aggregate db ops for a set of entities into read/write table sets. */
|
|
64
|
-
export function tableContract(entities) {
|
|
65
|
-
const reads = new Set();
|
|
66
|
-
const writes = new Set();
|
|
67
|
-
for (const e of entities) {
|
|
68
|
-
for (const op of extractDbOps(e)) {
|
|
69
|
-
if (op.table === 'unknown')
|
|
70
|
-
continue;
|
|
71
|
-
if (op.type === 'db_mutate')
|
|
72
|
-
writes.add(op.table);
|
|
73
|
-
else
|
|
74
|
-
reads.add(op.table);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return { reads, writes };
|
|
78
|
-
}
|
package/dist/tools/diff.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-Bundle Analysis Tools: diff_bundle + conflict_matrix
|
|
3
|
-
*
|
|
4
|
-
* diff_bundle: Compare entities between a worktree and the loaded project.
|
|
5
|
-
* conflict_matrix: Classify conflict tiers for parallel task scheduling.
|
|
6
|
-
*
|
|
7
|
-
* These tools compare TWO entity sets (base vs branch, or task vs task),
|
|
8
|
-
* unlike the single-bundle queries in index.ts and functors.ts.
|
|
9
|
-
*/
|
|
10
|
-
import type { ProjectLoader } from '../types.js';
|
|
11
|
-
export declare function diffBundle(args: {
|
|
12
|
-
worktree_path: string;
|
|
13
|
-
project?: string;
|
|
14
|
-
include_unchanged?: boolean;
|
|
15
|
-
}, loader: ProjectLoader): Promise<unknown>;
|
|
16
|
-
export declare function conflictMatrix(args: {
|
|
17
|
-
tasks: Array<{
|
|
18
|
-
id: string;
|
|
19
|
-
entity_ids: string[];
|
|
20
|
-
dimensions?: string[];
|
|
21
|
-
expand_blast_radius?: boolean;
|
|
22
|
-
}>;
|
|
23
|
-
project?: string;
|
|
24
|
-
}, loader: ProjectLoader, extras?: {
|
|
25
|
-
/** Lineage-backed co-change provider: given entity ids, returns a map of
|
|
26
|
-
* sorted-pair keys (`${idA}${idB}`) → shared commit counts. */
|
|
27
|
-
fetchCoChanges?: (entityIds: string[]) => Promise<Map<string, number>>;
|
|
28
|
-
}): Promise<unknown>;
|