ctxr-cli 0.30.0 → 0.32.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 +31 -3
- package/dist/commands/land.d.ts.map +1 -1
- package/dist/commands/land.js +3 -18
- package/dist/commands/land.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +10 -2
- package/dist/commands/serve.js.map +1 -1
- package/dist/config/schema.d.ts +18 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +41 -9
- package/dist/config/schema.js.map +1 -1
- package/dist/core/browse/approve.d.ts +3 -0
- package/dist/core/browse/approve.d.ts.map +1 -1
- package/dist/core/browse/approve.js.map +1 -1
- package/dist/core/browse/page-url.d.ts +15 -0
- package/dist/core/browse/page-url.d.ts.map +1 -1
- package/dist/core/browse/page-url.js +8 -1
- package/dist/core/browse/page-url.js.map +1 -1
- package/dist/core/forge/credentials.d.ts +12 -1
- package/dist/core/forge/credentials.d.ts.map +1 -1
- package/dist/core/forge/credentials.js +25 -1
- package/dist/core/forge/credentials.js.map +1 -1
- package/dist/core/forge/github.d.ts +9 -0
- package/dist/core/forge/github.d.ts.map +1 -1
- package/dist/core/forge/github.js +6 -0
- package/dist/core/forge/github.js.map +1 -1
- package/dist/core/mcp/drafts.d.ts +30 -0
- package/dist/core/mcp/drafts.d.ts.map +1 -0
- package/dist/core/mcp/drafts.js +52 -0
- package/dist/core/mcp/drafts.js.map +1 -0
- package/dist/core/mcp/http.d.ts +40 -0
- package/dist/core/mcp/http.d.ts.map +1 -0
- package/dist/core/mcp/http.js +90 -0
- package/dist/core/mcp/http.js.map +1 -0
- package/dist/core/mcp/jsonrpc.d.ts +73 -0
- package/dist/core/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/core/mcp/jsonrpc.js +149 -0
- package/dist/core/mcp/jsonrpc.js.map +1 -0
- package/dist/core/mcp/members.d.ts +11 -0
- package/dist/core/mcp/members.d.ts.map +1 -0
- package/dist/core/mcp/members.js +21 -0
- package/dist/core/mcp/members.js.map +1 -0
- package/dist/core/mcp/oauth.d.ts +99 -0
- package/dist/core/mcp/oauth.d.ts.map +1 -0
- package/dist/core/mcp/oauth.js +454 -0
- package/dist/core/mcp/oauth.js.map +1 -0
- package/dist/core/mcp/pages.d.ts +3 -0
- package/dist/core/mcp/pages.d.ts.map +1 -0
- package/dist/core/mcp/pages.js +41 -0
- package/dist/core/mcp/pages.js.map +1 -0
- package/dist/core/mcp/ripgrep.d.ts +48 -0
- package/dist/core/mcp/ripgrep.d.ts.map +1 -0
- package/dist/core/mcp/ripgrep.js +98 -0
- package/dist/core/mcp/ripgrep.js.map +1 -0
- package/dist/core/mcp/rwlock.d.ts +16 -0
- package/dist/core/mcp/rwlock.d.ts.map +1 -0
- package/dist/core/mcp/rwlock.js +59 -0
- package/dist/core/mcp/rwlock.js.map +1 -0
- package/dist/core/mcp/sessions.d.ts +84 -0
- package/dist/core/mcp/sessions.d.ts.map +1 -0
- package/dist/core/mcp/sessions.js +154 -0
- package/dist/core/mcp/sessions.js.map +1 -0
- package/dist/core/mcp/surface.d.ts +42 -0
- package/dist/core/mcp/surface.d.ts.map +1 -0
- package/dist/core/mcp/surface.js +141 -0
- package/dist/core/mcp/surface.js.map +1 -0
- package/dist/core/mcp/sync.d.ts +91 -0
- package/dist/core/mcp/sync.d.ts.map +1 -0
- package/dist/core/mcp/sync.js +218 -0
- package/dist/core/mcp/sync.js.map +1 -0
- package/dist/core/mcp/tools/capture.d.ts +64 -0
- package/dist/core/mcp/tools/capture.d.ts.map +1 -0
- package/dist/core/mcp/tools/capture.js +182 -0
- package/dist/core/mcp/tools/capture.js.map +1 -0
- package/dist/core/mcp/tools/edit.d.ts +79 -0
- package/dist/core/mcp/tools/edit.d.ts.map +1 -0
- package/dist/core/mcp/tools/edit.js +212 -0
- package/dist/core/mcp/tools/edit.js.map +1 -0
- package/dist/core/mcp/tools/files.d.ts +163 -0
- package/dist/core/mcp/tools/files.d.ts.map +1 -0
- package/dist/core/mcp/tools/files.js +265 -0
- package/dist/core/mcp/tools/files.js.map +1 -0
- package/dist/core/mcp/tools/find.d.ts +82 -0
- package/dist/core/mcp/tools/find.d.ts.map +1 -0
- package/dist/core/mcp/tools/find.js +136 -0
- package/dist/core/mcp/tools/find.js.map +1 -0
- package/dist/core/mcp/tools/gather.d.ts +88 -0
- package/dist/core/mcp/tools/gather.d.ts.map +1 -0
- package/dist/core/mcp/tools/gather.js +123 -0
- package/dist/core/mcp/tools/gather.js.map +1 -0
- package/dist/core/mcp/tools/index.d.ts +21 -0
- package/dist/core/mcp/tools/index.d.ts.map +1 -0
- package/dist/core/mcp/tools/index.js +129 -0
- package/dist/core/mcp/tools/index.js.map +1 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +19 -14
- package/dist/core/skills.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/templates/mcp/Edit.md +7 -0
- package/templates/mcp/Glob.md +5 -0
- package/templates/mcp/Grep.md +10 -0
- package/templates/mcp/Read.md +7 -0
- package/templates/mcp/Write.md +7 -0
- package/templates/mcp/capture.md +9 -0
- package/templates/mcp/consent.html +40 -0
- package/templates/mcp/find.md +9 -0
- package/templates/mcp/gather.md +5 -0
- package/templates/mcp/server-instructions.md +17 -0
- package/templates/skills/{ctxr-circleback → ctxr-capture-circleback}/sweep.mjs +6 -5
- package/templates/skills/ctxr-capture-circleback.md +67 -0
- package/templates/skills/ctxr-capture.md +10 -4
- package/templates/skills/ctxr-circleback.md +0 -70
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { joinBaseUrl, noteRoute } from '../../browse/page-url.js';
|
|
4
|
+
import { catalogSectionsFor, sectionForNote } from '../../catalog/model.js';
|
|
5
|
+
import { isUnderAnyPrefix } from '../../fs/prefix.js';
|
|
6
|
+
import { listCaptures, listNotes } from '../../notes/list.js';
|
|
7
|
+
import { readCatalogGlosses } from '../../records.js';
|
|
8
|
+
import { ToolRefusal } from '../jsonrpc.js';
|
|
9
|
+
/**
|
|
10
|
+
* remote-access spec, *`find` stands in for a client's own content
|
|
11
|
+
* matching*; context-retrieval's bounded exception. Literal,
|
|
12
|
+
* case-insensitive substring matching over the notes the store's
|
|
13
|
+
* enumeration admits, in path order, with no score. Captures — inbox files
|
|
14
|
+
* on the default branch and on pending `capture/` branches — come back in
|
|
15
|
+
* `unfiled`, never among the notes (context-ingest's exception, design.md
|
|
16
|
+
* D6). With no text, the catalog as a map to pick selectors from.
|
|
17
|
+
*/
|
|
18
|
+
export const MAX_LINES_PER_HIT = 3;
|
|
19
|
+
export const MAX_LINE_CHARS = 240;
|
|
20
|
+
export const DEFAULT_MAX_MATCHES = 25;
|
|
21
|
+
export const DEFAULT_MAX_MAP_NOTES = 500;
|
|
22
|
+
export const MAX_RESULTS = 1000;
|
|
23
|
+
const MAX_TEXT_CHARS = 200;
|
|
24
|
+
/**
|
|
25
|
+
* Plain on purpose: type, description and required only. Some clients (Gemini) accept a narrow subset of JSON
|
|
26
|
+
* Schema and drop a tool whose schema uses more; every limit is enforced by `parseFindArgs` instead.
|
|
27
|
+
*/
|
|
28
|
+
export const FIND_INPUT_SCHEMA = {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {
|
|
31
|
+
text: { type: 'string', description: 'Literal text to look for, case-insensitive. Omit it to get the map of the store instead.' },
|
|
32
|
+
under: { type: 'string', description: 'Only look under this folder of the store, e.g. "projects/".' },
|
|
33
|
+
max: { type: 'integer', description: `How many notes to return (default ${DEFAULT_MAX_MATCHES} when matching, ${DEFAULT_MAX_MAP_NOTES} for the map).` },
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
export function parseFindArgs(args) {
|
|
37
|
+
const out = {};
|
|
38
|
+
if (args.text !== undefined && args.text !== null) {
|
|
39
|
+
if (typeof args.text !== 'string')
|
|
40
|
+
throw new ToolRefusal('mcp.invalid_arguments', '"text" must be a string.');
|
|
41
|
+
if (args.text.length > MAX_TEXT_CHARS)
|
|
42
|
+
throw new ToolRefusal('mcp.invalid_arguments', `"text" is at most ${MAX_TEXT_CHARS} characters.`);
|
|
43
|
+
if (args.text.trim().length > 0)
|
|
44
|
+
out.text = args.text.trim();
|
|
45
|
+
}
|
|
46
|
+
if (args.under !== undefined && args.under !== null) {
|
|
47
|
+
if (typeof args.under !== 'string')
|
|
48
|
+
throw new ToolRefusal('mcp.invalid_arguments', '"under" must be a string.');
|
|
49
|
+
const under = args.under.trim().replace(/^\.?\/+/, '');
|
|
50
|
+
if (under.length > 0)
|
|
51
|
+
out.under = under;
|
|
52
|
+
}
|
|
53
|
+
if (args.max !== undefined && args.max !== null) {
|
|
54
|
+
if (typeof args.max !== 'number' || !Number.isInteger(args.max) || args.max < 1 || args.max > MAX_RESULTS) {
|
|
55
|
+
throw new ToolRefusal('mcp.invalid_arguments', `"max" must be a whole number from 1 to ${MAX_RESULTS}.`);
|
|
56
|
+
}
|
|
57
|
+
out.max = args.max;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
function matchLines(text, needle) {
|
|
62
|
+
const lines = [];
|
|
63
|
+
let count = 0;
|
|
64
|
+
const all = text.split(/\r?\n/);
|
|
65
|
+
for (let i = 0; i < all.length; i += 1) {
|
|
66
|
+
const line = all[i];
|
|
67
|
+
if (!line.toLowerCase().includes(needle))
|
|
68
|
+
continue;
|
|
69
|
+
count += 1;
|
|
70
|
+
if (lines.length < MAX_LINES_PER_HIT) {
|
|
71
|
+
lines.push({ line: i + 1, text: line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS - 1)}…` : line });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { lines, count };
|
|
75
|
+
}
|
|
76
|
+
const byPath = (a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
77
|
+
/** `baseUrl` is `serve.base_url` from the configuration `serve` loaded: links point at the browsing surface it answers. */
|
|
78
|
+
export async function find(snapshot, args, baseUrl) {
|
|
79
|
+
const store = snapshot.store;
|
|
80
|
+
const linkFor = (notePath) => joinBaseUrl(baseUrl, noteRoute(notePath));
|
|
81
|
+
const glosses = await readCatalogGlosses(store);
|
|
82
|
+
const scope = (p) => args.under === undefined || isUnderAnyPrefix(p, [args.under]);
|
|
83
|
+
const notes = (await listNotes(store.root, store.config)).filter((n) => scope(n.path)).sort(byPath);
|
|
84
|
+
if (args.text === undefined) {
|
|
85
|
+
const max = args.max ?? DEFAULT_MAX_MAP_NOTES;
|
|
86
|
+
const sections = catalogSectionsFor(store.config);
|
|
87
|
+
const grouped = new Map(sections.map((s) => [s.id, []]));
|
|
88
|
+
let listed = 0;
|
|
89
|
+
for (const note of notes) {
|
|
90
|
+
if (listed >= max)
|
|
91
|
+
break;
|
|
92
|
+
grouped.get(sectionForNote(sections, note.path).id).push({ path: note.path, gloss: glosses.get(note.path) ?? '', url: linkFor(note.path) });
|
|
93
|
+
listed += 1;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
mode: 'map',
|
|
97
|
+
sections: [...grouped.entries()].filter(([, entries]) => entries.length > 0).map(([id, entries]) => ({ id, notes: entries })),
|
|
98
|
+
notes_omitted: notes.length - listed,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const needle = args.text.toLowerCase();
|
|
102
|
+
const max = args.max ?? DEFAULT_MAX_MATCHES;
|
|
103
|
+
// Raw file text, frontmatter included, so line numbers are the file's own — what grep would report.
|
|
104
|
+
const noteHits = [];
|
|
105
|
+
for (const note of notes) {
|
|
106
|
+
const { lines, count } = matchLines(await readFile(path.join(store.root, note.path), 'utf8'), needle);
|
|
107
|
+
if (count > 0)
|
|
108
|
+
noteHits.push({ path: note.path, gloss: glosses.get(note.path) ?? '', lines, matching_lines: count, url: linkFor(note.path) });
|
|
109
|
+
}
|
|
110
|
+
const inbox = store.config.ingest.inbox_path;
|
|
111
|
+
const unfiled = [];
|
|
112
|
+
for (const capture of (await listCaptures(store.root, store.config)).sort(byPath)) {
|
|
113
|
+
if (!isUnderAnyPrefix(capture.path, [inbox]) || !scope(capture.path))
|
|
114
|
+
continue;
|
|
115
|
+
const { lines, count } = matchLines(await readFile(path.join(store.root, capture.path), 'utf8'), needle);
|
|
116
|
+
if (count > 0)
|
|
117
|
+
unfiled.push({ path: capture.path, lines, matching_lines: count, pending_merge: false, branch: null });
|
|
118
|
+
}
|
|
119
|
+
const pending = [...snapshot.pending].sort((a, b) => byPath(a, b) || (a.branch < b.branch ? -1 : 1));
|
|
120
|
+
for (const capture of pending) {
|
|
121
|
+
if (!scope(capture.path))
|
|
122
|
+
continue;
|
|
123
|
+
const { lines, count } = matchLines(capture.text, needle);
|
|
124
|
+
if (count > 0)
|
|
125
|
+
unfiled.push({ path: capture.path, lines, matching_lines: count, pending_merge: true, branch: capture.branch });
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
mode: 'match',
|
|
129
|
+
text: args.text,
|
|
130
|
+
notes: noteHits.slice(0, max),
|
|
131
|
+
notes_omitted: Math.max(0, noteHits.length - max),
|
|
132
|
+
unfiled: unfiled.slice(0, max),
|
|
133
|
+
unfiled_omitted: Math.max(0, unfiled.length - max),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=find.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find.js","sourceRoot":"","sources":["../../../../src/core/mcp/tools/find.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type GatherOutcome, type GatherResult } from '../../retrieval/pass.js';
|
|
2
|
+
import type { Snapshot } from '../sync.js';
|
|
3
|
+
/**
|
|
4
|
+
* remote-access spec, *`gather` returns the retrieval pass with the bodies a
|
|
5
|
+
* client cannot read itself* (design.md D8). The pass runs unchanged against
|
|
6
|
+
* the view's notes and the view's own graph, and still returns no body; this
|
|
7
|
+
* attaches them afterwards, to a prefix of the pass's order, within a byte
|
|
8
|
+
* budget — so the cap never reorders anything, exactly as the pass's own cap.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DEFAULT_GATHER_MAX_BYTES = 60000;
|
|
11
|
+
export interface GatherArgs {
|
|
12
|
+
seeds?: string[];
|
|
13
|
+
sections?: string[];
|
|
14
|
+
under?: string[];
|
|
15
|
+
entities?: string[];
|
|
16
|
+
hops?: number;
|
|
17
|
+
direction?: 'in' | 'out' | 'both';
|
|
18
|
+
type?: string;
|
|
19
|
+
max_notes?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface GatheredNote extends GatherResult {
|
|
22
|
+
/** The note's text, frontmatter included; null once the byte budget is spent. */
|
|
23
|
+
body: string | null;
|
|
24
|
+
/** Set on the first note only, when it alone exceeded the budget and was cut to it. */
|
|
25
|
+
body_clipped?: true;
|
|
26
|
+
}
|
|
27
|
+
export interface GatherToolResult extends Omit<GatherOutcome, 'notes'> {
|
|
28
|
+
notes: GatheredNote[];
|
|
29
|
+
bodies: {
|
|
30
|
+
max_bytes: number;
|
|
31
|
+
returned: number;
|
|
32
|
+
omitted: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Plain on purpose (see FIND_INPUT_SCHEMA): `parseGatherArgs` enforces every limit. */
|
|
36
|
+
export declare const GATHER_INPUT_SCHEMA: {
|
|
37
|
+
readonly type: 'object';
|
|
38
|
+
readonly properties: {
|
|
39
|
+
readonly seeds: {
|
|
40
|
+
readonly type: 'array';
|
|
41
|
+
readonly items: {
|
|
42
|
+
readonly type: 'string';
|
|
43
|
+
};
|
|
44
|
+
readonly description: 'Note paths to start from, usually from find.';
|
|
45
|
+
};
|
|
46
|
+
readonly sections: {
|
|
47
|
+
readonly type: 'array';
|
|
48
|
+
readonly items: {
|
|
49
|
+
readonly type: 'string';
|
|
50
|
+
};
|
|
51
|
+
readonly description: 'Catalog section ids whose notes to start from (find with no text lists them).';
|
|
52
|
+
};
|
|
53
|
+
readonly under: {
|
|
54
|
+
readonly type: 'array';
|
|
55
|
+
readonly items: {
|
|
56
|
+
readonly type: 'string';
|
|
57
|
+
};
|
|
58
|
+
readonly description: 'Folders whose notes to start from, e.g. "projects/".';
|
|
59
|
+
};
|
|
60
|
+
readonly entities: {
|
|
61
|
+
readonly type: 'array';
|
|
62
|
+
readonly items: {
|
|
63
|
+
readonly type: 'string';
|
|
64
|
+
};
|
|
65
|
+
readonly description: 'Note paths whose backlinks to start from: every note linking to them.';
|
|
66
|
+
};
|
|
67
|
+
readonly hops: {
|
|
68
|
+
readonly type: 'integer';
|
|
69
|
+
readonly description: 'How many links to follow out from the starting notes (default 1; 0 returns only them).';
|
|
70
|
+
};
|
|
71
|
+
readonly direction: {
|
|
72
|
+
readonly type: 'string';
|
|
73
|
+
readonly enum: readonly ['in', 'out', 'both'];
|
|
74
|
+
readonly description: 'Follow links pointing out, in, or both (default both).';
|
|
75
|
+
};
|
|
76
|
+
readonly type: {
|
|
77
|
+
readonly type: 'string';
|
|
78
|
+
readonly description: 'Follow only links of this relation type.';
|
|
79
|
+
};
|
|
80
|
+
readonly max_notes: {
|
|
81
|
+
readonly type: 'integer';
|
|
82
|
+
readonly description: 'Cap on how many notes to return; the omitted count is reported.';
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
export declare function parseGatherArgs(args: Record<string, unknown>): GatherArgs;
|
|
87
|
+
export declare function gatherWithBodies(snapshot: Snapshot, args: GatherArgs, maxBytes?: number): Promise<GatherToolResult>;
|
|
88
|
+
//# sourceMappingURL=gather.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../../../../src/core/mcp/tools/gather.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEnG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;GAMG;AAEH,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,MAAM,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAa,SAAQ,YAAY;IAChD,iFAAiF;IACjF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,uFAAuF;IACvF,YAAY,CAAC,EAAE,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,aAAa,EAAE,OAAO,CAAC;IACpE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAClE;AAED,wFAAwF;AACxF,eAAO,MAAM,mBAAmB;aAC9B,IAAI,EAAE,QAAQ;aACd,UAAU;iBACR,KAAK;qBAAI,IAAI,EAAE,OAAO;qBAAE,KAAK;yBAAI,IAAI,EAAE,QAAQ;;qBAAI,WAAW,EAAE,8CAA8C;;iBAC9G,QAAQ;qBAAI,IAAI,EAAE,OAAO;qBAAE,KAAK;yBAAI,IAAI,EAAE,QAAQ;;qBAAI,WAAW,EAAE,+EAA+E;;iBAClJ,KAAK;qBAAI,IAAI,EAAE,OAAO;qBAAE,KAAK;yBAAI,IAAI,EAAE,QAAQ;;qBAAI,WAAW,EAAE,sDAAsD;;iBACtH,QAAQ;qBAAI,IAAI,EAAE,OAAO;qBAAE,KAAK;yBAAI,IAAI,EAAE,QAAQ;;qBAAI,WAAW,EAAE,uEAAuE;;iBAC1I,IAAI;qBAAI,IAAI,EAAE,SAAS;qBAAE,WAAW,EAAE,wFAAwF;;iBAC9H,SAAS;qBAAI,IAAI,EAAE,QAAQ;qBAAE,IAAI,YAAG,IAAI,EAAE,KAAK,EAAE,MAAM;qBAAG,WAAW,EAAE,wDAAwD;;iBAC/H,IAAI;qBAAI,IAAI,EAAE,QAAQ;qBAAE,WAAW,EAAE,0CAA0C;;iBAC/E,SAAS;qBAAI,IAAI,EAAE,SAAS;qBAAE,WAAW,EAAE,iEAAiE;;;CAEtG,CAAC;AAqBX,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAuBzE;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,SAA2B,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiD3I"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { isUnderAnyPrefix } from '../../fs/prefix.js';
|
|
4
|
+
import { readAdmittedGraph } from '../../graph/persist.js';
|
|
5
|
+
import { listNotes } from '../../notes/list.js';
|
|
6
|
+
import { gather as runPass } from '../../retrieval/pass.js';
|
|
7
|
+
import { ToolRefusal } from '../jsonrpc.js';
|
|
8
|
+
/**
|
|
9
|
+
* remote-access spec, *`gather` returns the retrieval pass with the bodies a
|
|
10
|
+
* client cannot read itself* (design.md D8). The pass runs unchanged against
|
|
11
|
+
* the view's notes and the view's own graph, and still returns no body; this
|
|
12
|
+
* attaches them afterwards, to a prefix of the pass's order, within a byte
|
|
13
|
+
* budget — so the cap never reorders anything, exactly as the pass's own cap.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_GATHER_MAX_BYTES = 60_000;
|
|
16
|
+
/** Plain on purpose (see FIND_INPUT_SCHEMA): `parseGatherArgs` enforces every limit. */
|
|
17
|
+
export const GATHER_INPUT_SCHEMA = {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
seeds: { type: 'array', items: { type: 'string' }, description: 'Note paths to start from, usually from find.' },
|
|
21
|
+
sections: { type: 'array', items: { type: 'string' }, description: 'Catalog section ids whose notes to start from (find with no text lists them).' },
|
|
22
|
+
under: { type: 'array', items: { type: 'string' }, description: 'Folders whose notes to start from, e.g. "projects/".' },
|
|
23
|
+
entities: { type: 'array', items: { type: 'string' }, description: 'Note paths whose backlinks to start from: every note linking to them.' },
|
|
24
|
+
hops: { type: 'integer', description: 'How many links to follow out from the starting notes (default 1; 0 returns only them).' },
|
|
25
|
+
direction: { type: 'string', enum: ['in', 'out', 'both'], description: 'Follow links pointing out, in, or both (default both).' },
|
|
26
|
+
type: { type: 'string', description: 'Follow only links of this relation type.' },
|
|
27
|
+
max_notes: { type: 'integer', description: 'Cap on how many notes to return; the omitted count is reported.' },
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
function stringList(args, key) {
|
|
31
|
+
const value = args[key];
|
|
32
|
+
if (value === undefined || value === null)
|
|
33
|
+
return undefined;
|
|
34
|
+
const list = typeof value === 'string' ? [value] : value;
|
|
35
|
+
if (!Array.isArray(list) || !list.every((v) => typeof v === 'string' && v.trim().length > 0)) {
|
|
36
|
+
throw new ToolRefusal('mcp.invalid_arguments', `"${key}" must be a list of non-empty strings.`);
|
|
37
|
+
}
|
|
38
|
+
return list.map((v) => v.trim().replace(/^\.?\/+/, ''));
|
|
39
|
+
}
|
|
40
|
+
function wholeNumber(args, key, min, max) {
|
|
41
|
+
const value = args[key];
|
|
42
|
+
if (value === undefined || value === null)
|
|
43
|
+
return undefined;
|
|
44
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < min || value > max) {
|
|
45
|
+
throw new ToolRefusal('mcp.invalid_arguments', `"${key}" must be a whole number from ${min} to ${max}.`);
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
export function parseGatherArgs(args) {
|
|
50
|
+
const out = {
|
|
51
|
+
seeds: stringList(args, 'seeds'),
|
|
52
|
+
sections: stringList(args, 'sections'),
|
|
53
|
+
under: stringList(args, 'under'),
|
|
54
|
+
entities: stringList(args, 'entities'),
|
|
55
|
+
hops: wholeNumber(args, 'hops', 0, 5),
|
|
56
|
+
max_notes: wholeNumber(args, 'max_notes', 1, 500),
|
|
57
|
+
};
|
|
58
|
+
if (args.direction !== undefined && args.direction !== null) {
|
|
59
|
+
if (args.direction !== 'in' && args.direction !== 'out' && args.direction !== 'both') {
|
|
60
|
+
throw new ToolRefusal('mcp.invalid_arguments', '"direction" is one of in, out, both.');
|
|
61
|
+
}
|
|
62
|
+
out.direction = args.direction;
|
|
63
|
+
}
|
|
64
|
+
if (args.type !== undefined && args.type !== null) {
|
|
65
|
+
if (typeof args.type !== 'string')
|
|
66
|
+
throw new ToolRefusal('mcp.invalid_arguments', '"type" must be a string.');
|
|
67
|
+
out.type = args.type;
|
|
68
|
+
}
|
|
69
|
+
if ([out.seeds, out.sections, out.under, out.entities].every((l) => l === undefined || l.length === 0)) {
|
|
70
|
+
throw new ToolRefusal('mcp.invalid_arguments', 'Name at least one starting point: seeds, sections, under or entities. Use find first to get note paths.');
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
export async function gatherWithBodies(snapshot, args, maxBytes = DEFAULT_GATHER_MAX_BYTES) {
|
|
75
|
+
const store = snapshot.store;
|
|
76
|
+
const captureRoot = store.config.ingest.capture_root;
|
|
77
|
+
for (const seed of args.seeds ?? []) {
|
|
78
|
+
if (isUnderAnyPrefix(seed, [captureRoot])) {
|
|
79
|
+
throw new ToolRefusal('mcp.capture_not_filed', `"${seed}" is a capture that has not been filed into a note yet, so it cannot start a gather; read it with Read instead.`, { path: seed });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const notes = await listNotes(store.root, store.config);
|
|
83
|
+
const graph = await readAdmittedGraph(store);
|
|
84
|
+
const pass = await runPass(store, notes, graph, {
|
|
85
|
+
seeds: args.seeds,
|
|
86
|
+
sections: args.sections,
|
|
87
|
+
under: args.under,
|
|
88
|
+
entities: args.entities,
|
|
89
|
+
hops: args.hops,
|
|
90
|
+
direction: args.direction,
|
|
91
|
+
type: args.type,
|
|
92
|
+
maxNotes: args.max_notes,
|
|
93
|
+
});
|
|
94
|
+
let spent = 0;
|
|
95
|
+
let open = true;
|
|
96
|
+
let returned = 0;
|
|
97
|
+
const withBodies = [];
|
|
98
|
+
for (const [index, note] of pass.notes.entries()) {
|
|
99
|
+
if (!open) {
|
|
100
|
+
withBodies.push({ ...note, body: null });
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const text = await readFile(path.join(store.root, note.path), 'utf8');
|
|
104
|
+
const bytes = Buffer.byteLength(text, 'utf8');
|
|
105
|
+
if (spent + bytes <= maxBytes) {
|
|
106
|
+
spent += bytes;
|
|
107
|
+
returned += 1;
|
|
108
|
+
withBodies.push({ ...note, body: text });
|
|
109
|
+
}
|
|
110
|
+
else if (index === 0) {
|
|
111
|
+
// A call never comes back with no text at all: the first note is cut to the budget and says so.
|
|
112
|
+
withBodies.push({ ...note, body: Buffer.from(text, 'utf8').subarray(0, maxBytes).toString('utf8'), body_clipped: true });
|
|
113
|
+
returned += 1;
|
|
114
|
+
open = false;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
withBodies.push({ ...note, body: null });
|
|
118
|
+
open = false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return { ...pass, notes: withBodies, bodies: { max_bytes: maxBytes, returned, omitted: pass.notes.length - returned } };
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=gather.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gather.js","sourceRoot":"","sources":["../../../../src/core/mcp/tools/gather.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ToolDefinition } from '../jsonrpc.js';
|
|
2
|
+
import type { Principal } from '../oauth.js';
|
|
3
|
+
import type { Mutex, WriteDeps } from '../sessions.js';
|
|
4
|
+
import type { McpView, SyncDeps } from '../sync.js';
|
|
5
|
+
/**
|
|
6
|
+
* The remote surface's tool set and the prose that describes it
|
|
7
|
+
* (templates/mcp/, shipped-prose-lives-in-templates). Built per request from
|
|
8
|
+
* the server's current state. Reads go through `view.read`, so each sees one
|
|
9
|
+
* commit and names it; writes go through the one mutex (design.md D9, D13).
|
|
10
|
+
*/
|
|
11
|
+
export declare function serverInstructions(storeName: string): string;
|
|
12
|
+
export interface ToolContext {
|
|
13
|
+
view: McpView;
|
|
14
|
+
syncDeps: SyncDeps;
|
|
15
|
+
write: WriteDeps;
|
|
16
|
+
mutex: Mutex;
|
|
17
|
+
/** `serve.base_url` from the loaded configuration. */
|
|
18
|
+
baseUrl: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
export declare function buildTools(ctx: ToolContext): ToolDefinition<Principal>[];
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/mcp/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAoBpD;;;;;GAKG;AAEH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAWD,wBAAgB,UAAU,CAAC,GAAG,EAAE,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,EAAE,CAuGxE"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { packagedTemplate } from '../../templates.js';
|
|
2
|
+
import { asToolRefusal, capture, CAPTURE_INPUT_SCHEMA, parseCaptureArgs } from './capture.js';
|
|
3
|
+
import { EDIT_INPUT_SCHEMA, editTool, parseEditArgs, parseWriteArgs, WRITE_INPUT_SCHEMA, writeTool } from './edit.js';
|
|
4
|
+
import { GLOB_INPUT_SCHEMA, globTool, GREP_INPUT_SCHEMA, grepTool, parseGlobArgs, parseGrepArgs, parseReadArgs, READ_INPUT_SCHEMA, readTool, renderGlob, renderGrep, renderRead, } from './files.js';
|
|
5
|
+
import { find, FIND_INPUT_SCHEMA, parseFindArgs } from './find.js';
|
|
6
|
+
import { GATHER_INPUT_SCHEMA, gatherWithBodies, parseGatherArgs } from './gather.js';
|
|
7
|
+
/**
|
|
8
|
+
* The remote surface's tool set and the prose that describes it
|
|
9
|
+
* (templates/mcp/, shipped-prose-lives-in-templates). Built per request from
|
|
10
|
+
* the server's current state. Reads go through `view.read`, so each sees one
|
|
11
|
+
* commit and names it; writes go through the one mutex (design.md D9, D13).
|
|
12
|
+
*/
|
|
13
|
+
export function serverInstructions(storeName) {
|
|
14
|
+
return packagedTemplate('mcp', 'server-instructions').replaceAll('__STORE_NAME__', storeName);
|
|
15
|
+
}
|
|
16
|
+
/** Writes surface a WriteRefusal as a refusal the client model can read. */
|
|
17
|
+
async function writing(ctx, fn) {
|
|
18
|
+
try {
|
|
19
|
+
return await ctx.mutex.run(fn);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
throw asToolRefusal(err);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function buildTools(ctx) {
|
|
26
|
+
const read = (fn) => ctx.view.read(ctx.syncDeps, fn);
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
name: 'find',
|
|
30
|
+
title: 'Find in the store',
|
|
31
|
+
description: packagedTemplate('mcp', 'find'),
|
|
32
|
+
inputSchema: FIND_INPUT_SCHEMA,
|
|
33
|
+
scope: 'read',
|
|
34
|
+
readOnly: true,
|
|
35
|
+
run: (args) => {
|
|
36
|
+
const parsed = parseFindArgs(args);
|
|
37
|
+
return read((snapshot) => find(snapshot, parsed, ctx.baseUrl));
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'gather',
|
|
42
|
+
title: 'Gather related notes',
|
|
43
|
+
description: packagedTemplate('mcp', 'gather'),
|
|
44
|
+
inputSchema: GATHER_INPUT_SCHEMA,
|
|
45
|
+
scope: 'read',
|
|
46
|
+
readOnly: true,
|
|
47
|
+
run: (args) => {
|
|
48
|
+
const parsed = parseGatherArgs(args);
|
|
49
|
+
return read((snapshot) => gatherWithBodies(snapshot, parsed));
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'Read',
|
|
54
|
+
title: 'Read a file',
|
|
55
|
+
description: packagedTemplate('mcp', 'Read'),
|
|
56
|
+
inputSchema: READ_INPUT_SCHEMA,
|
|
57
|
+
scope: 'read',
|
|
58
|
+
readOnly: true,
|
|
59
|
+
render: renderRead,
|
|
60
|
+
run: (args, principal) => {
|
|
61
|
+
const parsed = parseReadArgs(args);
|
|
62
|
+
return read((snapshot) => readTool(snapshot, ctx.write, principal.email, parsed));
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Grep',
|
|
67
|
+
title: 'Search file contents',
|
|
68
|
+
description: packagedTemplate('mcp', 'Grep'),
|
|
69
|
+
inputSchema: GREP_INPUT_SCHEMA,
|
|
70
|
+
scope: 'read',
|
|
71
|
+
readOnly: true,
|
|
72
|
+
render: renderGrep,
|
|
73
|
+
run: (args) => {
|
|
74
|
+
const parsed = parseGrepArgs(args);
|
|
75
|
+
return read((snapshot) => grepTool(snapshot, parsed));
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'Glob',
|
|
80
|
+
title: 'Find files by name',
|
|
81
|
+
description: packagedTemplate('mcp', 'Glob'),
|
|
82
|
+
inputSchema: GLOB_INPUT_SCHEMA,
|
|
83
|
+
scope: 'read',
|
|
84
|
+
readOnly: true,
|
|
85
|
+
render: renderGlob,
|
|
86
|
+
run: (args) => {
|
|
87
|
+
const parsed = parseGlobArgs(args);
|
|
88
|
+
return read((snapshot) => globTool(snapshot, parsed));
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'capture',
|
|
93
|
+
title: 'Capture into the store',
|
|
94
|
+
description: packagedTemplate('mcp', 'capture'),
|
|
95
|
+
inputSchema: CAPTURE_INPUT_SCHEMA,
|
|
96
|
+
scope: 'capture',
|
|
97
|
+
readOnly: false,
|
|
98
|
+
run: (args, principal) => {
|
|
99
|
+
const parsed = parseCaptureArgs(args);
|
|
100
|
+
return writing(ctx, () => capture({ view: ctx.view, syncDeps: ctx.syncDeps, write: ctx.write }, principal.email, parsed));
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'Edit',
|
|
105
|
+
title: 'Edit a note',
|
|
106
|
+
description: packagedTemplate('mcp', 'Edit'),
|
|
107
|
+
inputSchema: EDIT_INPUT_SCHEMA,
|
|
108
|
+
scope: 'edit',
|
|
109
|
+
readOnly: false,
|
|
110
|
+
run: (args, principal) => {
|
|
111
|
+
const parsed = parseEditArgs(args);
|
|
112
|
+
return writing(ctx, () => editTool({ view: ctx.view, syncDeps: ctx.syncDeps, write: ctx.write }, principal.email, parsed));
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'Write',
|
|
117
|
+
title: 'Create a note',
|
|
118
|
+
description: packagedTemplate('mcp', 'Write'),
|
|
119
|
+
inputSchema: WRITE_INPUT_SCHEMA,
|
|
120
|
+
scope: 'edit',
|
|
121
|
+
readOnly: false,
|
|
122
|
+
run: (args, principal) => {
|
|
123
|
+
const parsed = parseWriteArgs(args);
|
|
124
|
+
return writing(ctx, () => writeTool({ view: ctx.view, syncDeps: ctx.syncDeps, write: ctx.write }, principal.email, parsed));
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/mcp/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAsCjF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,KAAK;IACpB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uGAAuG;IACvG,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,EAAE,CAAC;IACxC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvE;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC;CAC5C;AAED,eAAO,MAAM,oBAAoB,wIACiG,CAAC;AAYnI,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,EAAE,CAE5E;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,EAAE,CAExE;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/core/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/core/skills.js
CHANGED
|
@@ -281,25 +281,30 @@ const RESEARCH = {
|
|
|
281
281
|
.split('\n'),
|
|
282
282
|
};
|
|
283
283
|
/**
|
|
284
|
-
* circleback-sweep
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
284
|
+
* circleback-sweep, revised by capture-circleback-is-retrieval: the first
|
|
285
|
+
* opt-in owned skill, and the first that names a capture source. It is the
|
|
286
|
+
* capture skill's retrieval step for Circleback — it decides which meetings
|
|
287
|
+
* this store owes and writes each as the verbatim record — and hands back to
|
|
288
|
+
* `ctxr-capture` at step 2, so there is one capture procedure. Named into the
|
|
289
|
+
* capture family (`ctxr-capture-<source>`), which `ctxr-capture` step 1
|
|
290
|
+
* delegates to without naming any source. There is no `ctxr capture` command,
|
|
291
|
+
* so the name claims none. It exists only in a store that declares a
|
|
292
|
+
* `circleback` block. Its runner drives Circleback's own CLI, which holds its
|
|
293
|
+
* own credential; nothing here reads or stores one. `settings.json` is
|
|
294
|
+
* rendered because the runner, being stdlib-only, cannot parse
|
|
295
|
+
* `contexture.yaml`.
|
|
291
296
|
*/
|
|
292
|
-
const
|
|
293
|
-
file: 'ctxr-circleback',
|
|
294
|
-
name: 'Circleback',
|
|
295
|
-
description: "
|
|
296
|
-
body: (config) => skillTemplate('ctxr-circleback')
|
|
297
|
+
const CAPTURE_CIRCLEBACK = {
|
|
298
|
+
file: 'ctxr-capture-circleback',
|
|
299
|
+
name: 'Capture from Circleback',
|
|
300
|
+
description: "Retrieve the Circleback meetings this store's tag says it owes, written into the inbox as verbatim records with their identity, then continue with ctxr-capture from step 2.",
|
|
301
|
+
body: (config) => skillTemplate('ctxr-capture-circleback')
|
|
297
302
|
.replaceAll('__SKILLS_PATH__', config.harness.skills_path.replace(/\/+$/, ''))
|
|
298
303
|
.replaceAll('__INBOX_PATH__', config.ingest.inbox_path)
|
|
299
304
|
.replaceAll('__DEFAULT_BRANCH__', config.git.default_branch)
|
|
300
305
|
.split('\n'),
|
|
301
306
|
supportingFiles: (config) => {
|
|
302
|
-
const files = new Map(skillSupportingFiles('ctxr-circleback'));
|
|
307
|
+
const files = new Map(skillSupportingFiles('ctxr-capture-circleback'));
|
|
303
308
|
files.set('settings.json', circlebackSettings(config));
|
|
304
309
|
return files;
|
|
305
310
|
},
|
|
@@ -321,7 +326,7 @@ function circlebackSettings(config) {
|
|
|
321
326
|
return `${JSON.stringify(settings, null, 2)}\n`;
|
|
322
327
|
}
|
|
323
328
|
/** Owned skills a store gets only by opting in; each carries `enabled`. */
|
|
324
|
-
export const OPTIONAL_SKILLS = [
|
|
329
|
+
export const OPTIONAL_SKILLS = [CAPTURE_CIRCLEBACK];
|
|
325
330
|
/** Every owned skill this store is shipped: the full set plus the opt-in ones its config enables. */
|
|
326
331
|
export function activeSkillSeeds(config) {
|
|
327
332
|
return [...SKILLS, ...OPTIONAL_SKILLS.filter((seed) => seed.enabled?.(config) === true)];
|