@c3-oss/prosa 0.2.0 → 0.3.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/dist/bin/prosa.js +233 -98
- package/dist/bin/prosa.js.map +1 -1
- package/dist/cli/main.js +233 -98
- package/dist/cli/main.js.map +1 -1
- package/dist/index.d.ts +57 -6
- package/dist/index.js +2256 -2125
- package/dist/index.js.map +1 -1
- package/package.json +18 -2
package/dist/cli/main.js
CHANGED
|
@@ -1120,8 +1120,6 @@ var PROSA_PARSER_VERSION = "0.1.0";
|
|
|
1120
1120
|
var PROSA_SCHEMA_VERSION = 2;
|
|
1121
1121
|
|
|
1122
1122
|
// src/cli/commands/compile.ts
|
|
1123
|
-
import os2 from "os";
|
|
1124
|
-
import path14 from "path";
|
|
1125
1123
|
import { Command } from "commander";
|
|
1126
1124
|
|
|
1127
1125
|
// src/core/bundle.ts
|
|
@@ -1627,6 +1625,10 @@ function closeBundle(bundle) {
|
|
|
1627
1625
|
closeDb(bundle.db);
|
|
1628
1626
|
}
|
|
1629
1627
|
|
|
1628
|
+
// src/services/compile.ts
|
|
1629
|
+
import os2 from "os";
|
|
1630
|
+
import path14 from "path";
|
|
1631
|
+
|
|
1630
1632
|
// src/importers/claude/index.ts
|
|
1631
1633
|
init_cas();
|
|
1632
1634
|
init_db();
|
|
@@ -5628,35 +5630,9 @@ function isMissingParquetError(error) {
|
|
|
5628
5630
|
return /No files found|does not exist|not found/i.test(message) && /\.parquet/i.test(message);
|
|
5629
5631
|
}
|
|
5630
5632
|
|
|
5631
|
-
// src/
|
|
5633
|
+
// src/services/compile.ts
|
|
5632
5634
|
init_indexing();
|
|
5633
|
-
|
|
5634
|
-
// src/cli/logger.ts
|
|
5635
|
-
import pino from "pino";
|
|
5636
|
-
import pretty from "pino-pretty";
|
|
5637
|
-
function createCliLogger(options) {
|
|
5638
|
-
const loggerOptions = {
|
|
5639
|
-
base: void 0,
|
|
5640
|
-
level: options.verbose === true ? "debug" : "info"
|
|
5641
|
-
};
|
|
5642
|
-
if (options.jsonLogs === true) {
|
|
5643
|
-
return pino(loggerOptions, pino.destination({ dest: 2, sync: true }));
|
|
5644
|
-
}
|
|
5645
|
-
return pino(
|
|
5646
|
-
loggerOptions,
|
|
5647
|
-
pretty({
|
|
5648
|
-
colorize: process.stderr.isTTY,
|
|
5649
|
-
destination: 2,
|
|
5650
|
-
ignore: "pid,hostname",
|
|
5651
|
-
singleLine: true,
|
|
5652
|
-
sync: true,
|
|
5653
|
-
translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l"
|
|
5654
|
-
})
|
|
5655
|
-
);
|
|
5656
|
-
}
|
|
5657
|
-
|
|
5658
|
-
// src/cli/commands/compile.ts
|
|
5659
|
-
var PROVIDERS = [
|
|
5635
|
+
var COMPILE_PROVIDERS = [
|
|
5660
5636
|
{
|
|
5661
5637
|
name: "codex",
|
|
5662
5638
|
description: "Import Codex CLI session histories into the bundle.",
|
|
@@ -5686,13 +5662,129 @@ var PROVIDERS = [
|
|
|
5686
5662
|
compile: compileCursor
|
|
5687
5663
|
}
|
|
5688
5664
|
];
|
|
5665
|
+
function getCompileProvider(source) {
|
|
5666
|
+
const provider = COMPILE_PROVIDERS.find((p) => p.name === source);
|
|
5667
|
+
if (!provider) {
|
|
5668
|
+
throw new Error(`unknown compile source: ${source}`);
|
|
5669
|
+
}
|
|
5670
|
+
return provider;
|
|
5671
|
+
}
|
|
5672
|
+
function resolveCompilePath(p) {
|
|
5673
|
+
if (p === "~") return os2.homedir();
|
|
5674
|
+
if (p.startsWith("~/")) return path14.join(os2.homedir(), p.slice(2));
|
|
5675
|
+
return path14.resolve(p);
|
|
5676
|
+
}
|
|
5677
|
+
async function runCompileImports(options) {
|
|
5678
|
+
const { bundle, providers, deferIndex, logger } = options;
|
|
5679
|
+
let importedAny = false;
|
|
5680
|
+
const summaries = [];
|
|
5681
|
+
let tantivy = null;
|
|
5682
|
+
let tantivyError = null;
|
|
5683
|
+
try {
|
|
5684
|
+
if (deferIndex) {
|
|
5685
|
+
logger?.info("disabling FTS5 triggers for deferred indexing");
|
|
5686
|
+
disableFts5Triggers(bundle);
|
|
5687
|
+
}
|
|
5688
|
+
for (const provider of providers) {
|
|
5689
|
+
const sourcePath = resolveCompilePath(options.sessionsPath ?? provider.defaultSessionsPath());
|
|
5690
|
+
const providerLogger = logger?.child({
|
|
5691
|
+
source_tool: provider.name,
|
|
5692
|
+
source_path: sourcePath
|
|
5693
|
+
});
|
|
5694
|
+
providerLogger?.info("starting compile");
|
|
5695
|
+
const r = await provider.compile(bundle, sourcePath, { logger: providerLogger });
|
|
5696
|
+
importedAny ||= r.counts.source_files_imported > 0;
|
|
5697
|
+
providerLogger?.info(
|
|
5698
|
+
{
|
|
5699
|
+
batch_id: r.batch.batch_id,
|
|
5700
|
+
counts: r.counts
|
|
5701
|
+
},
|
|
5702
|
+
"compile finished"
|
|
5703
|
+
);
|
|
5704
|
+
const summary = {
|
|
5705
|
+
source: provider.name,
|
|
5706
|
+
sourcePath,
|
|
5707
|
+
batchId: r.batch.batch_id,
|
|
5708
|
+
batch: r.batch,
|
|
5709
|
+
counts: r.counts
|
|
5710
|
+
};
|
|
5711
|
+
summaries.push(summary);
|
|
5712
|
+
options.onProviderComplete?.(summary);
|
|
5713
|
+
}
|
|
5714
|
+
logger?.info({ changed: importedAny, fts5_deferred: deferIndex }, "marking indexes");
|
|
5715
|
+
markIndexesAfterImport(bundle, {
|
|
5716
|
+
changed: importedAny,
|
|
5717
|
+
fts5Deferred: deferIndex
|
|
5718
|
+
});
|
|
5719
|
+
if (importedAny) {
|
|
5720
|
+
try {
|
|
5721
|
+
logger?.info("rebuilding tantivy index");
|
|
5722
|
+
const status = await rebuildTantivyIndex(bundle);
|
|
5723
|
+
tantivy = { indexedDocCount: status.indexed_doc_count };
|
|
5724
|
+
options.onTantivyComplete?.(tantivy);
|
|
5725
|
+
} catch (error) {
|
|
5726
|
+
tantivyError = error instanceof Error ? error.message : String(error);
|
|
5727
|
+
logger?.error({ err: error }, "tantivy rebuild failed; SQLite data is intact");
|
|
5728
|
+
}
|
|
5729
|
+
}
|
|
5730
|
+
} finally {
|
|
5731
|
+
if (deferIndex) {
|
|
5732
|
+
logger?.info("re-enabling FTS5 triggers");
|
|
5733
|
+
enableFts5Triggers(bundle);
|
|
5734
|
+
}
|
|
5735
|
+
}
|
|
5736
|
+
return {
|
|
5737
|
+
providers: summaries,
|
|
5738
|
+
importedAny,
|
|
5739
|
+
tantivy,
|
|
5740
|
+
tantivyError
|
|
5741
|
+
};
|
|
5742
|
+
}
|
|
5743
|
+
async function exportCompileParquet(options) {
|
|
5744
|
+
const storePath = resolveCompilePath(options.storePath);
|
|
5745
|
+
options.logger?.info({ store_path: storePath }, "exporting parquet");
|
|
5746
|
+
const result = await exportBundleParquet({ bundlePath: storePath });
|
|
5747
|
+
return {
|
|
5748
|
+
outDir: result.outDir,
|
|
5749
|
+
manifestPath: result.manifestPath,
|
|
5750
|
+
tableCount: Object.keys(result.files).length,
|
|
5751
|
+
files: result.files,
|
|
5752
|
+
counts: result.counts
|
|
5753
|
+
};
|
|
5754
|
+
}
|
|
5755
|
+
|
|
5756
|
+
// src/cli/logger.ts
|
|
5757
|
+
import pino from "pino";
|
|
5758
|
+
import pretty from "pino-pretty";
|
|
5759
|
+
function createCliLogger(options) {
|
|
5760
|
+
const loggerOptions = {
|
|
5761
|
+
base: void 0,
|
|
5762
|
+
level: options.verbose === true ? "debug" : "info"
|
|
5763
|
+
};
|
|
5764
|
+
if (options.jsonLogs === true) {
|
|
5765
|
+
return pino(loggerOptions, pino.destination({ dest: 2, sync: true }));
|
|
5766
|
+
}
|
|
5767
|
+
return pino(
|
|
5768
|
+
loggerOptions,
|
|
5769
|
+
pretty({
|
|
5770
|
+
colorize: process.stderr.isTTY,
|
|
5771
|
+
destination: 2,
|
|
5772
|
+
ignore: "pid,hostname",
|
|
5773
|
+
singleLine: true,
|
|
5774
|
+
sync: true,
|
|
5775
|
+
translateTime: "SYS:yyyy-mm-dd HH:MM:ss.l"
|
|
5776
|
+
})
|
|
5777
|
+
);
|
|
5778
|
+
}
|
|
5779
|
+
|
|
5780
|
+
// src/cli/commands/compile.ts
|
|
5689
5781
|
function compileCommand() {
|
|
5690
5782
|
const command = addCompileLogOptions(
|
|
5691
5783
|
new Command("compile").description(
|
|
5692
5784
|
"Import session histories from one agent CLI into the bundle."
|
|
5693
5785
|
)
|
|
5694
5786
|
);
|
|
5695
|
-
for (const provider of
|
|
5787
|
+
for (const provider of COMPILE_PROVIDERS) {
|
|
5696
5788
|
command.addCommand(providerCompileCommand(provider));
|
|
5697
5789
|
}
|
|
5698
5790
|
command.action(() => {
|
|
@@ -5703,7 +5795,7 @@ function compileCommand() {
|
|
|
5703
5795
|
function compileAllCommand() {
|
|
5704
5796
|
return addCompileLogOptions(new Command("compile-all")).description("Import all agent CLI session histories using default source paths.").option("--defer-index", "skip immediate FTS5 updates; run `prosa index fts5` later").action(async (options) => {
|
|
5705
5797
|
await runCompiles({
|
|
5706
|
-
providers:
|
|
5798
|
+
providers: COMPILE_PROVIDERS,
|
|
5707
5799
|
storePath: defaultBundlePath(),
|
|
5708
5800
|
deferIndex: options.deferIndex === true,
|
|
5709
5801
|
logOptions: options
|
|
@@ -5732,76 +5824,42 @@ function addCompileLogOptions(command) {
|
|
|
5732
5824
|
}
|
|
5733
5825
|
async function runCompiles(options) {
|
|
5734
5826
|
const logger = createCliLogger(options.logOptions);
|
|
5735
|
-
const storePath =
|
|
5827
|
+
const storePath = resolveCompilePath(options.storePath);
|
|
5736
5828
|
logger.info({ store_path: storePath }, "opening bundle");
|
|
5737
5829
|
const bundle = await openBundle(storePath);
|
|
5738
5830
|
let importedAny = false;
|
|
5739
5831
|
try {
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
});
|
|
5750
|
-
providerLogger.info("starting compile");
|
|
5751
|
-
const r = await provider.compile(bundle, sourcePath, { logger: providerLogger });
|
|
5752
|
-
importedAny ||= r.counts.source_files_imported > 0;
|
|
5753
|
-
providerLogger.info(
|
|
5754
|
-
{
|
|
5755
|
-
batch_id: r.batch.batch_id,
|
|
5756
|
-
counts: r.counts
|
|
5757
|
-
},
|
|
5758
|
-
"compile finished"
|
|
5759
|
-
);
|
|
5760
|
-
printCounts(provider.name, r.batch.batch_id, r.counts);
|
|
5761
|
-
}
|
|
5762
|
-
logger.info({ changed: importedAny, fts5_deferred: options.deferIndex }, "marking indexes");
|
|
5763
|
-
markIndexesAfterImport(bundle, {
|
|
5764
|
-
changed: importedAny,
|
|
5765
|
-
fts5Deferred: options.deferIndex
|
|
5766
|
-
});
|
|
5767
|
-
if (importedAny) {
|
|
5768
|
-
try {
|
|
5769
|
-
logger.info("rebuilding tantivy index");
|
|
5770
|
-
const status = await rebuildTantivyIndex(bundle);
|
|
5771
|
-
process.stdout.write(`tantivy: indexed ${status.indexed_doc_count} docs
|
|
5832
|
+
const result = await runCompileImports({
|
|
5833
|
+
bundle,
|
|
5834
|
+
providers: options.providers,
|
|
5835
|
+
deferIndex: options.deferIndex,
|
|
5836
|
+
sessionsPath: options.sessionsPath,
|
|
5837
|
+
logger,
|
|
5838
|
+
onProviderComplete: printCounts,
|
|
5839
|
+
onTantivyComplete: (status) => {
|
|
5840
|
+
process.stdout.write(`tantivy: indexed ${status.indexedDocCount} docs
|
|
5772
5841
|
`);
|
|
5773
|
-
} catch (error) {
|
|
5774
|
-
logger.error({ err: error }, "tantivy rebuild failed; SQLite data is intact");
|
|
5775
5842
|
}
|
|
5776
|
-
}
|
|
5843
|
+
});
|
|
5844
|
+
importedAny = result.importedAny;
|
|
5777
5845
|
} finally {
|
|
5778
|
-
if (options.deferIndex) {
|
|
5779
|
-
logger.info("re-enabling FTS5 triggers");
|
|
5780
|
-
enableFts5Triggers(bundle);
|
|
5781
|
-
}
|
|
5782
5846
|
closeBundle(bundle);
|
|
5783
5847
|
logger.info({ store_path: storePath }, "bundle closed");
|
|
5784
5848
|
}
|
|
5785
5849
|
if (importedAny) {
|
|
5786
5850
|
try {
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
const tableCount = Object.keys(result.files).length;
|
|
5790
|
-
process.stdout.write(`parquet: wrote ${tableCount} tables to ${result.outDir}
|
|
5851
|
+
const result = await exportCompileParquet({ storePath, logger });
|
|
5852
|
+
process.stdout.write(`parquet: wrote ${result.tableCount} tables to ${result.outDir}
|
|
5791
5853
|
`);
|
|
5792
5854
|
} catch (error) {
|
|
5793
5855
|
logger.error({ err: error }, "parquet export failed; SQLite data is intact");
|
|
5794
5856
|
}
|
|
5795
5857
|
}
|
|
5796
5858
|
}
|
|
5797
|
-
function
|
|
5798
|
-
|
|
5799
|
-
if (p.startsWith("~/")) return path14.join(os2.homedir(), p.slice(2));
|
|
5800
|
-
return path14.resolve(p);
|
|
5801
|
-
}
|
|
5802
|
-
function printCounts(label, batchId, c) {
|
|
5859
|
+
function printCounts(summary) {
|
|
5860
|
+
const c = summary.counts;
|
|
5803
5861
|
process.stdout.write(
|
|
5804
|
-
`${
|
|
5862
|
+
`${summary.source} import: batch=${summary.batchId}
|
|
5805
5863
|
source_files seen=${c.source_files_seen} imported=${c.source_files_imported} skipped=${c.source_files_skipped}
|
|
5806
5864
|
sessions=${c.sessions} turns=${c.turns} messages=${c.messages} blocks=${c.content_blocks}
|
|
5807
5865
|
events=${c.events} tool_calls=${c.tool_calls} tool_results=${c.tool_results}
|
|
@@ -6128,10 +6186,13 @@ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/
|
|
|
6128
6186
|
|
|
6129
6187
|
// src/mcp/guidance.ts
|
|
6130
6188
|
var PROSA_MCP_INSTRUCTIONS = `
|
|
6131
|
-
prosa is a
|
|
6132
|
-
commands, decisions, file touches, and full transcripts before answering from
|
|
6189
|
+
prosa is a local memory over local agent session histories. Use it to import recent sessions,
|
|
6190
|
+
find prior work, commands, decisions, file touches, and full transcripts before answering from
|
|
6191
|
+
memory.
|
|
6133
6192
|
|
|
6134
6193
|
Recommended workflow:
|
|
6194
|
+
- Use compile to refresh the bundle when recent local sessions may not be indexed yet. With no
|
|
6195
|
+
input it imports all supported providers from default paths.
|
|
6135
6196
|
- For open-ended questions, start with search_sessions using 2-5 concrete terms.
|
|
6136
6197
|
- For questions about a file or path, start with find_touched_files, then inspect the returned sessions.
|
|
6137
6198
|
- After search results, call get_session for the most relevant session_ids before drawing conclusions.
|
|
@@ -6181,7 +6242,76 @@ init_search();
|
|
|
6181
6242
|
init_sessions();
|
|
6182
6243
|
function registerProsaTools(server, bundle, options = {}) {
|
|
6183
6244
|
const searchEngine = options.searchEngine ?? "fts5";
|
|
6245
|
+
const storePath = options.storePath ?? bundle.path;
|
|
6184
6246
|
registerProsaPrompts(server);
|
|
6247
|
+
server.registerTool(
|
|
6248
|
+
"compile",
|
|
6249
|
+
{
|
|
6250
|
+
title: "Compile sessions",
|
|
6251
|
+
description: "Import local agent session histories into the active prosa bundle. With no input, compiles all providers from default paths. With source, compiles that provider; sessions_path may override that provider path.",
|
|
6252
|
+
inputSchema: {
|
|
6253
|
+
source: z.enum(["cursor", "codex", "claude", "gemini"]).optional(),
|
|
6254
|
+
sessions_path: z.string().min(1).optional()
|
|
6255
|
+
},
|
|
6256
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true }
|
|
6257
|
+
},
|
|
6258
|
+
async ({ source, sessions_path }) => {
|
|
6259
|
+
if (sessions_path && !source) {
|
|
6260
|
+
return {
|
|
6261
|
+
content: [
|
|
6262
|
+
{
|
|
6263
|
+
type: "text",
|
|
6264
|
+
text: "sessions_path requires source because providers use incompatible source layouts"
|
|
6265
|
+
}
|
|
6266
|
+
],
|
|
6267
|
+
isError: true
|
|
6268
|
+
};
|
|
6269
|
+
}
|
|
6270
|
+
try {
|
|
6271
|
+
const result = await runCompileImports({
|
|
6272
|
+
bundle,
|
|
6273
|
+
providers: source ? [getCompileProvider(source)] : COMPILE_PROVIDERS,
|
|
6274
|
+
deferIndex: false,
|
|
6275
|
+
sessionsPath: sessions_path
|
|
6276
|
+
});
|
|
6277
|
+
const parquet = result.importedAny ? await exportCompileParquet({ storePath }) : null;
|
|
6278
|
+
return {
|
|
6279
|
+
content: [
|
|
6280
|
+
{
|
|
6281
|
+
type: "text",
|
|
6282
|
+
text: JSON.stringify(
|
|
6283
|
+
{
|
|
6284
|
+
providers: result.providers.map((provider) => ({
|
|
6285
|
+
source: provider.source,
|
|
6286
|
+
source_path: provider.sourcePath,
|
|
6287
|
+
batch_id: provider.batchId,
|
|
6288
|
+
counts: provider.counts
|
|
6289
|
+
})),
|
|
6290
|
+
imported_any: result.importedAny,
|
|
6291
|
+
tantivy: result.tantivy ? { indexed_doc_count: result.tantivy.indexedDocCount } : null,
|
|
6292
|
+
tantivy_error: result.tantivyError,
|
|
6293
|
+
parquet: parquet ? {
|
|
6294
|
+
out_dir: parquet.outDir,
|
|
6295
|
+
manifest_path: parquet.manifestPath,
|
|
6296
|
+
table_count: parquet.tableCount,
|
|
6297
|
+
files: parquet.files,
|
|
6298
|
+
counts: parquet.counts
|
|
6299
|
+
} : null
|
|
6300
|
+
},
|
|
6301
|
+
null,
|
|
6302
|
+
2
|
|
6303
|
+
)
|
|
6304
|
+
}
|
|
6305
|
+
]
|
|
6306
|
+
};
|
|
6307
|
+
} catch (error) {
|
|
6308
|
+
return {
|
|
6309
|
+
content: [{ type: "text", text: error instanceof Error ? error.message : String(error) }],
|
|
6310
|
+
isError: true
|
|
6311
|
+
};
|
|
6312
|
+
}
|
|
6313
|
+
}
|
|
6314
|
+
);
|
|
6185
6315
|
server.registerTool(
|
|
6186
6316
|
"list_sessions",
|
|
6187
6317
|
{
|
|
@@ -6494,7 +6624,7 @@ function registerProsaPrompts(server) {
|
|
|
6494
6624
|
|
|
6495
6625
|
// src/mcp/server.ts
|
|
6496
6626
|
async function listenMcpStdioServer(bundle, options = {}) {
|
|
6497
|
-
const server = createMcpServer(bundle, options.searchEngine ?? "fts5");
|
|
6627
|
+
const server = createMcpServer(bundle, options.searchEngine ?? "fts5", options.storePath);
|
|
6498
6628
|
const transport = new StdioServerTransport();
|
|
6499
6629
|
await server.connect(transport);
|
|
6500
6630
|
return {
|
|
@@ -6508,10 +6638,13 @@ async function listenMcpServer(bundle, options) {
|
|
|
6508
6638
|
const mcpPath = options.path ?? "/mcp";
|
|
6509
6639
|
const sessions = /* @__PURE__ */ new Map();
|
|
6510
6640
|
const searchEngine = options.searchEngine ?? "fts5";
|
|
6641
|
+
const storePath = options.storePath ?? bundle.path;
|
|
6511
6642
|
const httpServer = http.createServer((req, res) => {
|
|
6512
|
-
handleRequest(req, res, mcpPath, sessions, bundle, searchEngine).catch(
|
|
6513
|
-
|
|
6514
|
-
|
|
6643
|
+
handleRequest(req, res, mcpPath, sessions, bundle, searchEngine, storePath).catch(
|
|
6644
|
+
(error) => {
|
|
6645
|
+
writeError(res, error);
|
|
6646
|
+
}
|
|
6647
|
+
);
|
|
6515
6648
|
});
|
|
6516
6649
|
await new Promise((resolve, reject) => {
|
|
6517
6650
|
httpServer.once("error", reject);
|
|
@@ -6534,7 +6667,7 @@ async function listenMcpServer(bundle, options) {
|
|
|
6534
6667
|
}
|
|
6535
6668
|
};
|
|
6536
6669
|
}
|
|
6537
|
-
async function handleRequest(req, res, mcpPath, sessions, bundle, searchEngine) {
|
|
6670
|
+
async function handleRequest(req, res, mcpPath, sessions, bundle, searchEngine, storePath) {
|
|
6538
6671
|
if (!req.url || !req.url.startsWith(mcpPath)) {
|
|
6539
6672
|
res.writeHead(404).end();
|
|
6540
6673
|
return;
|
|
@@ -6556,14 +6689,14 @@ async function handleRequest(req, res, mcpPath, sessions, bundle, searchEngine)
|
|
|
6556
6689
|
res.writeHead(404).end();
|
|
6557
6690
|
return;
|
|
6558
6691
|
}
|
|
6559
|
-
entry = await openSession(bundle, sessions, searchEngine);
|
|
6692
|
+
entry = await openSession(bundle, sessions, searchEngine, storePath);
|
|
6560
6693
|
}
|
|
6561
6694
|
const bodyText = await readBody(req);
|
|
6562
6695
|
const body = bodyText.length > 0 ? safeJsonParse(bodyText) : void 0;
|
|
6563
6696
|
await entry.transport.handleRequest(req, res, body);
|
|
6564
6697
|
}
|
|
6565
|
-
async function openSession(bundle, store, searchEngine) {
|
|
6566
|
-
const server = createMcpServer(bundle, searchEngine);
|
|
6698
|
+
async function openSession(bundle, store, searchEngine, storePath) {
|
|
6699
|
+
const server = createMcpServer(bundle, searchEngine, storePath);
|
|
6567
6700
|
const transport = new StreamableHTTPServerTransport({
|
|
6568
6701
|
sessionIdGenerator: () => randomUUID(),
|
|
6569
6702
|
onsessioninitialized: (id) => {
|
|
@@ -6581,7 +6714,7 @@ async function openSession(bundle, store, searchEngine) {
|
|
|
6581
6714
|
await server.connect(transport);
|
|
6582
6715
|
return { server, transport };
|
|
6583
6716
|
}
|
|
6584
|
-
function createMcpServer(bundle, searchEngine) {
|
|
6717
|
+
function createMcpServer(bundle, searchEngine, storePath) {
|
|
6585
6718
|
const server = new McpServer(
|
|
6586
6719
|
{
|
|
6587
6720
|
name: "prosa",
|
|
@@ -6589,7 +6722,7 @@ function createMcpServer(bundle, searchEngine) {
|
|
|
6589
6722
|
},
|
|
6590
6723
|
{ instructions: PROSA_MCP_INSTRUCTIONS }
|
|
6591
6724
|
);
|
|
6592
|
-
registerProsaTools(server, bundle, { searchEngine });
|
|
6725
|
+
registerProsaTools(server, bundle, { searchEngine, storePath });
|
|
6593
6726
|
return server;
|
|
6594
6727
|
}
|
|
6595
6728
|
async function readBody(req) {
|
|
@@ -6630,7 +6763,8 @@ function writeError(res, error) {
|
|
|
6630
6763
|
function mcpCommand() {
|
|
6631
6764
|
const serve = new Command5("serve").description("Start a local MCP server over the prosa bundle.").option("--store <path>", "bundle directory", defaultBundlePath()).option("--transport <transport>", "MCP transport: stdio|http", "stdio").option("--host <host>", "bind host", "127.0.0.1").option("--port <port>", "bind port", "7331").option("--path <path>", "HTTP path", "/mcp").option("--search-engine <engine>", "search engine: fts5|tantivy", "fts5").action(
|
|
6632
6765
|
async (options) => {
|
|
6633
|
-
const
|
|
6766
|
+
const storePath = path18.resolve(options.store);
|
|
6767
|
+
const bundle = await openBundle(storePath);
|
|
6634
6768
|
try {
|
|
6635
6769
|
const transport = parseMcpTransport(options.transport);
|
|
6636
6770
|
const searchEngine = parseSearchEngine(options.searchEngine);
|
|
@@ -6643,7 +6777,8 @@ function mcpCommand() {
|
|
|
6643
6777
|
host: options.host,
|
|
6644
6778
|
port,
|
|
6645
6779
|
path: options.path,
|
|
6646
|
-
searchEngine
|
|
6780
|
+
searchEngine,
|
|
6781
|
+
storePath
|
|
6647
6782
|
});
|
|
6648
6783
|
process.stdout.write(`prosa mcp server listening at ${server2.url}
|
|
6649
6784
|
`);
|
|
@@ -6651,7 +6786,7 @@ function mcpCommand() {
|
|
|
6651
6786
|
registerShutdown(server2.close, bundle);
|
|
6652
6787
|
return;
|
|
6653
6788
|
}
|
|
6654
|
-
const server = await listenMcpStdioServer(bundle, { searchEngine });
|
|
6789
|
+
const server = await listenMcpStdioServer(bundle, { searchEngine, storePath });
|
|
6655
6790
|
registerShutdown(server.close, bundle);
|
|
6656
6791
|
} catch (error) {
|
|
6657
6792
|
closeBundle(bundle);
|