@bodhi-ventures/aiocs 0.5.3 → 0.6.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 +21 -3
- package/dist/{chunk-M767TPUX.js → chunk-2UWV3O7E.js} +676 -1
- package/dist/cli.js +206 -2
- package/dist/mcp-server.js +281 -1
- package/docs/json-contract.md +196 -0
- package/package.json +1 -1
- package/skills/aiocs/SKILL.md +37 -6
- package/skills/aiocs-curation/SKILL.md +24 -3
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AiocsError,
|
|
5
5
|
backfillEmbeddings,
|
|
6
6
|
clearEmbeddings,
|
|
7
|
+
describeSource,
|
|
7
8
|
diffSnapshotsForSource,
|
|
8
9
|
exportCatalogBackup,
|
|
9
10
|
fetchSources,
|
|
@@ -12,26 +13,33 @@ import {
|
|
|
12
13
|
getDoctorReport,
|
|
13
14
|
getEmbeddingStatus,
|
|
14
15
|
getManagedSourceSpecDirectories,
|
|
16
|
+
getSourceContextForSource,
|
|
15
17
|
importCatalogBackup,
|
|
16
18
|
initManagedSources,
|
|
17
19
|
linkProjectSources,
|
|
20
|
+
listRoutingLearningsForQuery,
|
|
18
21
|
listSnapshotsForSource,
|
|
22
|
+
listSourcePages,
|
|
19
23
|
listSources,
|
|
20
24
|
openCatalog,
|
|
21
25
|
packageName,
|
|
22
26
|
packageVersion,
|
|
23
27
|
parseDaemonConfig,
|
|
24
28
|
refreshDueSources,
|
|
29
|
+
retrieveContext,
|
|
25
30
|
runEmbeddingWorker,
|
|
26
31
|
runSourceCanaries,
|
|
32
|
+
saveRoutingLearning,
|
|
27
33
|
searchCatalog,
|
|
28
34
|
showChunk,
|
|
35
|
+
showPage,
|
|
29
36
|
startDaemon,
|
|
30
37
|
toAiocsError,
|
|
31
38
|
unlinkProjectSources,
|
|
39
|
+
upsertSourceContextFromFile,
|
|
32
40
|
upsertSourceFromSpecFile,
|
|
33
41
|
verifyCoverage
|
|
34
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-2UWV3O7E.js";
|
|
35
43
|
|
|
36
44
|
// src/cli.ts
|
|
37
45
|
import { Command, CommanderError as CommanderError2 } from "commander";
|
|
@@ -99,7 +107,7 @@ function inferRequestedCommand(argv) {
|
|
|
99
107
|
if (!first) {
|
|
100
108
|
return "cli";
|
|
101
109
|
}
|
|
102
|
-
if (["source", "snapshot", "project", "refresh", "verify", "backup"].includes(first) && second && !second.startsWith("-")) {
|
|
110
|
+
if (["source", "snapshot", "page", "project", "refresh", "verify", "backup", "learning"].includes(first) && second && !second.startsWith("-")) {
|
|
103
111
|
return `${first}.${second}`;
|
|
104
112
|
}
|
|
105
113
|
return first;
|
|
@@ -124,6 +132,20 @@ function renderSearchResult(result) {
|
|
|
124
132
|
""
|
|
125
133
|
].join("\n");
|
|
126
134
|
}
|
|
135
|
+
function renderPageResult(result) {
|
|
136
|
+
return [
|
|
137
|
+
`Source: ${result.sourceId}`,
|
|
138
|
+
`Snapshot: ${result.snapshotId}`,
|
|
139
|
+
...result.pageKind ? [`Kind: ${result.pageKind}`] : [],
|
|
140
|
+
...result.filePath ? [`Path: ${result.filePath}`] : [],
|
|
141
|
+
...result.language ? [`Language: ${result.language}`] : [],
|
|
142
|
+
`Page: ${result.title}`,
|
|
143
|
+
`URL: ${result.url}`,
|
|
144
|
+
"",
|
|
145
|
+
result.markdown,
|
|
146
|
+
""
|
|
147
|
+
].join("\n");
|
|
148
|
+
}
|
|
127
149
|
function parsePositiveIntegerOption(value, field) {
|
|
128
150
|
if (typeof value === "undefined") {
|
|
129
151
|
return void 0;
|
|
@@ -351,6 +373,58 @@ source.command("list").action(async (_options, command) => {
|
|
|
351
373
|
};
|
|
352
374
|
});
|
|
353
375
|
});
|
|
376
|
+
source.command("describe").argument("<source-id>").action(async (sourceId, _options, command) => {
|
|
377
|
+
await executeCommand(command, "source.describe", async () => {
|
|
378
|
+
const result = await describeSource(sourceId);
|
|
379
|
+
return {
|
|
380
|
+
data: result,
|
|
381
|
+
human: [
|
|
382
|
+
`${result.source.id} | ${result.source.kind} | ${result.source.label}`,
|
|
383
|
+
`Spec ${result.source.specPath ?? "(inline/unknown)"}`,
|
|
384
|
+
result.latestSnapshot ? `Latest ${result.latestSnapshot.snapshotId} | pages=${result.latestSnapshot.pageCount} | created=${result.latestSnapshot.createdAt}` : "No successful snapshots",
|
|
385
|
+
...result.context.context ? [
|
|
386
|
+
...result.context.context.purpose ? [`Purpose: ${result.context.context.purpose}`] : [],
|
|
387
|
+
...result.context.context.summary ? [`Summary: ${result.context.context.summary}`] : [],
|
|
388
|
+
...result.context.context.topicHints.length > 0 ? [`Topics: ${result.context.context.topicHints.join(", ")}`] : [],
|
|
389
|
+
...result.context.context.commonLocations.length > 0 ? [
|
|
390
|
+
"Common locations:",
|
|
391
|
+
...result.context.context.commonLocations.map((location) => `- ${location.label} | ${location.filePath ?? location.url ?? "(unknown)"}${location.note ? ` | ${location.note}` : ""}`)
|
|
392
|
+
] : []
|
|
393
|
+
] : ["No curated source context"],
|
|
394
|
+
...result.recentLearnings.length > 0 ? [
|
|
395
|
+
"Recent learnings:",
|
|
396
|
+
...result.recentLearnings.map((learning2) => `- ${learning2.learningType} | ${learning2.intent} | ${learning2.filePath ?? learning2.pageUrl ?? "(no target)"}`)
|
|
397
|
+
] : ["No routing learnings"]
|
|
398
|
+
]
|
|
399
|
+
};
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
var sourceContext = source.command("context");
|
|
403
|
+
sourceContext.command("show").argument("<source-id>").action(async (sourceId, _options, command) => {
|
|
404
|
+
await executeCommand(command, "source.context.show", async () => {
|
|
405
|
+
const result = await getSourceContextForSource(sourceId);
|
|
406
|
+
return {
|
|
407
|
+
data: result,
|
|
408
|
+
human: result.context ? [
|
|
409
|
+
`Context for ${sourceId}`,
|
|
410
|
+
...result.context.purpose ? [`Purpose: ${result.context.purpose}`] : [],
|
|
411
|
+
...result.context.summary ? [`Summary: ${result.context.summary}`] : [],
|
|
412
|
+
...result.context.topicHints.length > 0 ? [`Topics: ${result.context.topicHints.join(", ")}`] : [],
|
|
413
|
+
...result.context.authNotes.length > 0 ? ["Auth notes:", ...result.context.authNotes.map((item) => `- ${item}`)] : [],
|
|
414
|
+
...result.context.gotchas.length > 0 ? ["Gotchas:", ...result.context.gotchas.map((item) => `- ${item}`)] : []
|
|
415
|
+
] : `No curated source context for ${sourceId}`
|
|
416
|
+
};
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
sourceContext.command("upsert").argument("<source-id>").argument("<context-file>").action(async (sourceId, contextFile, _options, command) => {
|
|
420
|
+
await executeCommand(command, "source.context.upsert", async () => {
|
|
421
|
+
const result = await upsertSourceContextFromFile(sourceId, contextFile);
|
|
422
|
+
return {
|
|
423
|
+
data: result,
|
|
424
|
+
human: `Updated source context for ${result.sourceId}`
|
|
425
|
+
};
|
|
426
|
+
});
|
|
427
|
+
});
|
|
354
428
|
program.command("fetch").argument("<source-id-or-all>").action(async (sourceIdOrAll, _options, command) => {
|
|
355
429
|
await executeCommand(command, "fetch", async () => {
|
|
356
430
|
const result = await fetchSources(sourceIdOrAll);
|
|
@@ -403,6 +477,48 @@ snapshot.command("list").argument("<source-id>").action(async (sourceId, _option
|
|
|
403
477
|
};
|
|
404
478
|
});
|
|
405
479
|
});
|
|
480
|
+
var page = program.command("page");
|
|
481
|
+
page.command("list").argument("<source-id>").option("--snapshot <snapshot-id>", "list pages from a specific snapshot").option("--query <text>", "filter pages by title, url, or file path").option("--path <glob>", "restrict pages to file paths matching a glob", (value, current) => {
|
|
482
|
+
current.push(value);
|
|
483
|
+
return current;
|
|
484
|
+
}, []).option("--limit <count>", "maximum number of pages to return").option("--offset <count>", "number of pages to skip before returning results").action(async (sourceId, options, command) => {
|
|
485
|
+
await executeCommand(command, "page.list", async () => {
|
|
486
|
+
const limit = parsePositiveIntegerOption(options.limit, "limit");
|
|
487
|
+
const offset = parsePositiveIntegerOption(options.offset, "offset");
|
|
488
|
+
const result = await listSourcePages(sourceId, {
|
|
489
|
+
...options.snapshot ? { snapshot: options.snapshot } : {},
|
|
490
|
+
...options.query ? { query: options.query } : {},
|
|
491
|
+
...options.path && options.path.length > 0 ? { path: options.path } : {},
|
|
492
|
+
...typeof limit === "number" ? { limit } : {},
|
|
493
|
+
...typeof offset === "number" ? { offset } : {}
|
|
494
|
+
});
|
|
495
|
+
return {
|
|
496
|
+
data: result,
|
|
497
|
+
human: result.pages.length === 0 ? `No pages for ${sourceId}` : [
|
|
498
|
+
`Showing ${result.offset + 1}-${result.offset + result.pages.length} of ${result.total} page(s) for ${sourceId}`,
|
|
499
|
+
...result.pages.map((entry) => `${entry.title} | ${entry.filePath ?? entry.url} | kind=${entry.pageKind} | chars=${entry.markdownLength}`)
|
|
500
|
+
]
|
|
501
|
+
};
|
|
502
|
+
});
|
|
503
|
+
});
|
|
504
|
+
page.command("show").argument("<source-id>").option("--snapshot <snapshot-id>", "read from a specific snapshot").option("--url <page-url>", "read a page by URL").option("--path <file-path>", "read a file-backed page by file path").action(async (sourceId, options, command) => {
|
|
505
|
+
await executeCommand(command, "page.show", async () => {
|
|
506
|
+
const result = await showPage({
|
|
507
|
+
sourceId,
|
|
508
|
+
...options.snapshot ? { snapshotId: options.snapshot } : {},
|
|
509
|
+
...options.url ? { url: options.url } : {},
|
|
510
|
+
...options.path ? { filePath: options.path } : {}
|
|
511
|
+
});
|
|
512
|
+
return {
|
|
513
|
+
data: result,
|
|
514
|
+
human: renderPageResult({
|
|
515
|
+
sourceId: result.sourceId,
|
|
516
|
+
snapshotId: result.snapshotId,
|
|
517
|
+
...result.page
|
|
518
|
+
})
|
|
519
|
+
};
|
|
520
|
+
});
|
|
521
|
+
});
|
|
406
522
|
program.command("diff").alias("changes").argument("<source-id>").option("--from <snapshot-id>", "base snapshot id").option("--to <snapshot-id>", "target snapshot id").description("Compare two snapshots for a source.").action(
|
|
407
523
|
async (sourceId, options, command) => {
|
|
408
524
|
await executeCommand(command, "diff", async () => {
|
|
@@ -521,6 +637,94 @@ embeddings.command("run").description("Process queued embedding jobs immediately
|
|
|
521
637
|
};
|
|
522
638
|
});
|
|
523
639
|
});
|
|
640
|
+
var learning = program.command("learning");
|
|
641
|
+
learning.command("save").requiredOption("--source <source-id>", "source to attach the learning to").requiredOption("--kind <discovery|negative>", "learning type").requiredOption("--intent <text>", "intent or question pattern this learning applies to").option("--snapshot <snapshot-id>", "snapshot associated with the learning").option("--page-url <page-url>", "page URL associated with the learning").option("--file-path <file-path>", "file-backed page path associated with the learning").option("--title <title>", "page title or short label").option("--note <text>", "additional note").option("--search-term <term>", "search term that worked (or failed)", (value, current) => {
|
|
642
|
+
current.push(value);
|
|
643
|
+
return current;
|
|
644
|
+
}, []).action(async (options, command) => {
|
|
645
|
+
await executeCommand(command, "learning.save", async () => {
|
|
646
|
+
if (options.kind !== "discovery" && options.kind !== "negative") {
|
|
647
|
+
throw new AiocsError(
|
|
648
|
+
AIOCS_ERROR_CODES.invalidArgument,
|
|
649
|
+
"kind must be discovery or negative"
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
const result = await saveRoutingLearning({
|
|
653
|
+
sourceId: options.source,
|
|
654
|
+
learningType: options.kind,
|
|
655
|
+
intent: options.intent,
|
|
656
|
+
...options.snapshot ? { snapshotId: options.snapshot } : {},
|
|
657
|
+
...options.pageUrl ? { pageUrl: options.pageUrl } : {},
|
|
658
|
+
...options.filePath ? { filePath: options.filePath } : {},
|
|
659
|
+
...options.title ? { title: options.title } : {},
|
|
660
|
+
...options.note ? { note: options.note } : {},
|
|
661
|
+
...options.searchTerm && options.searchTerm.length > 0 ? { searchTerms: options.searchTerm } : {}
|
|
662
|
+
});
|
|
663
|
+
return {
|
|
664
|
+
data: result,
|
|
665
|
+
human: `Saved ${result.learning.learningType} learning for ${result.learning.sourceId}`
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
learning.command("list").option("--source <source-id>", "filter by source id").option("--kind <discovery|negative>", "filter by learning type").option("--intent <text>", "filter by intent substring").option("--limit <count>", "maximum number of learnings to return").action(async (options, command) => {
|
|
670
|
+
await executeCommand(command, "learning.list", async () => {
|
|
671
|
+
const limit = parsePositiveIntegerOption(options.limit, "limit");
|
|
672
|
+
if (options.kind && options.kind !== "discovery" && options.kind !== "negative") {
|
|
673
|
+
throw new AiocsError(
|
|
674
|
+
AIOCS_ERROR_CODES.invalidArgument,
|
|
675
|
+
"kind must be discovery or negative"
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
const result = await listRoutingLearningsForQuery({
|
|
679
|
+
...options.source ? { sourceId: options.source } : {},
|
|
680
|
+
...options.kind ? { learningType: options.kind } : {},
|
|
681
|
+
...options.intent ? { intentQuery: options.intent } : {},
|
|
682
|
+
...typeof limit === "number" ? { limit } : {}
|
|
683
|
+
});
|
|
684
|
+
return {
|
|
685
|
+
data: result,
|
|
686
|
+
human: result.learnings.length === 0 ? "No learnings recorded." : result.learnings.map((entry) => `${entry.learningType} | ${entry.sourceId} | ${entry.intent} | ${entry.filePath ?? entry.pageUrl ?? "(no target)"}`)
|
|
687
|
+
};
|
|
688
|
+
});
|
|
689
|
+
});
|
|
690
|
+
program.command("retrieve").argument("<query>").option("--source <source-id>", "restrict retrieval to a source", (value, current) => {
|
|
691
|
+
current.push(value);
|
|
692
|
+
return current;
|
|
693
|
+
}, []).option("--snapshot <snapshot-id>", "retrieve from a specific snapshot").option("--all", "retrieve across all latest snapshots").option("--project <path>", "resolve retrieval scope as if running from this path").option("--path <glob>", "restrict retrieval to file paths matching a glob", (value, current) => {
|
|
694
|
+
current.push(value);
|
|
695
|
+
return current;
|
|
696
|
+
}, []).option("--language <name>", "restrict retrieval to a language", (value, current) => {
|
|
697
|
+
current.push(value);
|
|
698
|
+
return current;
|
|
699
|
+
}, []).option("--mode <mode>", "search mode: auto, lexical, hybrid, semantic").option("--limit <count>", "maximum number of search results to shortlist").option("--offset <count>", "number of search results to skip before shortlisting").option("--page-limit <count>", "maximum number of full pages to read into context").action(async (query, options, command) => {
|
|
700
|
+
await executeCommand(command, "retrieve", async () => {
|
|
701
|
+
const limit = parsePositiveIntegerOption(options.limit, "limit");
|
|
702
|
+
const offset = parsePositiveIntegerOption(options.offset, "offset");
|
|
703
|
+
const pageLimit = parsePositiveIntegerOption(options.pageLimit, "limit");
|
|
704
|
+
const mode = parseSearchModeOption(options.mode);
|
|
705
|
+
const result = await retrieveContext(query, {
|
|
706
|
+
source: options.source,
|
|
707
|
+
...options.snapshot ? { snapshot: options.snapshot } : {},
|
|
708
|
+
...typeof options.all !== "undefined" ? { all: options.all } : {},
|
|
709
|
+
...options.project ? { project: options.project } : {},
|
|
710
|
+
...options.path && options.path.length > 0 ? { path: options.path } : {},
|
|
711
|
+
...options.language && options.language.length > 0 ? { language: options.language } : {},
|
|
712
|
+
...mode ? { mode } : {},
|
|
713
|
+
...typeof limit === "number" ? { limit } : {},
|
|
714
|
+
...typeof offset === "number" ? { offset } : {},
|
|
715
|
+
...typeof pageLimit === "number" ? { pageLimit } : {}
|
|
716
|
+
});
|
|
717
|
+
return {
|
|
718
|
+
data: result,
|
|
719
|
+
human: [
|
|
720
|
+
`Retrieval for "${query}" | mode=${result.modeUsed} | sources=${result.sourceScope.join(", ") || "(none)"}`,
|
|
721
|
+
...result.sourceHints.length > 0 ? ["Source hints:", ...result.sourceHints.map((hint) => `- ${hint.sourceId} | score=${hint.score} | ${hint.context.summary ?? hint.context.purpose ?? "context"}`)] : [],
|
|
722
|
+
...result.matchedLearnings.length > 0 ? ["Matched learnings:", ...result.matchedLearnings.map((learning2) => `- ${learning2.sourceId} | ${learning2.intent} | score=${learning2.score}`)] : [],
|
|
723
|
+
...result.pages.length > 0 ? ["Full pages read:", ...result.pages.map((page2) => `${page2.sourceId} | ${page2.filePath ?? page2.url} | ${page2.title}`)] : ["No full pages selected"]
|
|
724
|
+
]
|
|
725
|
+
};
|
|
726
|
+
});
|
|
727
|
+
});
|
|
524
728
|
program.command("search").argument("<query>").option("--source <source-id>", "restrict search to a source", (value, current) => {
|
|
525
729
|
current.push(value);
|
|
526
730
|
return current;
|
package/dist/mcp-server.js
CHANGED
|
@@ -4,29 +4,37 @@ import {
|
|
|
4
4
|
AiocsError,
|
|
5
5
|
backfillEmbeddings,
|
|
6
6
|
clearEmbeddings,
|
|
7
|
+
describeSource,
|
|
7
8
|
diffSnapshotsForSource,
|
|
8
9
|
exportCatalogBackup,
|
|
9
10
|
fetchSources,
|
|
10
11
|
getDoctorReport,
|
|
11
12
|
getEmbeddingStatus,
|
|
13
|
+
getSourceContextForSource,
|
|
12
14
|
importCatalogBackup,
|
|
13
15
|
initManagedSources,
|
|
14
16
|
linkProjectSources,
|
|
17
|
+
listRoutingLearningsForQuery,
|
|
15
18
|
listSnapshotsForSource,
|
|
19
|
+
listSourcePages,
|
|
16
20
|
listSources,
|
|
17
21
|
packageDescription,
|
|
18
22
|
packageName,
|
|
19
23
|
packageVersion,
|
|
20
24
|
refreshDueSources,
|
|
25
|
+
retrieveContext,
|
|
21
26
|
runEmbeddingWorker,
|
|
22
27
|
runSourceCanaries,
|
|
28
|
+
saveRoutingLearning,
|
|
23
29
|
searchCatalog,
|
|
24
30
|
showChunk,
|
|
31
|
+
showPage,
|
|
25
32
|
toAiocsError,
|
|
26
33
|
unlinkProjectSources,
|
|
34
|
+
upsertSourceContextFromFile,
|
|
27
35
|
upsertSourceFromSpecFile,
|
|
28
36
|
verifyCoverage
|
|
29
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-2UWV3O7E.js";
|
|
30
38
|
|
|
31
39
|
// src/mcp-server.ts
|
|
32
40
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -64,6 +72,52 @@ var sourceSchema = z.object({
|
|
|
64
72
|
lastSuccessfulCanaryAt: z.string().nullable(),
|
|
65
73
|
lastCanaryStatus: z.enum(["pass", "fail"]).nullable()
|
|
66
74
|
});
|
|
75
|
+
var sourceContextSchema = z.object({
|
|
76
|
+
purpose: z.string().optional(),
|
|
77
|
+
summary: z.string().optional(),
|
|
78
|
+
topicHints: z.array(z.string()),
|
|
79
|
+
commonLocations: z.array(z.object({
|
|
80
|
+
label: z.string(),
|
|
81
|
+
url: z.string().optional(),
|
|
82
|
+
filePath: z.string().optional(),
|
|
83
|
+
note: z.string().optional()
|
|
84
|
+
})),
|
|
85
|
+
gotchas: z.array(z.string()),
|
|
86
|
+
authNotes: z.array(z.string())
|
|
87
|
+
});
|
|
88
|
+
var routingLearningSchema = z.object({
|
|
89
|
+
learningId: z.string(),
|
|
90
|
+
sourceId: z.string(),
|
|
91
|
+
snapshotId: z.string().nullable(),
|
|
92
|
+
learningType: z.enum(["discovery", "negative"]),
|
|
93
|
+
intent: z.string(),
|
|
94
|
+
pageUrl: z.string().nullable(),
|
|
95
|
+
filePath: z.string().nullable(),
|
|
96
|
+
title: z.string().nullable(),
|
|
97
|
+
note: z.string().nullable(),
|
|
98
|
+
searchTerms: z.array(z.string()),
|
|
99
|
+
createdAt: z.string(),
|
|
100
|
+
updatedAt: z.string()
|
|
101
|
+
});
|
|
102
|
+
var pageSchema = z.object({
|
|
103
|
+
url: z.string(),
|
|
104
|
+
title: z.string(),
|
|
105
|
+
markdown: z.string(),
|
|
106
|
+
pageKind: z.enum(["document", "file"]),
|
|
107
|
+
filePath: z.string().nullable(),
|
|
108
|
+
language: z.string().nullable()
|
|
109
|
+
});
|
|
110
|
+
var pageListingSchema = z.object({
|
|
111
|
+
sourceId: z.string(),
|
|
112
|
+
snapshotId: z.string(),
|
|
113
|
+
total: z.number().int().nonnegative(),
|
|
114
|
+
limit: z.number().int().nonnegative(),
|
|
115
|
+
offset: z.number().int().nonnegative(),
|
|
116
|
+
hasMore: z.boolean(),
|
|
117
|
+
pages: z.array(pageSchema.omit({ markdown: true }).extend({
|
|
118
|
+
markdownLength: z.number().int().nonnegative()
|
|
119
|
+
}))
|
|
120
|
+
});
|
|
67
121
|
var fetchResultSchema = z.object({
|
|
68
122
|
sourceId: z.string(),
|
|
69
123
|
snapshotId: z.string(),
|
|
@@ -254,10 +308,26 @@ var toolHandlers = {
|
|
|
254
308
|
}),
|
|
255
309
|
source_upsert: async (args = {}) => upsertSourceFromSpecFile(args.specFile),
|
|
256
310
|
source_list: async () => listSources(),
|
|
311
|
+
source_describe: async (args = {}) => describeSource(args.sourceId),
|
|
312
|
+
source_context_show: async (args = {}) => getSourceContextForSource(args.sourceId),
|
|
313
|
+
source_context_upsert: async (args = {}) => upsertSourceContextFromFile(args.sourceId, args.contextFile),
|
|
257
314
|
fetch: async (args = {}) => fetchSources(args.sourceIdOrAll),
|
|
258
315
|
canary: async (args = {}) => runSourceCanaries(args.sourceIdOrAll),
|
|
259
316
|
refresh_due: async (args = {}) => refreshDueSources(args.sourceIdOrAll ?? "all"),
|
|
260
317
|
snapshot_list: async (args = {}) => listSnapshotsForSource(args.sourceId),
|
|
318
|
+
page_list: async (args = {}) => listSourcePages(args.sourceId, {
|
|
319
|
+
...typeof args.snapshotId === "string" ? { snapshot: args.snapshotId } : {},
|
|
320
|
+
...typeof args.query === "string" ? { query: args.query } : {},
|
|
321
|
+
...Array.isArray(args.pathPatterns) ? { path: args.pathPatterns } : {},
|
|
322
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
323
|
+
...typeof args.offset === "number" ? { offset: args.offset } : {}
|
|
324
|
+
}),
|
|
325
|
+
page_show: async (args = {}) => showPage({
|
|
326
|
+
sourceId: args.sourceId,
|
|
327
|
+
...typeof args.snapshotId === "string" ? { snapshotId: args.snapshotId } : {},
|
|
328
|
+
...typeof args.url === "string" ? { url: args.url } : {},
|
|
329
|
+
...typeof args.filePath === "string" ? { filePath: args.filePath } : {}
|
|
330
|
+
}),
|
|
261
331
|
diff_snapshots: async (args = {}) => diffSnapshotsForSource({
|
|
262
332
|
sourceId: args.sourceId,
|
|
263
333
|
...typeof args.fromSnapshotId === "string" ? { fromSnapshotId: args.fromSnapshotId } : {},
|
|
@@ -276,6 +346,35 @@ var toolHandlers = {
|
|
|
276
346
|
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
277
347
|
...typeof args.offset === "number" ? { offset: args.offset } : {}
|
|
278
348
|
}),
|
|
349
|
+
retrieve_context: async (args = {}) => retrieveContext(args.query, {
|
|
350
|
+
source: args.sourceIds ?? [],
|
|
351
|
+
...typeof args.snapshotId === "string" ? { snapshot: args.snapshotId } : {},
|
|
352
|
+
...typeof args.all === "boolean" ? { all: args.all } : {},
|
|
353
|
+
...typeof args.project === "string" ? { project: args.project } : {},
|
|
354
|
+
...Array.isArray(args.pathPatterns) ? { path: args.pathPatterns } : {},
|
|
355
|
+
...Array.isArray(args.languages) ? { language: args.languages } : {},
|
|
356
|
+
...typeof args.mode === "string" ? { mode: args.mode } : {},
|
|
357
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
358
|
+
...typeof args.offset === "number" ? { offset: args.offset } : {},
|
|
359
|
+
...typeof args.pageLimit === "number" ? { pageLimit: args.pageLimit } : {}
|
|
360
|
+
}),
|
|
361
|
+
learning_save: async (args = {}) => saveRoutingLearning({
|
|
362
|
+
sourceId: args.sourceId,
|
|
363
|
+
learningType: args.learningType,
|
|
364
|
+
intent: args.intent,
|
|
365
|
+
...typeof args.snapshotId === "string" ? { snapshotId: args.snapshotId } : {},
|
|
366
|
+
...typeof args.pageUrl === "string" ? { pageUrl: args.pageUrl } : {},
|
|
367
|
+
...typeof args.filePath === "string" ? { filePath: args.filePath } : {},
|
|
368
|
+
...typeof args.title === "string" ? { title: args.title } : {},
|
|
369
|
+
...typeof args.note === "string" ? { note: args.note } : {},
|
|
370
|
+
...Array.isArray(args.searchTerms) ? { searchTerms: args.searchTerms } : {}
|
|
371
|
+
}),
|
|
372
|
+
learning_list: async (args = {}) => listRoutingLearningsForQuery({
|
|
373
|
+
...typeof args.sourceId === "string" ? { sourceId: args.sourceId } : {},
|
|
374
|
+
...typeof args.learningType === "string" ? { learningType: args.learningType } : {},
|
|
375
|
+
...typeof args.intentQuery === "string" ? { intentQuery: args.intentQuery } : {},
|
|
376
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {}
|
|
377
|
+
}),
|
|
279
378
|
show: async (args = {}) => showChunk(args.chunkId),
|
|
280
379
|
embeddings_status: async () => getEmbeddingStatus(),
|
|
281
380
|
embeddings_backfill: async (args = {}) => backfillEmbeddings(args.sourceIdOrAll),
|
|
@@ -410,6 +509,66 @@ registerAiocsTool(
|
|
|
410
509
|
})
|
|
411
510
|
}
|
|
412
511
|
);
|
|
512
|
+
registerAiocsTool(
|
|
513
|
+
"source_describe",
|
|
514
|
+
{
|
|
515
|
+
title: "Source describe",
|
|
516
|
+
description: "Describe one source with latest snapshot info, curated source context, and recent routing learnings.",
|
|
517
|
+
inputSchema: z.object({
|
|
518
|
+
sourceId: z.string()
|
|
519
|
+
}),
|
|
520
|
+
outputSchema: z.object({
|
|
521
|
+
source: sourceSchema,
|
|
522
|
+
context: z.object({
|
|
523
|
+
sourceId: z.string(),
|
|
524
|
+
context: sourceContextSchema.nullable(),
|
|
525
|
+
createdAt: z.string().nullable(),
|
|
526
|
+
updatedAt: z.string().nullable()
|
|
527
|
+
}),
|
|
528
|
+
latestSnapshot: z.object({
|
|
529
|
+
snapshotId: z.string(),
|
|
530
|
+
detectedVersion: z.string().nullable(),
|
|
531
|
+
createdAt: z.string(),
|
|
532
|
+
pageCount: z.number().int().nonnegative()
|
|
533
|
+
}).nullable(),
|
|
534
|
+
recentLearnings: z.array(routingLearningSchema)
|
|
535
|
+
})
|
|
536
|
+
}
|
|
537
|
+
);
|
|
538
|
+
registerAiocsTool(
|
|
539
|
+
"source_context_show",
|
|
540
|
+
{
|
|
541
|
+
title: "Source context show",
|
|
542
|
+
description: "Show curated local source context for a source.",
|
|
543
|
+
inputSchema: z.object({
|
|
544
|
+
sourceId: z.string()
|
|
545
|
+
}),
|
|
546
|
+
outputSchema: z.object({
|
|
547
|
+
sourceId: z.string(),
|
|
548
|
+
context: sourceContextSchema.nullable(),
|
|
549
|
+
createdAt: z.string().nullable(),
|
|
550
|
+
updatedAt: z.string().nullable()
|
|
551
|
+
})
|
|
552
|
+
}
|
|
553
|
+
);
|
|
554
|
+
registerAiocsTool(
|
|
555
|
+
"source_context_upsert",
|
|
556
|
+
{
|
|
557
|
+
title: "Source context upsert",
|
|
558
|
+
description: "Load or update curated local source context from a JSON or YAML file.",
|
|
559
|
+
inputSchema: z.object({
|
|
560
|
+
sourceId: z.string(),
|
|
561
|
+
contextFile: z.string()
|
|
562
|
+
}),
|
|
563
|
+
outputSchema: z.object({
|
|
564
|
+
sourceId: z.string(),
|
|
565
|
+
context: sourceContextSchema,
|
|
566
|
+
contextFile: z.string(),
|
|
567
|
+
createdAt: z.string(),
|
|
568
|
+
updatedAt: z.string()
|
|
569
|
+
})
|
|
570
|
+
}
|
|
571
|
+
);
|
|
413
572
|
registerAiocsTool(
|
|
414
573
|
"fetch",
|
|
415
574
|
{
|
|
@@ -469,6 +628,40 @@ registerAiocsTool(
|
|
|
469
628
|
})
|
|
470
629
|
}
|
|
471
630
|
);
|
|
631
|
+
registerAiocsTool(
|
|
632
|
+
"page_list",
|
|
633
|
+
{
|
|
634
|
+
title: "Page list",
|
|
635
|
+
description: "List stored pages for a source snapshot with optional query and path filtering.",
|
|
636
|
+
inputSchema: z.object({
|
|
637
|
+
sourceId: z.string(),
|
|
638
|
+
snapshotId: z.string().optional(),
|
|
639
|
+
query: z.string().optional(),
|
|
640
|
+
pathPatterns: z.array(z.string()).optional(),
|
|
641
|
+
limit: z.number().int().positive().optional(),
|
|
642
|
+
offset: z.number().int().nonnegative().optional()
|
|
643
|
+
}),
|
|
644
|
+
outputSchema: pageListingSchema
|
|
645
|
+
}
|
|
646
|
+
);
|
|
647
|
+
registerAiocsTool(
|
|
648
|
+
"page_show",
|
|
649
|
+
{
|
|
650
|
+
title: "Page show",
|
|
651
|
+
description: "Read a full stored page by URL or file path.",
|
|
652
|
+
inputSchema: z.object({
|
|
653
|
+
sourceId: z.string(),
|
|
654
|
+
snapshotId: z.string().optional(),
|
|
655
|
+
url: z.string().optional(),
|
|
656
|
+
filePath: z.string().optional()
|
|
657
|
+
}),
|
|
658
|
+
outputSchema: z.object({
|
|
659
|
+
sourceId: z.string(),
|
|
660
|
+
snapshotId: z.string(),
|
|
661
|
+
page: pageSchema
|
|
662
|
+
})
|
|
663
|
+
}
|
|
664
|
+
);
|
|
472
665
|
registerAiocsTool(
|
|
473
666
|
"diff_snapshots",
|
|
474
667
|
{
|
|
@@ -541,6 +734,56 @@ registerAiocsTool(
|
|
|
541
734
|
})
|
|
542
735
|
}
|
|
543
736
|
);
|
|
737
|
+
registerAiocsTool(
|
|
738
|
+
"retrieve_context",
|
|
739
|
+
{
|
|
740
|
+
title: "Retrieve context",
|
|
741
|
+
description: "Run aiocs awareness, learned routing hints, search, and full-page reads to assemble grounded answer context.",
|
|
742
|
+
inputSchema: z.object({
|
|
743
|
+
query: z.string(),
|
|
744
|
+
sourceIds: z.array(z.string()).optional(),
|
|
745
|
+
snapshotId: z.string().optional(),
|
|
746
|
+
all: z.boolean().optional(),
|
|
747
|
+
project: z.string().optional(),
|
|
748
|
+
pathPatterns: z.array(z.string()).optional(),
|
|
749
|
+
languages: z.array(z.string()).optional(),
|
|
750
|
+
mode: z.enum(["auto", "lexical", "hybrid", "semantic"]).optional(),
|
|
751
|
+
limit: z.number().int().positive().optional(),
|
|
752
|
+
offset: z.number().int().nonnegative().optional(),
|
|
753
|
+
pageLimit: z.number().int().positive().optional()
|
|
754
|
+
}),
|
|
755
|
+
outputSchema: z.object({
|
|
756
|
+
query: z.string(),
|
|
757
|
+
modeRequested: z.enum(["auto", "lexical", "hybrid", "semantic"]),
|
|
758
|
+
modeUsed: z.enum(["lexical", "hybrid", "semantic"]),
|
|
759
|
+
sourceScope: z.array(z.string()),
|
|
760
|
+
sourceHints: z.array(z.object({
|
|
761
|
+
sourceId: z.string(),
|
|
762
|
+
score: z.number(),
|
|
763
|
+
context: sourceContextSchema,
|
|
764
|
+
matchedCommonLocations: z.array(z.object({
|
|
765
|
+
label: z.string(),
|
|
766
|
+
url: z.string().optional(),
|
|
767
|
+
filePath: z.string().optional(),
|
|
768
|
+
note: z.string().optional()
|
|
769
|
+
}))
|
|
770
|
+
})),
|
|
771
|
+
matchedLearnings: z.array(routingLearningSchema.extend({ score: z.number() })),
|
|
772
|
+
avoidedLearnings: z.array(routingLearningSchema.extend({ score: z.number() })),
|
|
773
|
+
search: z.object({
|
|
774
|
+
total: z.number().int().nonnegative(),
|
|
775
|
+
limit: z.number().int().positive(),
|
|
776
|
+
offset: z.number().int().nonnegative(),
|
|
777
|
+
hasMore: z.boolean(),
|
|
778
|
+
results: z.array(searchResultSchema)
|
|
779
|
+
}),
|
|
780
|
+
pages: z.array(pageSchema.extend({
|
|
781
|
+
sourceId: z.string(),
|
|
782
|
+
snapshotId: z.string()
|
|
783
|
+
}))
|
|
784
|
+
})
|
|
785
|
+
}
|
|
786
|
+
);
|
|
544
787
|
registerAiocsTool(
|
|
545
788
|
"show",
|
|
546
789
|
{
|
|
@@ -554,6 +797,43 @@ registerAiocsTool(
|
|
|
554
797
|
})
|
|
555
798
|
}
|
|
556
799
|
);
|
|
800
|
+
registerAiocsTool(
|
|
801
|
+
"learning_save",
|
|
802
|
+
{
|
|
803
|
+
title: "Learning save",
|
|
804
|
+
description: "Save a discovery or negative routing learning for future retrieval hints.",
|
|
805
|
+
inputSchema: z.object({
|
|
806
|
+
sourceId: z.string(),
|
|
807
|
+
learningType: z.enum(["discovery", "negative"]),
|
|
808
|
+
intent: z.string(),
|
|
809
|
+
snapshotId: z.string().optional(),
|
|
810
|
+
pageUrl: z.string().optional(),
|
|
811
|
+
filePath: z.string().optional(),
|
|
812
|
+
title: z.string().optional(),
|
|
813
|
+
note: z.string().optional(),
|
|
814
|
+
searchTerms: z.array(z.string()).optional()
|
|
815
|
+
}),
|
|
816
|
+
outputSchema: z.object({
|
|
817
|
+
learning: routingLearningSchema
|
|
818
|
+
})
|
|
819
|
+
}
|
|
820
|
+
);
|
|
821
|
+
registerAiocsTool(
|
|
822
|
+
"learning_list",
|
|
823
|
+
{
|
|
824
|
+
title: "Learning list",
|
|
825
|
+
description: "List saved routing learnings, optionally filtered by source, type, or intent substring.",
|
|
826
|
+
inputSchema: z.object({
|
|
827
|
+
sourceId: z.string().optional(),
|
|
828
|
+
learningType: z.enum(["discovery", "negative"]).optional(),
|
|
829
|
+
intentQuery: z.string().optional(),
|
|
830
|
+
limit: z.number().int().positive().optional()
|
|
831
|
+
}),
|
|
832
|
+
outputSchema: z.object({
|
|
833
|
+
learnings: z.array(routingLearningSchema)
|
|
834
|
+
})
|
|
835
|
+
}
|
|
836
|
+
);
|
|
557
837
|
registerAiocsTool(
|
|
558
838
|
"embeddings_status",
|
|
559
839
|
{
|