@ai-ecoverse/slicc-agent 3.27.1 → 3.28.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.
Files changed (54) hide show
  1. package/README.md +45 -3
  2. package/dist/codemode/index.js +10 -4
  3. package/dist/codemode/index.js.map +2 -2
  4. package/dist/host.js +1 -0
  5. package/dist/host.js.map +2 -2
  6. package/dist/main.js +21 -2
  7. package/dist/main.js.map +2 -2
  8. package/dist/mcp/allow.js +39 -0
  9. package/dist/mcp/allow.js.map +7 -0
  10. package/dist/mcp/catalog.js +182 -0
  11. package/dist/mcp/catalog.js.map +7 -0
  12. package/dist/mcp/config.js +201 -0
  13. package/dist/mcp/config.js.map +7 -0
  14. package/dist/mcp/connection.js +296 -0
  15. package/dist/mcp/connection.js.map +7 -0
  16. package/dist/mcp/content.js +139 -0
  17. package/dist/mcp/content.js.map +7 -0
  18. package/dist/mcp/credentials.js +45 -0
  19. package/dist/mcp/credentials.js.map +7 -0
  20. package/dist/mcp/index.js +54 -0
  21. package/dist/mcp/index.js.map +7 -0
  22. package/dist/mcp/runtime.js +209 -0
  23. package/dist/mcp/runtime.js.map +7 -0
  24. package/dist/mcp/section.js +35 -0
  25. package/dist/mcp/section.js.map +7 -0
  26. package/dist/mcp/sse.js +112 -0
  27. package/dist/mcp/sse.js.map +7 -0
  28. package/dist/mcp/tools.js +413 -0
  29. package/dist/mcp/tools.js.map +7 -0
  30. package/dist/patches.js +2 -0
  31. package/dist/patches.js.map +2 -2
  32. package/dist/roles/roles.js +10 -1
  33. package/dist/roles/roles.js.map +2 -2
  34. package/dist/scoops/index.js +2 -1
  35. package/dist/scoops/index.js.map +2 -2
  36. package/dist/scoops/service.js +21 -6
  37. package/dist/scoops/service.js.map +2 -2
  38. package/dist/types/codemode/index.d.ts +8 -3
  39. package/dist/types/host.d.ts +2 -0
  40. package/dist/types/mcp/allow.d.ts +12 -0
  41. package/dist/types/mcp/catalog.d.ts +29 -0
  42. package/dist/types/mcp/config.d.ts +35 -0
  43. package/dist/types/mcp/connection.d.ts +57 -0
  44. package/dist/types/mcp/content.d.ts +27 -0
  45. package/dist/types/mcp/credentials.d.ts +15 -0
  46. package/dist/types/mcp/index.d.ts +16 -0
  47. package/dist/types/mcp/runtime.d.ts +42 -0
  48. package/dist/types/mcp/section.d.ts +7 -0
  49. package/dist/types/mcp/sse.d.ts +16 -0
  50. package/dist/types/mcp/tools.d.ts +44 -0
  51. package/dist/types/patches.d.ts +1 -0
  52. package/dist/types/scoops/index.d.ts +1 -0
  53. package/dist/types/scoops/service.d.ts +1 -0
  54. package/package.json +5 -4
@@ -0,0 +1,413 @@
1
+ import {
2
+ renderToolSample,
3
+ toCodemodeIdentifier
4
+ } from "@earendil-works/pi-codemode";
5
+ import {
6
+ defineTool
7
+ } from "@earendil-works/pi-durable";
8
+ import { errorMessage } from "./connection.js";
9
+ import {
10
+ convertResult,
11
+ limitContent,
12
+ modelContent,
13
+ READ_MCP_RESOURCE,
14
+ scriptResult,
15
+ spiller
16
+ } from "./content.js";
17
+ import { scrub } from "./credentials.js";
18
+ const LIST_MCP_RESOURCES = "list_mcp_resources";
19
+ const LIST_MCP_RESOURCE_TEMPLATES = "list_mcp_resource_templates";
20
+ function parametersOf(schema) {
21
+ const { $schema: _schema, ...rest } = schema;
22
+ return {
23
+ ...rest,
24
+ type: rest.type ?? "object",
25
+ ...rest.properties === void 0 ? { properties: {} } : {}
26
+ };
27
+ }
28
+ function resultSchema(structured) {
29
+ return {
30
+ type: "object",
31
+ properties: {
32
+ content: { type: "array", items: { type: "object" } },
33
+ ...structured ? { structuredContent: structured } : {},
34
+ isError: { type: "boolean" }
35
+ },
36
+ required: ["content"]
37
+ };
38
+ }
39
+ function describe(entry) {
40
+ const title = entry.tool.title ?? entry.tool.annotations?.title;
41
+ return entry.tool.description?.trim() || title || `MCP tool ${entry.tool.name} from server ${entry.server}`;
42
+ }
43
+ function signalOf(context) {
44
+ return context.abortSignal;
45
+ }
46
+ function apiSaver(api, prefix, context) {
47
+ let counter = 0;
48
+ return spiller(
49
+ async (path, data, using) => (await api.env?.writeFile(path, data, using))?.ok === true,
50
+ () => `${api.callId}-${prefix}${++counter}`,
51
+ context
52
+ );
53
+ }
54
+ function progressText(progress) {
55
+ const total = progress.total === void 0 ? "" : `/${progress.total}`;
56
+ return progress.message ?? `Progress ${progress.progress}${total}`;
57
+ }
58
+ function failure(entry, error) {
59
+ const message = error instanceof Error ? error.message : String(error);
60
+ throw new Error(scrub(message, entry.connection.secrets));
61
+ }
62
+ function directTool(entry, readable) {
63
+ return defineTool({
64
+ name: entry.name,
65
+ description: describe(entry),
66
+ parameters: parametersOf(entry.tool.inputSchema),
67
+ replay: "unsafe",
68
+ async execute(args, api, context) {
69
+ const save = apiSaver(api, "", context);
70
+ const options = {
71
+ timeoutMs: entry.connection.timeoutMs,
72
+ onProgress: (progress) => api.output(`${progressText(progress)}
73
+ `)
74
+ };
75
+ const signal = signalOf(context);
76
+ if (signal) options.signal = signal;
77
+ const result = await entry.connection.callTool(entry.tool.name, args, options).catch((error) => failure(entry, error));
78
+ const converted = await convertResult(
79
+ entry.server,
80
+ entry.tool.name,
81
+ result,
82
+ save,
83
+ readable()
84
+ );
85
+ const details = {
86
+ server: entry.server,
87
+ tool: entry.tool.name,
88
+ ...converted.fullOutputPath ? { fullOutputPath: converted.fullOutputPath } : {}
89
+ };
90
+ return {
91
+ content: converted.content,
92
+ details,
93
+ ...converted.isError ? { isError: true } : {}
94
+ };
95
+ }
96
+ });
97
+ }
98
+ function scriptTool(entry, signal) {
99
+ const inputSchema = parametersOf(entry.tool.inputSchema);
100
+ const outputSchema = resultSchema(entry.tool.outputSchema);
101
+ return {
102
+ name: entry.name,
103
+ description: describe(entry),
104
+ inputSchema,
105
+ outputSchema,
106
+ async execute(args, { signal: own }) {
107
+ const combined = signal ? AbortSignal.any([own, signal]) : own;
108
+ const result = await entry.connection.callTool(entry.tool.name, args ?? {}, {
109
+ signal: combined,
110
+ timeoutMs: entry.connection.timeoutMs
111
+ }).catch((error) => failure(entry, error));
112
+ return scriptResult(result);
113
+ }
114
+ };
115
+ }
116
+ function stringArgument(params, key) {
117
+ const value = params?.[key];
118
+ if (value === void 0 || value === null) return void 0;
119
+ if (typeof value !== "string") throw new Error(`${key} must be a string`);
120
+ return value.trim() || void 0;
121
+ }
122
+ function listed(server, item) {
123
+ const { _meta, icons: _icons, ...rest } = item;
124
+ return { server, ...rest };
125
+ }
126
+ const stringProperty = (description) => ({ type: "string", description });
127
+ const LIST_PARAMETERS = {
128
+ type: "object",
129
+ properties: {
130
+ server: stringProperty("MCP server name. Omit to list every server with resources."),
131
+ cursor: stringProperty(
132
+ "Opaque cursor from a previous call with the same server; omit for the first page."
133
+ )
134
+ },
135
+ additionalProperties: false
136
+ };
137
+ const READ_PARAMETERS = {
138
+ type: "object",
139
+ properties: {
140
+ server: stringProperty(
141
+ "MCP server name exactly as configured. Must match the 'server' field returned by list_mcp_resources."
142
+ ),
143
+ uri: stringProperty(
144
+ "Resource URI to read. Must be one of the URIs returned by list_mcp_resources."
145
+ )
146
+ },
147
+ required: ["server", "uri"],
148
+ additionalProperties: false
149
+ };
150
+ const DESCRIPTIONS = {
151
+ [LIST_MCP_RESOURCES]: "Lists resources provided by MCP servers. Resources allow servers to share data that provides context to language models, such as files, database schemas, or application-specific information. Prefer resources over web search when possible.",
152
+ [LIST_MCP_RESOURCE_TEMPLATES]: "Lists resource templates provided by MCP servers. Parameterized resource templates allow servers to share data that takes parameters and provides context to language models, such as files, database schemas, or application-specific information. Prefer resource templates over web search when possible.",
153
+ [READ_MCP_RESOURCE]: "Read a specific resource from an MCP server given the server name and resource URI."
154
+ };
155
+ function find(servers, name) {
156
+ const server = servers.find((candidate) => candidate.name === name);
157
+ if (server) return server;
158
+ const available = servers.map((candidate) => candidate.name).join(", ");
159
+ throw new Error(
160
+ `MCP server "${name}" has no resources${available ? `. Servers with resources: ${available}` : ""}`
161
+ );
162
+ }
163
+ async function listing(servers, params, signal, key) {
164
+ const serverName = stringArgument(params, "server");
165
+ const cursor = stringArgument(params, "cursor");
166
+ const visible = (item) => {
167
+ const { uri, uriTemplate, mimeType } = item;
168
+ const target = uri ?? uriTemplate ?? "";
169
+ return !(target.startsWith("ui://") || /;\s*profile\s*=\s*"?mcp-app"?/i.test(mimeType ?? ""));
170
+ };
171
+ const options = (server) => ({
172
+ timeoutMs: server.connection.timeoutMs,
173
+ ...signal ? { signal } : {}
174
+ });
175
+ if (serverName) {
176
+ const server = find(servers, serverName);
177
+ const page = key === "resources" ? await server.connection.resourcesPage(cursor, options(server)).then((result) => ({
178
+ items: result.resources,
179
+ nextCursor: result.nextCursor
180
+ })) : await server.connection.resourceTemplatesPage(cursor, options(server)).then((result) => ({
181
+ items: result.resourceTemplates,
182
+ nextCursor: result.nextCursor
183
+ }));
184
+ return {
185
+ server: server.name,
186
+ [key]: page.items.filter(visible).map((item) => listed(server.name, item)),
187
+ ...page.nextCursor === void 0 ? {} : { nextCursor: page.nextCursor }
188
+ };
189
+ }
190
+ if (cursor) throw new Error("cursor can only be used when a server is specified");
191
+ const sorted = [...servers].sort((a, b) => a.name.localeCompare(b.name));
192
+ const results = await Promise.allSettled(
193
+ sorted.map(
194
+ (server) => key === "resources" ? server.connection.allResources(options(server)) : server.connection.allResourceTemplates(options(server))
195
+ )
196
+ );
197
+ const items = [];
198
+ const errors = [];
199
+ results.forEach((result, index) => {
200
+ const server = sorted[index].name;
201
+ if (result.status === "fulfilled")
202
+ items.push(...result.value.filter(visible).map((item) => listed(server, item)));
203
+ else
204
+ errors.push({
205
+ server,
206
+ error: errorMessage(result.reason)
207
+ });
208
+ });
209
+ return { [key]: items, ...errors.length ? { errors } : {} };
210
+ }
211
+ async function reading(servers, params, signal, save) {
212
+ const serverName = stringArgument(params, "server");
213
+ const uri = stringArgument(params, "uri");
214
+ if (!serverName) throw new Error("server must be provided");
215
+ if (!uri) throw new Error("uri must be provided");
216
+ const server = find(servers, serverName);
217
+ const result = await server.connection.readResource(uri, {
218
+ timeoutMs: server.connection.timeoutMs,
219
+ ...signal ? { signal } : {}
220
+ });
221
+ const blocks = result.contents.flatMap((contents2) => [
222
+ ...result.contents.length > 1 ? [{ type: "text", text: `${contents2.uri}:` }] : [],
223
+ { type: "resource", resource: contents2 }
224
+ ]);
225
+ const converted = await modelContent(server.name, blocks, save);
226
+ const limited = await limitContent(
227
+ converted.length ? converted : [{ type: "text", text: `Resource ${uri} is empty.` }],
228
+ save
229
+ );
230
+ const contents = result.contents.map((item) => {
231
+ const { _meta: _ignored, ...rest } = item;
232
+ return rest;
233
+ });
234
+ return { ...limited, payload: { server: server.name, uri, contents } };
235
+ }
236
+ function resourceTools(servers) {
237
+ const listTool = (name, key) => defineTool({
238
+ name,
239
+ description: DESCRIPTIONS[name],
240
+ parameters: LIST_PARAMETERS,
241
+ replay: "safe",
242
+ async execute(args, api, context) {
243
+ const payload = await listing(await servers(api, context), args, signalOf(context), key);
244
+ const limited = await limitContent(
245
+ [{ type: "text", text: JSON.stringify(payload) }],
246
+ apiSaver(api, "", context)
247
+ );
248
+ return { content: limited.content };
249
+ }
250
+ });
251
+ return [
252
+ listTool(LIST_MCP_RESOURCES, "resources"),
253
+ listTool(LIST_MCP_RESOURCE_TEMPLATES, "resourceTemplates"),
254
+ defineTool({
255
+ name: READ_MCP_RESOURCE,
256
+ description: DESCRIPTIONS[READ_MCP_RESOURCE],
257
+ parameters: READ_PARAMETERS,
258
+ replay: "safe",
259
+ async execute(args, api, context) {
260
+ const read = await reading(
261
+ await servers(api, context),
262
+ args,
263
+ signalOf(context),
264
+ apiSaver(api, "", context)
265
+ );
266
+ return { content: read.content };
267
+ }
268
+ })
269
+ ];
270
+ }
271
+ function resourceScriptTools(servers, signal, save) {
272
+ const combine = (own) => signal ? AbortSignal.any([own, signal]) : own;
273
+ return [
274
+ {
275
+ name: LIST_MCP_RESOURCES,
276
+ description: DESCRIPTIONS[LIST_MCP_RESOURCES],
277
+ inputSchema: LIST_PARAMETERS,
278
+ execute: (args, { signal: own }) => listing(servers(), args, combine(own), "resources")
279
+ },
280
+ {
281
+ name: LIST_MCP_RESOURCE_TEMPLATES,
282
+ description: DESCRIPTIONS[LIST_MCP_RESOURCE_TEMPLATES],
283
+ inputSchema: LIST_PARAMETERS,
284
+ execute: (args, { signal: own }) => listing(servers(), args, combine(own), "resourceTemplates")
285
+ },
286
+ {
287
+ name: READ_MCP_RESOURCE,
288
+ description: DESCRIPTIONS[READ_MCP_RESOURCE],
289
+ inputSchema: READ_PARAMETERS,
290
+ execute: async (args, { signal: own }) => (await reading(servers(), args, combine(own), save)).payload
291
+ }
292
+ ];
293
+ }
294
+ function isNamespaceName(namespace, query) {
295
+ const id = toCodemodeIdentifier(namespace);
296
+ const queryId = toCodemodeIdentifier(query);
297
+ const suffix = (name) => name.slice(name.lastIndexOf("__") + 2);
298
+ return namespace === query || id === queryId || suffix(namespace) === query || suffix(id) === queryId;
299
+ }
300
+ function words(text) {
301
+ return text.toLowerCase().split(/[^a-z0-9]+/).filter((word) => word.length > 1);
302
+ }
303
+ function rank(query, documents, limit) {
304
+ const terms = words(query);
305
+ if (!terms.length) return [];
306
+ const tokenized = documents.map((doc) => ({ name: doc.name, words: words(doc.text) }));
307
+ const frequency = /* @__PURE__ */ new Map();
308
+ for (const doc of tokenized)
309
+ for (const term of new Set(doc.words)) frequency.set(term, (frequency.get(term) ?? 0) + 1);
310
+ const total = tokenized.length;
311
+ const scored = tokenized.map((doc) => {
312
+ let score = 0;
313
+ for (const term of terms) {
314
+ const count = doc.words.filter((word) => word === term || word.startsWith(term)).length;
315
+ if (!count) continue;
316
+ const df = frequency.get(term) ?? 0;
317
+ const idf = Math.log(1 + (total - df + 0.5) / (df + 0.5));
318
+ score += idf * (count * 2.2 / (count + 1.2 * (0.25 + 0.75 * doc.words.length / 20)));
319
+ }
320
+ return { name: doc.name, score };
321
+ });
322
+ return scored.filter((doc) => doc.score > 0).sort((a, b) => b.score - a.score || a.name.localeCompare(b.name)).slice(0, limit).map((doc) => doc.name);
323
+ }
324
+ const DEFAULT_SEARCH_LIMIT = 8;
325
+ function discoveryGlobals(tools, namespaceOf) {
326
+ const samples = new Map(tools.map((tool) => [tool.name, renderToolSample(tool)]));
327
+ const entry = (name) => ({
328
+ name: toCodemodeIdentifier(name),
329
+ description: samples.get(name)
330
+ });
331
+ return [
332
+ {
333
+ name: "searchTools",
334
+ spread: true,
335
+ execute: (args) => {
336
+ const [query, options] = args;
337
+ if (typeof query !== "string") throw new Error("searchTools() expects a query string");
338
+ const limit = options?.limit ?? DEFAULT_SEARCH_LIMIT;
339
+ if (typeof limit !== "number" || !Number.isInteger(limit) || limit <= 0)
340
+ throw new Error("searchTools() limit must be a positive integer");
341
+ const namespace = options?.namespace;
342
+ if (namespace !== void 0 && namespace !== null && typeof namespace !== "string")
343
+ throw new Error("searchTools() namespace must be a string");
344
+ const documents = tools.flatMap((tool) => {
345
+ const space = namespaceOf(tool.name);
346
+ if (namespace && (!space || !isNamespaceName(space.name, namespace))) return [];
347
+ return [
348
+ {
349
+ name: tool.name,
350
+ text: [
351
+ tool.name.replace(/_/g, " "),
352
+ tool.description,
353
+ space?.description ?? ""
354
+ ].join(" ")
355
+ }
356
+ ];
357
+ });
358
+ return rank(query, documents, limit).map(entry);
359
+ }
360
+ },
361
+ {
362
+ name: "describeTool",
363
+ spread: true,
364
+ execute: (args) => {
365
+ const [name] = args;
366
+ if (typeof name !== "string") throw new Error("describeTool() expects a tool name");
367
+ const tool = tools.find(
368
+ (candidate) => candidate.name === name || toCodemodeIdentifier(candidate.name) === name
369
+ );
370
+ return tool ? samples.get(tool.name) : void 0;
371
+ }
372
+ },
373
+ {
374
+ name: "describeNamespace",
375
+ spread: true,
376
+ execute: (args) => {
377
+ const [name] = args;
378
+ if (typeof name !== "string")
379
+ throw new Error("describeNamespace() expects a namespace name");
380
+ let found;
381
+ const names = [];
382
+ for (const tool of tools) {
383
+ const space = namespaceOf(tool.name);
384
+ if (!space || !isNamespaceName(space.name, name)) continue;
385
+ found ??= space;
386
+ names.push(toCodemodeIdentifier(tool.name));
387
+ }
388
+ if (!found) return void 0;
389
+ return {
390
+ name: found.name,
391
+ ...found.description ? { description: found.description } : {},
392
+ ...found.instructions ? { instructions: found.instructions } : {},
393
+ tools: names
394
+ };
395
+ }
396
+ }
397
+ ];
398
+ }
399
+ export {
400
+ DEFAULT_SEARCH_LIMIT,
401
+ LIST_MCP_RESOURCES,
402
+ LIST_MCP_RESOURCE_TEMPLATES,
403
+ READ_MCP_RESOURCE,
404
+ apiSaver,
405
+ directTool,
406
+ discoveryGlobals,
407
+ rank,
408
+ resourceScriptTools,
409
+ resourceTools,
410
+ resultSchema,
411
+ scriptTool
412
+ };
413
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/mcp/tools.ts"],
4
+ "sourcesContent": ["import type { Context, JsonValue } from '@earendil-works/chord';\nimport {\n type CodemodeJsonSchema,\n type CodemodeTool,\n renderToolSample,\n toCodemodeIdentifier,\n} from '@earendil-works/pi-codemode';\nimport {\n defineTool,\n type ToolExecutionApi,\n type ToolRegistration,\n} from '@earendil-works/pi-durable';\nimport type { McpRequestOptions, Tool as McpTool } from '@earendil-works/pi-mcp';\nimport type { McpExposure } from './config.ts';\nimport { errorMessage, type McpServerConnection } from './connection.ts';\nimport {\n type Content,\n convertResult,\n limitContent,\n modelContent,\n READ_MCP_RESOURCE,\n type Saver,\n scriptResult,\n spiller,\n} from './content.ts';\nimport { scrub } from './credentials.ts';\n\nexport const LIST_MCP_RESOURCES = 'list_mcp_resources';\nexport const LIST_MCP_RESOURCE_TEMPLATES = 'list_mcp_resource_templates';\nexport { READ_MCP_RESOURCE };\n\nexport interface McpToolEntry {\n server: string;\n name: string;\n exposure: McpExposure;\n tool: McpTool;\n connection: McpServerConnection;\n}\n\nexport type McpDetails = { server: string; tool: string; fullOutputPath?: string };\n\nfunction parametersOf(schema: Record<string, unknown>): Record<string, unknown> {\n const { $schema: _schema, ...rest } = schema;\n return {\n ...rest,\n type: rest.type ?? 'object',\n ...(rest.properties === undefined ? { properties: {} } : {}),\n };\n}\n\nexport function resultSchema(structured: Record<string, unknown> | undefined): CodemodeJsonSchema {\n return {\n type: 'object',\n properties: {\n content: { type: 'array', items: { type: 'object' } },\n ...(structured ? { structuredContent: structured } : {}),\n isError: { type: 'boolean' },\n },\n required: ['content'],\n };\n}\n\nfunction describe(entry: McpToolEntry): string {\n const title = entry.tool.title ?? entry.tool.annotations?.title;\n return (\n entry.tool.description?.trim() ||\n title ||\n `MCP tool ${entry.tool.name} from server ${entry.server}`\n );\n}\n\nfunction signalOf(context: Context): AbortSignal | undefined {\n return context.abortSignal as AbortSignal | undefined;\n}\n\nexport function apiSaver(api: ToolExecutionApi, prefix: string, context: Context): Saver {\n let counter = 0;\n return spiller(\n async (path, data, using) => (await api.env?.writeFile(path, data, using))?.ok === true,\n () => `${api.callId}-${prefix}${++counter}`,\n context\n );\n}\n\nfunction progressText(progress: { progress: number; total?: number; message?: string }): string {\n const total = progress.total === undefined ? '' : `/${progress.total}`;\n return progress.message ?? `Progress ${progress.progress}${total}`;\n}\n\nfunction failure(entry: { connection: McpServerConnection }, error: unknown): never {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(scrub(message, entry.connection.secrets));\n}\n\nexport function directTool(entry: McpToolEntry, readable: () => boolean): ToolRegistration {\n return defineTool({\n name: entry.name,\n description: describe(entry),\n parameters: parametersOf(entry.tool.inputSchema) as never,\n replay: 'unsafe',\n async execute(args, api, context) {\n const save = apiSaver(api, '', context);\n const options: McpRequestOptions = {\n timeoutMs: entry.connection.timeoutMs,\n onProgress: (progress) => api.output(`${progressText(progress)}\\n`),\n };\n const signal = signalOf(context);\n if (signal) options.signal = signal;\n const result = await entry.connection\n .callTool(entry.tool.name, args as Record<string, unknown>, options)\n .catch((error) => failure(entry, error));\n const converted = await convertResult(\n entry.server,\n entry.tool.name,\n result,\n save,\n readable()\n );\n const details: McpDetails = {\n server: entry.server,\n tool: entry.tool.name,\n ...(converted.fullOutputPath ? { fullOutputPath: converted.fullOutputPath } : {}),\n };\n return {\n content: converted.content,\n details: details as JsonValue,\n ...(converted.isError ? { isError: true } : {}),\n };\n },\n }) as ToolRegistration;\n}\n\nexport function scriptTool(entry: McpToolEntry, signal: AbortSignal | undefined): CodemodeTool {\n const inputSchema = parametersOf(entry.tool.inputSchema);\n const outputSchema = resultSchema(entry.tool.outputSchema as Record<string, unknown> | undefined);\n return {\n name: entry.name,\n description: describe(entry),\n inputSchema,\n outputSchema,\n async execute(args, { signal: own }) {\n const combined = signal ? AbortSignal.any([own, signal]) : own;\n const result = await entry.connection\n .callTool(entry.tool.name, (args ?? {}) as Record<string, unknown>, {\n signal: combined,\n timeoutMs: entry.connection.timeoutMs,\n })\n .catch((error) => failure(entry, error));\n return scriptResult(result);\n },\n };\n}\n\nexport interface ResourceServer {\n name: string;\n connection: McpServerConnection;\n}\n\nfunction stringArgument(params: unknown, key: string): string | undefined {\n const value = (params as Record<string, unknown> | undefined)?.[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') throw new Error(`${key} must be a string`);\n return value.trim() || undefined;\n}\n\nfunction listed(server: string, item: object): Record<string, unknown> {\n const { _meta, icons: _icons, ...rest } = item as Record<string, unknown>;\n return { server, ...rest };\n}\n\nconst stringProperty = (description: string) => ({ type: 'string', description });\nconst LIST_PARAMETERS = {\n type: 'object',\n properties: {\n server: stringProperty('MCP server name. Omit to list every server with resources.'),\n cursor: stringProperty(\n 'Opaque cursor from a previous call with the same server; omit for the first page.'\n ),\n },\n additionalProperties: false,\n};\nconst READ_PARAMETERS = {\n type: 'object',\n properties: {\n server: stringProperty(\n \"MCP server name exactly as configured. Must match the 'server' field returned by list_mcp_resources.\"\n ),\n uri: stringProperty(\n 'Resource URI to read. Must be one of the URIs returned by list_mcp_resources.'\n ),\n },\n required: ['server', 'uri'],\n additionalProperties: false,\n};\n\nconst DESCRIPTIONS: Record<string, string> = {\n [LIST_MCP_RESOURCES]:\n 'Lists resources provided by MCP servers. Resources allow servers to share data that provides context to language models, such as files, database schemas, or application-specific information. Prefer resources over web search when possible.',\n [LIST_MCP_RESOURCE_TEMPLATES]:\n 'Lists resource templates provided by MCP servers. Parameterized resource templates allow servers to share data that takes parameters and provides context to language models, such as files, database schemas, or application-specific information. Prefer resource templates over web search when possible.',\n [READ_MCP_RESOURCE]:\n 'Read a specific resource from an MCP server given the server name and resource URI.',\n};\n\ntype Key = 'resources' | 'resourceTemplates';\n\nfunction find(servers: readonly ResourceServer[], name: string): ResourceServer {\n const server = servers.find((candidate) => candidate.name === name);\n if (server) return server;\n const available = servers.map((candidate) => candidate.name).join(', ');\n throw new Error(\n `MCP server \"${name}\" has no resources${available ? `. Servers with resources: ${available}` : ''}`\n );\n}\n\nasync function listing(\n servers: readonly ResourceServer[],\n params: unknown,\n signal: AbortSignal | undefined,\n key: Key\n): Promise<Record<string, unknown>> {\n const serverName = stringArgument(params, 'server');\n const cursor = stringArgument(params, 'cursor');\n const visible = (item: object) => {\n const { uri, uriTemplate, mimeType } = item as Record<string, string | undefined>;\n const target = uri ?? uriTemplate ?? '';\n return !(target.startsWith('ui://') || /;\\s*profile\\s*=\\s*\"?mcp-app\"?/i.test(mimeType ?? ''));\n };\n const options = (server: ResourceServer): McpRequestOptions => ({\n timeoutMs: server.connection.timeoutMs,\n ...(signal ? { signal } : {}),\n });\n if (serverName) {\n const server = find(servers, serverName);\n const page =\n key === 'resources'\n ? await server.connection.resourcesPage(cursor, options(server)).then((result) => ({\n items: result.resources as object[],\n nextCursor: result.nextCursor,\n }))\n : await server.connection.resourceTemplatesPage(cursor, options(server)).then((result) => ({\n items: result.resourceTemplates as object[],\n nextCursor: result.nextCursor,\n }));\n return {\n server: server.name,\n [key]: page.items.filter(visible).map((item) => listed(server.name, item)),\n ...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),\n };\n }\n if (cursor) throw new Error('cursor can only be used when a server is specified');\n const sorted = [...servers].sort((a, b) => a.name.localeCompare(b.name));\n const results = await Promise.allSettled(\n sorted.map((server) =>\n key === 'resources'\n ? server.connection.allResources(options(server))\n : server.connection.allResourceTemplates(options(server))\n )\n );\n const items: Record<string, unknown>[] = [];\n const errors: { server: string; error: string }[] = [];\n results.forEach((result, index) => {\n const server = (sorted[index] as ResourceServer).name;\n if (result.status === 'fulfilled')\n items.push(...(result.value as object[]).filter(visible).map((item) => listed(server, item)));\n else\n errors.push({\n server,\n error: errorMessage(result.reason),\n });\n });\n return { [key]: items, ...(errors.length ? { errors } : {}) };\n}\n\nasync function reading(\n servers: readonly ResourceServer[],\n params: unknown,\n signal: AbortSignal | undefined,\n save: Saver\n): Promise<{ content: Content[]; payload: Record<string, unknown>; fullOutputPath?: string }> {\n const serverName = stringArgument(params, 'server');\n const uri = stringArgument(params, 'uri');\n if (!serverName) throw new Error('server must be provided');\n if (!uri) throw new Error('uri must be provided');\n const server = find(servers, serverName);\n const result = await server.connection.readResource(uri, {\n timeoutMs: server.connection.timeoutMs,\n ...(signal ? { signal } : {}),\n });\n const blocks = result.contents.flatMap((contents) => [\n ...(result.contents.length > 1 ? [{ type: 'text' as const, text: `${contents.uri}:` }] : []),\n { type: 'resource' as const, resource: contents },\n ]);\n const converted = await modelContent(server.name, blocks, save);\n const limited = await limitContent(\n converted.length ? converted : [{ type: 'text', text: `Resource ${uri} is empty.` }],\n save\n );\n const contents = result.contents.map((item) => {\n const { _meta: _ignored, ...rest } = item as typeof item & { _meta?: unknown };\n return rest;\n });\n return { ...limited, payload: { server: server.name, uri, contents } };\n}\n\nexport type ServersFor = (\n api: ToolExecutionApi,\n context: Context\n) => Promise<readonly ResourceServer[]>;\n\nexport function resourceTools(servers: ServersFor): ToolRegistration[] {\n const listTool = (name: string, key: Key) =>\n defineTool({\n name,\n description: DESCRIPTIONS[name] as string,\n parameters: LIST_PARAMETERS as never,\n replay: 'safe',\n async execute(args, api, context) {\n const payload = await listing(await servers(api, context), args, signalOf(context), key);\n const limited = await limitContent(\n [{ type: 'text', text: JSON.stringify(payload) }],\n apiSaver(api, '', context)\n );\n return { content: limited.content };\n },\n }) as ToolRegistration;\n return [\n listTool(LIST_MCP_RESOURCES, 'resources'),\n listTool(LIST_MCP_RESOURCE_TEMPLATES, 'resourceTemplates'),\n defineTool({\n name: READ_MCP_RESOURCE,\n description: DESCRIPTIONS[READ_MCP_RESOURCE] as string,\n parameters: READ_PARAMETERS as never,\n replay: 'safe',\n async execute(args, api, context) {\n const read = await reading(\n await servers(api, context),\n args,\n signalOf(context),\n apiSaver(api, '', context)\n );\n return { content: read.content };\n },\n }) as ToolRegistration,\n ];\n}\n\nexport function resourceScriptTools(\n servers: () => readonly ResourceServer[],\n signal: AbortSignal | undefined,\n save: Saver\n): CodemodeTool[] {\n const combine = (own: AbortSignal) => (signal ? AbortSignal.any([own, signal]) : own);\n return [\n {\n name: LIST_MCP_RESOURCES,\n description: DESCRIPTIONS[LIST_MCP_RESOURCES] as string,\n inputSchema: LIST_PARAMETERS,\n execute: (args, { signal: own }) => listing(servers(), args, combine(own), 'resources'),\n },\n {\n name: LIST_MCP_RESOURCE_TEMPLATES,\n description: DESCRIPTIONS[LIST_MCP_RESOURCE_TEMPLATES] as string,\n inputSchema: LIST_PARAMETERS,\n execute: (args, { signal: own }) =>\n listing(servers(), args, combine(own), 'resourceTemplates'),\n },\n {\n name: READ_MCP_RESOURCE,\n description: DESCRIPTIONS[READ_MCP_RESOURCE] as string,\n inputSchema: READ_PARAMETERS,\n execute: async (args, { signal: own }) =>\n (await reading(servers(), args, combine(own), save)).payload,\n },\n ];\n}\n\nexport interface Namespace {\n name: string;\n description?: string;\n instructions?: string;\n}\n\nfunction isNamespaceName(namespace: string, query: string): boolean {\n const id = toCodemodeIdentifier(namespace);\n const queryId = toCodemodeIdentifier(query);\n const suffix = (name: string) => name.slice(name.lastIndexOf('__') + 2);\n return (\n namespace === query || id === queryId || suffix(namespace) === query || suffix(id) === queryId\n );\n}\n\nfunction words(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((word) => word.length > 1);\n}\n\nexport function rank(\n query: string,\n documents: readonly { name: string; text: string }[],\n limit: number\n): string[] {\n const terms = words(query);\n if (!terms.length) return [];\n const tokenized = documents.map((doc) => ({ name: doc.name, words: words(doc.text) }));\n const frequency = new Map<string, number>();\n for (const doc of tokenized)\n for (const term of new Set(doc.words)) frequency.set(term, (frequency.get(term) ?? 0) + 1);\n const total = tokenized.length;\n const scored = tokenized.map((doc) => {\n let score = 0;\n for (const term of terms) {\n const count = doc.words.filter((word) => word === term || word.startsWith(term)).length;\n if (!count) continue;\n const df = frequency.get(term) ?? 0;\n const idf = Math.log(1 + (total - df + 0.5) / (df + 0.5));\n score += idf * ((count * 2.2) / (count + 1.2 * (0.25 + (0.75 * doc.words.length) / 20)));\n }\n return { name: doc.name, score };\n });\n return scored\n .filter((doc) => doc.score > 0)\n .sort((a, b) => b.score - a.score || a.name.localeCompare(b.name))\n .slice(0, limit)\n .map((doc) => doc.name);\n}\n\nexport const DEFAULT_SEARCH_LIMIT = 8;\n\nexport function discoveryGlobals(\n tools: readonly CodemodeTool[],\n namespaceOf: (tool: string) => Namespace | undefined\n): CodemodeTool[] {\n const samples = new Map(tools.map((tool) => [tool.name, renderToolSample(tool)]));\n const entry = (name: string) => ({\n name: toCodemodeIdentifier(name),\n description: samples.get(name) as string,\n });\n return [\n {\n name: 'searchTools',\n spread: true,\n execute: (args) => {\n const [query, options] = args as [\n unknown,\n { limit?: unknown; namespace?: unknown } | undefined,\n ];\n if (typeof query !== 'string') throw new Error('searchTools() expects a query string');\n const limit = options?.limit ?? DEFAULT_SEARCH_LIMIT;\n if (typeof limit !== 'number' || !Number.isInteger(limit) || limit <= 0)\n throw new Error('searchTools() limit must be a positive integer');\n const namespace = options?.namespace;\n if (namespace !== undefined && namespace !== null && typeof namespace !== 'string')\n throw new Error('searchTools() namespace must be a string');\n const documents = tools.flatMap((tool) => {\n const space = namespaceOf(tool.name);\n if (namespace && (!space || !isNamespaceName(space.name, namespace))) return [];\n return [\n {\n name: tool.name,\n text: [\n tool.name.replace(/_/g, ' '),\n tool.description as string,\n space?.description ?? '',\n ].join(' '),\n },\n ];\n });\n return rank(query, documents, limit).map(entry);\n },\n },\n {\n name: 'describeTool',\n spread: true,\n execute: (args) => {\n const [name] = args as unknown[];\n if (typeof name !== 'string') throw new Error('describeTool() expects a tool name');\n const tool = tools.find(\n (candidate) => candidate.name === name || toCodemodeIdentifier(candidate.name) === name\n );\n return tool ? samples.get(tool.name) : undefined;\n },\n },\n {\n name: 'describeNamespace',\n spread: true,\n execute: (args) => {\n const [name] = args as unknown[];\n if (typeof name !== 'string')\n throw new Error('describeNamespace() expects a namespace name');\n let found: Namespace | undefined;\n const names: string[] = [];\n for (const tool of tools) {\n const space = namespaceOf(tool.name);\n if (!space || !isNamespaceName(space.name, name)) continue;\n found ??= space;\n names.push(toCodemodeIdentifier(tool.name));\n }\n if (!found) return undefined;\n return {\n name: found.name,\n ...(found.description ? { description: found.description } : {}),\n ...(found.instructions ? { instructions: found.instructions } : {}),\n tools: names,\n };\n },\n },\n ];\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["contents"]
7
+ }
package/dist/patches.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Server } from "@earendil-works/pi-server";
2
2
  import { withUnrefTimers } from "./wire.js";
3
3
  const applied = /* @__PURE__ */ Symbol.for("slicc.agent.patches");
4
+ const MCP_SSE_PATCH = "pi-mcp-sse-buffer";
4
5
  function patchServerAccept(target) {
5
6
  if (target[applied]) return;
6
7
  const original = target.prototype.accept;
@@ -18,6 +19,7 @@ function applyPatches() {
18
19
  patchServerAccept(Server);
19
20
  }
20
21
  export {
22
+ MCP_SSE_PATCH,
21
23
  applyPatches,
22
24
  patchServerAccept
23
25
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/patches.ts"],
4
- "sourcesContent": ["import { Server } from '@earendil-works/pi-server';\nimport { withUnrefTimers } from './wire.ts';\n\nconst applied = Symbol.for('slicc.agent.patches');\n\ninterface Patchable {\n prototype: { accept: (...args: unknown[]) => unknown };\n [applied]?: true;\n}\n\nexport function patchServerAccept(target: Patchable): void {\n if (target[applied]) return;\n const original = target.prototype.accept;\n if (typeof original !== 'function' || !String(original).includes('handshakeTimeout.unref()')) {\n throw new Error(\n 'pi-server-handshake-unref: Server.prototype.accept no longer calls handshakeTimeout.unref(); revisit patches.json'\n );\n }\n target.prototype.accept = function accept(this: unknown, ...args: unknown[]) {\n return withUnrefTimers(() => original.apply(this, args));\n };\n target[applied] = true;\n}\n\nexport function applyPatches(): void {\n patchServerAccept(Server as unknown as Patchable);\n}\n"],
5
- "mappings": "AAAA,SAAS,cAAc;AACvB,SAAS,uBAAuB;AAEhC,MAAM,UAAU,uBAAO,IAAI,qBAAqB;AAOzC,SAAS,kBAAkB,QAAyB;AACzD,MAAI,OAAO,OAAO,EAAG;AACrB,QAAM,WAAW,OAAO,UAAU;AAClC,MAAI,OAAO,aAAa,cAAc,CAAC,OAAO,QAAQ,EAAE,SAAS,0BAA0B,GAAG;AAC5F,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU,SAAS,SAAS,UAAyB,MAAiB;AAC3E,WAAO,gBAAgB,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC;AAAA,EACzD;AACA,SAAO,OAAO,IAAI;AACpB;AAEO,SAAS,eAAqB;AACnC,oBAAkB,MAA8B;AAClD;",
4
+ "sourcesContent": ["import { Server } from '@earendil-works/pi-server';\nimport { withUnrefTimers } from './wire.ts';\n\nconst applied = Symbol.for('slicc.agent.patches');\n\nexport const MCP_SSE_PATCH = 'pi-mcp-sse-buffer';\n\ninterface Patchable {\n prototype: { accept: (...args: unknown[]) => unknown };\n [applied]?: true;\n}\n\nexport function patchServerAccept(target: Patchable): void {\n if (target[applied]) return;\n const original = target.prototype.accept;\n if (typeof original !== 'function' || !String(original).includes('handshakeTimeout.unref()')) {\n throw new Error(\n 'pi-server-handshake-unref: Server.prototype.accept no longer calls handshakeTimeout.unref(); revisit patches.json'\n );\n }\n target.prototype.accept = function accept(this: unknown, ...args: unknown[]) {\n return withUnrefTimers(() => original.apply(this, args));\n };\n target[applied] = true;\n}\n\nexport function applyPatches(): void {\n patchServerAccept(Server as unknown as Patchable);\n}\n"],
5
+ "mappings": "AAAA,SAAS,cAAc;AACvB,SAAS,uBAAuB;AAEhC,MAAM,UAAU,uBAAO,IAAI,qBAAqB;AAEzC,MAAM,gBAAgB;AAOtB,SAAS,kBAAkB,QAAyB;AACzD,MAAI,OAAO,OAAO,EAAG;AACrB,QAAM,WAAW,OAAO,UAAU;AAClC,MAAI,OAAO,aAAa,cAAc,CAAC,OAAO,QAAQ,EAAE,SAAS,0BAA0B,GAAG;AAC5F,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU,SAAS,SAAS,UAAyB,MAAiB;AAC3E,WAAO,gBAAgB,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC;AAAA,EACzD;AACA,SAAO,OAAO,IAAI;AACpB;AAEO,SAAS,eAAqB;AACnC,oBAAkB,MAA8B;AAClD;",
6
6
  "names": []
7
7
  }
@@ -11,6 +11,15 @@ const TOOLS = {
11
11
  memory_write: "memory_write"
12
12
  };
13
13
  const WRITERS = /* @__PURE__ */ new Set(["write", "edit", "bash"]);
14
+ const PASSED = /* @__PURE__ */ new Set([
15
+ "codemode",
16
+ "list_mcp_resources",
17
+ "list_mcp_resource_templates",
18
+ "read_mcp_resource"
19
+ ]);
20
+ function passThrough(name) {
21
+ return PASSED.has(name) || /^mcp__[A-Za-z0-9_*]+$/.test(name);
22
+ }
14
23
  const THINKING = /* @__PURE__ */ new Set(["off", "minimal", "low", "medium", "high", "xhigh"]);
15
24
  const APPLIED = /* @__PURE__ */ new Set([
16
25
  "name",
@@ -39,7 +48,7 @@ function list(value) {
39
48
  function tools(names, where, warnings) {
40
49
  const mapped = [];
41
50
  for (const name of names) {
42
- const tool = TOOLS[name];
51
+ const tool = TOOLS[name] ?? (passThrough(name) ? name : void 0);
43
52
  if (tool) {
44
53
  if (!mapped.includes(tool)) mapped.push(tool);
45
54
  } else warnings.push(`${where}: tool "${name}" isn't available in SLICC; it's left out`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/roles/roles.ts"],
4
- "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { RoleMemory } from '../memory/store.ts';\nimport { type FrontmatterValue, parseFrontmatter } from './frontmatter.ts';\n\nexport type RoleSource = 'builtin' | 'package' | 'user' | 'project';\nexport type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\nexport interface Role {\n name: string;\n description: string;\n prompt: string;\n mode: 'replace' | 'append';\n tools?: string[];\n model?: string;\n thinking?: Thinking;\n aliases: string[];\n output?: string;\n memory?: RoleMemory;\n context?: { project: boolean; global: boolean };\n source: RoleSource;\n path: string;\n}\n\nexport interface Roles {\n roles: Role[];\n warnings: string[];\n limits: { maxLiveScoops: number; maxPerTurn: number };\n}\n\nexport const DEFAULT_LIMITS = { maxLiveScoops: 16, maxPerTurn: 64 };\n\nconst TOOLS: Record<string, string> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'bash',\n find: 'bash',\n ls: 'bash',\n memory_write: 'memory_write',\n};\n\nconst WRITERS = new Set(['write', 'edit', 'bash']);\n\nconst THINKING = new Set<string>(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\n\nconst APPLIED = new Set([\n 'name',\n 'description',\n 'tools',\n 'model',\n 'thinking',\n 'systemPromptMode',\n 'aliases',\n 'output',\n 'package',\n 'advertise',\n 'inheritProjectContext',\n 'inheritGlobalContext',\n 'inheritSkills',\n 'memory',\n 'skills',\n 'defaultReads',\n]);\n\nexport type RoleFiles = Pick<ExecutionEnv, 'readTextFile' | 'listDir'>;\n\nexport interface RoleSourceDir {\n source: RoleSource;\n dir: string;\n}\n\nfunction list(value: FrontmatterValue | undefined): string[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string')\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction tools(names: string[], where: string, warnings: string[]): string[] {\n const mapped: string[] = [];\n for (const name of names) {\n const tool = TOOLS[name];\n if (tool) {\n if (!mapped.includes(tool)) mapped.push(tool);\n } else warnings.push(`${where}: tool \"${name}\" isn't available in SLICC; it's left out`);\n }\n return mapped;\n}\n\nexport function roleMemory(value: FrontmatterValue): RoleMemory | undefined {\n if (typeof value !== 'string') return undefined;\n const inline = /^\\{(.*)\\}$/s.exec(value.trim());\n const pairs = new Map<string, string>();\n for (const part of (inline ? (inline[1] as string) : value).split(/[,\\n]/)) {\n const found = /^\\s*([\\w-]+)\\s*:\\s*(.*?)\\s*$/.exec(part);\n if (found) pairs.set(found[1] as string, (found[2] as string).replace(/^([\"'])(.*)\\1$/, '$2'));\n }\n const scope = pairs.get('scope');\n const path = pairs.get('path');\n if ((scope !== 'user' && scope !== 'project') || !path) return undefined;\n return { scope, path };\n}\n\nfunction withMemoryWrite(\n listed: string[] | undefined,\n memory: RoleMemory | undefined\n): string[] | undefined {\n if (memory && listed?.some((tool) => WRITERS.has(tool)) && !listed.includes('memory_write'))\n return [...listed, 'memory_write'];\n return listed;\n}\n\nfunction memoryFields(\n fields: Record<string, FrontmatterValue>,\n path: string,\n warnings: string[]\n): Pick<Role, 'memory' | 'context'> & { listed: string[] | undefined } {\n const memory = fields.memory === undefined ? undefined : roleMemory(fields.memory);\n if (fields.memory !== undefined && !memory)\n warnings.push(`${path}: memory needs a scope (user or project) and a path; ignored`);\n const listed = withMemoryWrite(\n fields.tools !== undefined ? tools(list(fields.tools), path, warnings) : undefined,\n memory\n );\n const inherits =\n fields.inheritProjectContext !== undefined || fields.inheritGlobalContext !== undefined;\n return {\n ...(memory ? { memory } : {}),\n listed,\n ...(inherits\n ? {\n context: {\n project: fields.inheritProjectContext !== false,\n global: fields.inheritGlobalContext === true,\n },\n }\n : {}),\n };\n}\n\nexport function parseRole(\n text: string,\n source: RoleSource,\n path: string,\n warnings: string[]\n): Role | undefined {\n const { fields, body, problems } = parseFrontmatter(text, ['memory']);\n for (const problem of problems) warnings.push(`${path}: ${problem}`);\n const name = fields.name;\n const description = fields.description;\n if (typeof name !== 'string' || typeof description !== 'string') {\n warnings.push(`${path}: an agent file needs a name and a description; skipped`);\n return undefined;\n }\n for (const key of Object.keys(fields))\n if (!APPLIED.has(key))\n warnings.push(`${path}: \"${key}\" isn't supported in SLICC; it's ignored`);\n const thinking =\n typeof fields.thinking === 'string' && THINKING.has(fields.thinking)\n ? (fields.thinking as Thinking)\n : undefined;\n if (fields.thinking !== undefined && !thinking)\n warnings.push(`${path}: thinking \"${String(fields.thinking)}\" is unknown; ignored`);\n const { memory, listed, context } = memoryFields(fields, path, warnings);\n const pkg = typeof fields.package === 'string' && fields.package ? `${fields.package}.` : '';\n return {\n name: `${pkg}${name}`,\n description,\n prompt: body,\n mode: fields.systemPromptMode === 'append' ? 'append' : 'replace',\n ...(listed ? { tools: listed } : {}),\n ...(typeof fields.model === 'string' ? { model: fields.model } : {}),\n ...(thinking ? { thinking } : {}),\n aliases: list(fields.aliases),\n ...(typeof fields.output === 'string' ? { output: fields.output } : {}),\n ...(memory ? { memory } : {}),\n ...(context ? { context } : {}),\n source,\n path,\n };\n}\n\nasync function markdown(\n files: RoleFiles,\n dir: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n if (dir.endsWith('.md')) return [dir];\n const listed = await files.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n const path = `${dir}/${info.name}`;\n if (info.kind === 'directory') out.push(...(await markdown(files, path, context, depth + 1)));\n else if (info.name.endsWith('.md') && !info.name.endsWith('.chain.md')) out.push(path);\n }\n return out.sort();\n}\n\ntype Override = {\n model?: unknown;\n thinking?: unknown;\n tools?: unknown;\n systemPrompt?: unknown;\n description?: unknown;\n disabled?: unknown;\n};\n\ninterface Settings {\n overrides: Record<string, Override>;\n limits: Roles['limits'];\n}\n\nfunction positive(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;\n}\n\nasync function settings(\n files: RoleFiles,\n path: string,\n context: Context,\n warnings: string[]\n): Promise<Settings> {\n const read = await files.readTextFile(path, context);\n const empty = { overrides: {}, limits: { ...DEFAULT_LIMITS } };\n if (!read.ok) return empty;\n let parsed: {\n subagents?: {\n agentOverrides?: Record<string, Override>;\n maxLiveScoops?: unknown;\n maxPerTurn?: unknown;\n };\n };\n try {\n parsed = JSON.parse(read.value);\n } catch (error) {\n warnings.push(`${path}: not valid JSON (${(error as Error).message}); overrides ignored`);\n return empty;\n }\n const subagents = parsed.subagents ?? {};\n return {\n overrides: subagents.agentOverrides ?? {},\n limits: {\n maxLiveScoops: positive(subagents.maxLiveScoops, DEFAULT_LIMITS.maxLiveScoops),\n maxPerTurn: positive(subagents.maxPerTurn, DEFAULT_LIMITS.maxPerTurn),\n },\n };\n}\n\nfunction apply(role: Role, override: Override | undefined, warnings: string[]): Role | undefined {\n if (!override) return role;\n if (override.disabled === true) return undefined;\n const next: Role = { ...role };\n if (typeof override.model === 'string') next.model = override.model;\n if (typeof override.thinking === 'string' && THINKING.has(override.thinking))\n next.thinking = override.thinking as Thinking;\n if (typeof override.description === 'string') next.description = override.description;\n if (typeof override.systemPrompt === 'string') next.prompt = override.systemPrompt;\n if (Array.isArray(override.tools))\n next.tools = withMemoryWrite(\n tools(override.tools.map(String), `override for ${role.name}`, warnings),\n role.memory\n );\n return next;\n}\n\nexport interface LoadOptions {\n files: RoleFiles;\n builtin: () => Promise<{ path: string; text: string }[]>;\n dirs: RoleSourceDir[];\n settingsPath: string;\n}\n\nconst ORDER: RoleSource[] = ['builtin', 'package', 'user', 'project'];\n\nexport async function loadRoles(options: LoadOptions, context: Context): Promise<Roles> {\n const warnings: string[] = [];\n const byName = new Map<string, Role>();\n const add = (role: Role | undefined) => {\n if (role) byName.set(role.name, role);\n };\n for (const { path, text } of await options.builtin())\n add(parseRole(text, 'builtin', path, warnings));\n const dirs = [...options.dirs].sort((a, b) => ORDER.indexOf(a.source) - ORDER.indexOf(b.source));\n for (const { source, dir } of dirs)\n for (const path of await markdown(options.files, dir, context)) {\n const read = await options.files.readTextFile(path, context);\n if (read.ok) add(parseRole(read.value, source, path, warnings));\n }\n const { overrides, limits } = await settings(\n options.files,\n options.settingsPath,\n context,\n warnings\n );\n const roles: Role[] = [];\n for (const role of byName.values()) {\n const applied = apply(role, overrides[role.name], warnings);\n if (applied) roles.push(applied);\n }\n return { roles, warnings, limits };\n}\n\nexport function findRole(roles: readonly Role[], name: string): Role | undefined {\n return (\n roles.find((role) => role.name === name) ?? roles.find((role) => role.aliases.includes(name))\n );\n}\n\nexport async function manifestDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const top = await files.listDir(root, context);\n if (!top.ok) return [];\n const out: string[] = [];\n for (const entry of top.value) {\n if (entry.kind !== 'directory' || entry.name.startsWith('.')) continue;\n if (!entry.name.startsWith('@')) {\n out.push(`${root}/${entry.name}`);\n continue;\n }\n const scoped = await files.listDir(`${root}/${entry.name}`, context);\n if (scoped.ok)\n for (const inner of scoped.value)\n if (inner.kind === 'directory') out.push(`${root}/${entry.name}/${inner.name}`);\n }\n return out;\n}\n\ntype Manifest = {\n 'pi-subagents'?: { agents?: unknown };\n pi?: { subagents?: { agents?: unknown } };\n};\n\nexport function agentPaths(dir: string, text: string): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const agents = manifest['pi-subagents']?.agents ?? manifest.pi?.subagents?.agents;\n const listed = Array.isArray(agents) ? agents : typeof agents === 'string' ? [agents] : [];\n return listed\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nexport async function packageDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const out: string[] = [];\n for (const dir of await manifestDirs(files, root, context)) {\n const read = await files.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...agentPaths(dir, read.value));\n }\n return out;\n}\n"],
5
- "mappings": "AAGA,SAAgC,wBAAwB;AA2BjD,MAAM,iBAAiB,EAAE,eAAe,IAAI,YAAY,GAAG;AAElE,MAAM,QAAgC;AAAA,EACpC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,IAAI;AAAA,EACJ,cAAc;AAChB;AAEA,MAAM,UAAU,oBAAI,IAAI,CAAC,SAAS,QAAQ,MAAM,CAAC;AAEjD,MAAM,WAAW,oBAAI,IAAY,CAAC,OAAO,WAAW,OAAO,UAAU,QAAQ,OAAO,CAAC;AAErF,MAAM,UAAU,oBAAI,IAAI;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASD,SAAS,KAAK,OAA+C;AAC3D,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,MAAI,OAAO,UAAU;AACnB,WAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC,EACzB,OAAO,OAAO;AACnB,SAAO,CAAC;AACV;AAEA,SAAS,MAAM,OAAiB,OAAe,UAA8B;AAC3E,QAAM,SAAmB,CAAC;AAC1B,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,MAAM;AACR,UAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO,KAAK,IAAI;AAAA,IAC9C,MAAO,UAAS,KAAK,GAAG,KAAK,WAAW,IAAI,2CAA2C;AAAA,EACzF;AACA,SAAO;AACT;AAEO,SAAS,WAAW,OAAiD;AAC1E,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,SAAS,cAAc,KAAK,MAAM,KAAK,CAAC;AAC9C,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,SAAS,SAAU,OAAO,CAAC,IAAe,OAAO,MAAM,OAAO,GAAG;AAC1E,UAAM,QAAQ,+BAA+B,KAAK,IAAI;AACtD,QAAI,MAAO,OAAM,IAAI,MAAM,CAAC,GAAc,MAAM,CAAC,EAAa,QAAQ,kBAAkB,IAAI,CAAC;AAAA,EAC/F;AACA,QAAM,QAAQ,MAAM,IAAI,OAAO;AAC/B,QAAM,OAAO,MAAM,IAAI,MAAM;AAC7B,MAAK,UAAU,UAAU,UAAU,aAAc,CAAC,KAAM,QAAO;AAC/D,SAAO,EAAE,OAAO,KAAK;AACvB;AAEA,SAAS,gBACP,QACA,QACsB;AACtB,MAAI,UAAU,QAAQ,KAAK,CAAC,SAAS,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,SAAS,cAAc;AACxF,WAAO,CAAC,GAAG,QAAQ,cAAc;AACnC,SAAO;AACT;AAEA,SAAS,aACP,QACA,MACA,UACqE;AACrE,QAAM,SAAS,OAAO,WAAW,SAAY,SAAY,WAAW,OAAO,MAAM;AACjF,MAAI,OAAO,WAAW,UAAa,CAAC;AAClC,aAAS,KAAK,GAAG,IAAI,8DAA8D;AACrF,QAAM,SAAS;AAAA,IACb,OAAO,UAAU,SAAY,MAAM,KAAK,OAAO,KAAK,GAAG,MAAM,QAAQ,IAAI;AAAA,IACzE;AAAA,EACF;AACA,QAAM,WACJ,OAAO,0BAA0B,UAAa,OAAO,yBAAyB;AAChF,SAAO;AAAA,IACL,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA,GAAI,WACA;AAAA,MACE,SAAS;AAAA,QACP,SAAS,OAAO,0BAA0B;AAAA,QAC1C,QAAQ,OAAO,yBAAyB;AAAA,MAC1C;AAAA,IACF,IACA,CAAC;AAAA,EACP;AACF;AAEO,SAAS,UACd,MACA,QACA,MACA,UACkB;AAClB,QAAM,EAAE,QAAQ,MAAM,SAAS,IAAI,iBAAiB,MAAM,CAAC,QAAQ,CAAC;AACpE,aAAW,WAAW,SAAU,UAAS,KAAK,GAAG,IAAI,KAAK,OAAO,EAAE;AACnE,QAAM,OAAO,OAAO;AACpB,QAAM,cAAc,OAAO;AAC3B,MAAI,OAAO,SAAS,YAAY,OAAO,gBAAgB,UAAU;AAC/D,aAAS,KAAK,GAAG,IAAI,yDAAyD;AAC9E,WAAO;AAAA,EACT;AACA,aAAW,OAAO,OAAO,KAAK,MAAM;AAClC,QAAI,CAAC,QAAQ,IAAI,GAAG;AAClB,eAAS,KAAK,GAAG,IAAI,MAAM,GAAG,0CAA0C;AAC5E,QAAM,WACJ,OAAO,OAAO,aAAa,YAAY,SAAS,IAAI,OAAO,QAAQ,IAC9D,OAAO,WACR;AACN,MAAI,OAAO,aAAa,UAAa,CAAC;AACpC,aAAS,KAAK,GAAG,IAAI,eAAe,OAAO,OAAO,QAAQ,CAAC,uBAAuB;AACpF,QAAM,EAAE,QAAQ,QAAQ,QAAQ,IAAI,aAAa,QAAQ,MAAM,QAAQ;AACvE,QAAM,MAAM,OAAO,OAAO,YAAY,YAAY,OAAO,UAAU,GAAG,OAAO,OAAO,MAAM;AAC1F,SAAO;AAAA,IACL,MAAM,GAAG,GAAG,GAAG,IAAI;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,OAAO,qBAAqB,WAAW,WAAW;AAAA,IACxD,GAAI,SAAS,EAAE,OAAO,OAAO,IAAI,CAAC;AAAA,IAClC,GAAI,OAAO,OAAO,UAAU,WAAW,EAAE,OAAO,OAAO,MAAM,IAAI,CAAC;AAAA,IAClE,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,SAAS,KAAK,OAAO,OAAO;AAAA,IAC5B,GAAI,OAAO,OAAO,WAAW,WAAW,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,IACrE,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,SACb,OACA,KACA,SACA,QAAQ,GACW;AACnB,MAAI,IAAI,SAAS,KAAK,EAAG,QAAO,CAAC,GAAG;AACpC,QAAM,SAAS,MAAM,MAAM,QAAQ,KAAK,OAAO;AAC/C,MAAI,CAAC,OAAO,MAAM,QAAQ,EAAG,QAAO,CAAC;AACrC,QAAM,MAAgB,CAAC;AACvB,aAAW,QAAQ,OAAO,OAAO;AAC/B,UAAM,OAAO,GAAG,GAAG,IAAI,KAAK,IAAI;AAChC,QAAI,KAAK,SAAS,YAAa,KAAI,KAAK,GAAI,MAAM,SAAS,OAAO,MAAM,SAAS,QAAQ,CAAC,CAAE;AAAA,aACnF,KAAK,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,KAAK,SAAS,WAAW,EAAG,KAAI,KAAK,IAAI;AAAA,EACvF;AACA,SAAO,IAAI,KAAK;AAClB;AAgBA,SAAS,SAAS,OAAgB,UAA0B;AAC1D,SAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI,QAAQ;AACrF;AAEA,eAAe,SACb,OACA,MACA,SACA,UACmB;AACnB,QAAM,OAAO,MAAM,MAAM,aAAa,MAAM,OAAO;AACnD,QAAM,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,EAAE,GAAG,eAAe,EAAE;AAC7D,MAAI,CAAC,KAAK,GAAI,QAAO;AACrB,MAAI;AAOJ,MAAI;AACF,aAAS,KAAK,MAAM,KAAK,KAAK;AAAA,EAChC,SAAS,OAAO;AACd,aAAS,KAAK,GAAG,IAAI,qBAAsB,MAAgB,OAAO,sBAAsB;AACxF,WAAO;AAAA,EACT;AACA,QAAM,YAAY,OAAO,aAAa,CAAC;AACvC,SAAO;AAAA,IACL,WAAW,UAAU,kBAAkB,CAAC;AAAA,IACxC,QAAQ;AAAA,MACN,eAAe,SAAS,UAAU,eAAe,eAAe,aAAa;AAAA,MAC7E,YAAY,SAAS,UAAU,YAAY,eAAe,UAAU;AAAA,IACtE;AAAA,EACF;AACF;AAEA,SAAS,MAAM,MAAY,UAAgC,UAAsC;AAC/F,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,aAAa,KAAM,QAAO;AACvC,QAAM,OAAa,EAAE,GAAG,KAAK;AAC7B,MAAI,OAAO,SAAS,UAAU,SAAU,MAAK,QAAQ,SAAS;AAC9D,MAAI,OAAO,SAAS,aAAa,YAAY,SAAS,IAAI,SAAS,QAAQ;AACzE,SAAK,WAAW,SAAS;AAC3B,MAAI,OAAO,SAAS,gBAAgB,SAAU,MAAK,cAAc,SAAS;AAC1E,MAAI,OAAO,SAAS,iBAAiB,SAAU,MAAK,SAAS,SAAS;AACtE,MAAI,MAAM,QAAQ,SAAS,KAAK;AAC9B,SAAK,QAAQ;AAAA,MACX,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,gBAAgB,KAAK,IAAI,IAAI,QAAQ;AAAA,MACvE,KAAK;AAAA,IACP;AACF,SAAO;AACT;AASA,MAAM,QAAsB,CAAC,WAAW,WAAW,QAAQ,SAAS;AAEpE,eAAsB,UAAU,SAAsB,SAAkC;AACtF,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAAS,oBAAI,IAAkB;AACrC,QAAM,MAAM,CAAC,SAA2B;AACtC,QAAI,KAAM,QAAO,IAAI,KAAK,MAAM,IAAI;AAAA,EACtC;AACA,aAAW,EAAE,MAAM,KAAK,KAAK,MAAM,QAAQ,QAAQ;AACjD,QAAI,UAAU,MAAM,WAAW,MAAM,QAAQ,CAAC;AAChD,QAAM,OAAO,CAAC,GAAG,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,MAAM,QAAQ,EAAE,MAAM,IAAI,MAAM,QAAQ,EAAE,MAAM,CAAC;AAC/F,aAAW,EAAE,QAAQ,IAAI,KAAK;AAC5B,eAAW,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK,OAAO,GAAG;AAC9D,YAAM,OAAO,MAAM,QAAQ,MAAM,aAAa,MAAM,OAAO;AAC3D,UAAI,KAAK,GAAI,KAAI,UAAU,KAAK,OAAO,QAAQ,MAAM,QAAQ,CAAC;AAAA,IAChE;AACF,QAAM,EAAE,WAAW,OAAO,IAAI,MAAM;AAAA,IAClC,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAgB,CAAC;AACvB,aAAW,QAAQ,OAAO,OAAO,GAAG;AAClC,UAAM,UAAU,MAAM,MAAM,UAAU,KAAK,IAAI,GAAG,QAAQ;AAC1D,QAAI,QAAS,OAAM,KAAK,OAAO;AAAA,EACjC;AACA,SAAO,EAAE,OAAO,UAAU,OAAO;AACnC;AAEO,SAAS,SAAS,OAAwB,MAAgC;AAC/E,SACE,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,SAAS,IAAI,CAAC;AAEhG;AAEA,eAAsB,aACpB,OACA,MACA,SACmB;AACnB,QAAM,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO;AAC7C,MAAI,CAAC,IAAI,GAAI,QAAO,CAAC;AACrB,QAAM,MAAgB,CAAC;AACvB,aAAW,SAAS,IAAI,OAAO;AAC7B,QAAI,MAAM,SAAS,eAAe,MAAM,KAAK,WAAW,GAAG,EAAG;AAC9D,QAAI,CAAC,MAAM,KAAK,WAAW,GAAG,GAAG;AAC/B,UAAI,KAAK,GAAG,IAAI,IAAI,MAAM,IAAI,EAAE;AAChC;AAAA,IACF;AACA,UAAM,SAAS,MAAM,MAAM,QAAQ,GAAG,IAAI,IAAI,MAAM,IAAI,IAAI,OAAO;AACnE,QAAI,OAAO;AACT,iBAAW,SAAS,OAAO;AACzB,YAAI,MAAM,SAAS,YAAa,KAAI,KAAK,GAAG,IAAI,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,EAAE;AAAA;AAAA,EACpF;AACA,SAAO;AACT;AAOO,SAAS,WAAW,KAAa,MAAwB;AAC9D,MAAI;AACJ,MAAI;AACF,eAAW,KAAK,MAAM,IAAI;AAAA,EAC5B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAS,SAAS,cAAc,GAAG,UAAU,SAAS,IAAI,WAAW;AAC3E,QAAM,SAAS,MAAM,QAAQ,MAAM,IAAI,SAAS,OAAO,WAAW,WAAW,CAAC,MAAM,IAAI,CAAC;AACzF,SAAO,OACJ,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,EACzD,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,KAAK,QAAQ,SAAS,EAAE,EAAE,QAAQ,OAAO,EAAE,CAAC,EAAE;AAC3E;AAEA,eAAsB,YACpB,OACA,MACA,SACmB;AACnB,QAAM,MAAgB,CAAC;AACvB,aAAW,OAAO,MAAM,aAAa,OAAO,MAAM,OAAO,GAAG;AAC1D,UAAM,OAAO,MAAM,MAAM,aAAa,GAAG,GAAG,iBAAiB,OAAO;AACpE,QAAI,KAAK,GAAI,KAAI,KAAK,GAAG,WAAW,KAAK,KAAK,KAAK,CAAC;AAAA,EACtD;AACA,SAAO;AACT;",
4
+ "sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport type { RoleMemory } from '../memory/store.ts';\nimport { type FrontmatterValue, parseFrontmatter } from './frontmatter.ts';\n\nexport type RoleSource = 'builtin' | 'package' | 'user' | 'project';\nexport type Thinking = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';\n\nexport interface Role {\n name: string;\n description: string;\n prompt: string;\n mode: 'replace' | 'append';\n tools?: string[];\n model?: string;\n thinking?: Thinking;\n aliases: string[];\n output?: string;\n memory?: RoleMemory;\n context?: { project: boolean; global: boolean };\n source: RoleSource;\n path: string;\n}\n\nexport interface Roles {\n roles: Role[];\n warnings: string[];\n limits: { maxLiveScoops: number; maxPerTurn: number };\n}\n\nexport const DEFAULT_LIMITS = { maxLiveScoops: 16, maxPerTurn: 64 };\n\nconst TOOLS: Record<string, string> = {\n read: 'read',\n write: 'write',\n edit: 'edit',\n bash: 'bash',\n grep: 'bash',\n find: 'bash',\n ls: 'bash',\n memory_write: 'memory_write',\n};\n\nconst WRITERS = new Set(['write', 'edit', 'bash']);\n\nconst PASSED = new Set([\n 'codemode',\n 'list_mcp_resources',\n 'list_mcp_resource_templates',\n 'read_mcp_resource',\n]);\n\nfunction passThrough(name: string): boolean {\n return PASSED.has(name) || /^mcp__[A-Za-z0-9_*]+$/.test(name);\n}\n\nconst THINKING = new Set<string>(['off', 'minimal', 'low', 'medium', 'high', 'xhigh']);\n\nconst APPLIED = new Set([\n 'name',\n 'description',\n 'tools',\n 'model',\n 'thinking',\n 'systemPromptMode',\n 'aliases',\n 'output',\n 'package',\n 'advertise',\n 'inheritProjectContext',\n 'inheritGlobalContext',\n 'inheritSkills',\n 'memory',\n 'skills',\n 'defaultReads',\n]);\n\nexport type RoleFiles = Pick<ExecutionEnv, 'readTextFile' | 'listDir'>;\n\nexport interface RoleSourceDir {\n source: RoleSource;\n dir: string;\n}\n\nfunction list(value: FrontmatterValue | undefined): string[] {\n if (Array.isArray(value)) return value;\n if (typeof value === 'string')\n return value\n .split(',')\n .map((item) => item.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction tools(names: string[], where: string, warnings: string[]): string[] {\n const mapped: string[] = [];\n for (const name of names) {\n const tool = TOOLS[name] ?? (passThrough(name) ? name : undefined);\n if (tool) {\n if (!mapped.includes(tool)) mapped.push(tool);\n } else warnings.push(`${where}: tool \"${name}\" isn't available in SLICC; it's left out`);\n }\n return mapped;\n}\n\nexport function roleMemory(value: FrontmatterValue): RoleMemory | undefined {\n if (typeof value !== 'string') return undefined;\n const inline = /^\\{(.*)\\}$/s.exec(value.trim());\n const pairs = new Map<string, string>();\n for (const part of (inline ? (inline[1] as string) : value).split(/[,\\n]/)) {\n const found = /^\\s*([\\w-]+)\\s*:\\s*(.*?)\\s*$/.exec(part);\n if (found) pairs.set(found[1] as string, (found[2] as string).replace(/^([\"'])(.*)\\1$/, '$2'));\n }\n const scope = pairs.get('scope');\n const path = pairs.get('path');\n if ((scope !== 'user' && scope !== 'project') || !path) return undefined;\n return { scope, path };\n}\n\nfunction withMemoryWrite(\n listed: string[] | undefined,\n memory: RoleMemory | undefined\n): string[] | undefined {\n if (memory && listed?.some((tool) => WRITERS.has(tool)) && !listed.includes('memory_write'))\n return [...listed, 'memory_write'];\n return listed;\n}\n\nfunction memoryFields(\n fields: Record<string, FrontmatterValue>,\n path: string,\n warnings: string[]\n): Pick<Role, 'memory' | 'context'> & { listed: string[] | undefined } {\n const memory = fields.memory === undefined ? undefined : roleMemory(fields.memory);\n if (fields.memory !== undefined && !memory)\n warnings.push(`${path}: memory needs a scope (user or project) and a path; ignored`);\n const listed = withMemoryWrite(\n fields.tools !== undefined ? tools(list(fields.tools), path, warnings) : undefined,\n memory\n );\n const inherits =\n fields.inheritProjectContext !== undefined || fields.inheritGlobalContext !== undefined;\n return {\n ...(memory ? { memory } : {}),\n listed,\n ...(inherits\n ? {\n context: {\n project: fields.inheritProjectContext !== false,\n global: fields.inheritGlobalContext === true,\n },\n }\n : {}),\n };\n}\n\nexport function parseRole(\n text: string,\n source: RoleSource,\n path: string,\n warnings: string[]\n): Role | undefined {\n const { fields, body, problems } = parseFrontmatter(text, ['memory']);\n for (const problem of problems) warnings.push(`${path}: ${problem}`);\n const name = fields.name;\n const description = fields.description;\n if (typeof name !== 'string' || typeof description !== 'string') {\n warnings.push(`${path}: an agent file needs a name and a description; skipped`);\n return undefined;\n }\n for (const key of Object.keys(fields))\n if (!APPLIED.has(key))\n warnings.push(`${path}: \"${key}\" isn't supported in SLICC; it's ignored`);\n const thinking =\n typeof fields.thinking === 'string' && THINKING.has(fields.thinking)\n ? (fields.thinking as Thinking)\n : undefined;\n if (fields.thinking !== undefined && !thinking)\n warnings.push(`${path}: thinking \"${String(fields.thinking)}\" is unknown; ignored`);\n const { memory, listed, context } = memoryFields(fields, path, warnings);\n const pkg = typeof fields.package === 'string' && fields.package ? `${fields.package}.` : '';\n return {\n name: `${pkg}${name}`,\n description,\n prompt: body,\n mode: fields.systemPromptMode === 'append' ? 'append' : 'replace',\n ...(listed ? { tools: listed } : {}),\n ...(typeof fields.model === 'string' ? { model: fields.model } : {}),\n ...(thinking ? { thinking } : {}),\n aliases: list(fields.aliases),\n ...(typeof fields.output === 'string' ? { output: fields.output } : {}),\n ...(memory ? { memory } : {}),\n ...(context ? { context } : {}),\n source,\n path,\n };\n}\n\nasync function markdown(\n files: RoleFiles,\n dir: string,\n context: Context,\n depth = 0\n): Promise<string[]> {\n if (dir.endsWith('.md')) return [dir];\n const listed = await files.listDir(dir, context);\n if (!listed.ok || depth > 4) return [];\n const out: string[] = [];\n for (const info of listed.value) {\n const path = `${dir}/${info.name}`;\n if (info.kind === 'directory') out.push(...(await markdown(files, path, context, depth + 1)));\n else if (info.name.endsWith('.md') && !info.name.endsWith('.chain.md')) out.push(path);\n }\n return out.sort();\n}\n\ntype Override = {\n model?: unknown;\n thinking?: unknown;\n tools?: unknown;\n systemPrompt?: unknown;\n description?: unknown;\n disabled?: unknown;\n};\n\ninterface Settings {\n overrides: Record<string, Override>;\n limits: Roles['limits'];\n}\n\nfunction positive(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : fallback;\n}\n\nasync function settings(\n files: RoleFiles,\n path: string,\n context: Context,\n warnings: string[]\n): Promise<Settings> {\n const read = await files.readTextFile(path, context);\n const empty = { overrides: {}, limits: { ...DEFAULT_LIMITS } };\n if (!read.ok) return empty;\n let parsed: {\n subagents?: {\n agentOverrides?: Record<string, Override>;\n maxLiveScoops?: unknown;\n maxPerTurn?: unknown;\n };\n };\n try {\n parsed = JSON.parse(read.value);\n } catch (error) {\n warnings.push(`${path}: not valid JSON (${(error as Error).message}); overrides ignored`);\n return empty;\n }\n const subagents = parsed.subagents ?? {};\n return {\n overrides: subagents.agentOverrides ?? {},\n limits: {\n maxLiveScoops: positive(subagents.maxLiveScoops, DEFAULT_LIMITS.maxLiveScoops),\n maxPerTurn: positive(subagents.maxPerTurn, DEFAULT_LIMITS.maxPerTurn),\n },\n };\n}\n\nfunction apply(role: Role, override: Override | undefined, warnings: string[]): Role | undefined {\n if (!override) return role;\n if (override.disabled === true) return undefined;\n const next: Role = { ...role };\n if (typeof override.model === 'string') next.model = override.model;\n if (typeof override.thinking === 'string' && THINKING.has(override.thinking))\n next.thinking = override.thinking as Thinking;\n if (typeof override.description === 'string') next.description = override.description;\n if (typeof override.systemPrompt === 'string') next.prompt = override.systemPrompt;\n if (Array.isArray(override.tools))\n next.tools = withMemoryWrite(\n tools(override.tools.map(String), `override for ${role.name}`, warnings),\n role.memory\n );\n return next;\n}\n\nexport interface LoadOptions {\n files: RoleFiles;\n builtin: () => Promise<{ path: string; text: string }[]>;\n dirs: RoleSourceDir[];\n settingsPath: string;\n}\n\nconst ORDER: RoleSource[] = ['builtin', 'package', 'user', 'project'];\n\nexport async function loadRoles(options: LoadOptions, context: Context): Promise<Roles> {\n const warnings: string[] = [];\n const byName = new Map<string, Role>();\n const add = (role: Role | undefined) => {\n if (role) byName.set(role.name, role);\n };\n for (const { path, text } of await options.builtin())\n add(parseRole(text, 'builtin', path, warnings));\n const dirs = [...options.dirs].sort((a, b) => ORDER.indexOf(a.source) - ORDER.indexOf(b.source));\n for (const { source, dir } of dirs)\n for (const path of await markdown(options.files, dir, context)) {\n const read = await options.files.readTextFile(path, context);\n if (read.ok) add(parseRole(read.value, source, path, warnings));\n }\n const { overrides, limits } = await settings(\n options.files,\n options.settingsPath,\n context,\n warnings\n );\n const roles: Role[] = [];\n for (const role of byName.values()) {\n const applied = apply(role, overrides[role.name], warnings);\n if (applied) roles.push(applied);\n }\n return { roles, warnings, limits };\n}\n\nexport function findRole(roles: readonly Role[], name: string): Role | undefined {\n return (\n roles.find((role) => role.name === name) ?? roles.find((role) => role.aliases.includes(name))\n );\n}\n\nexport async function manifestDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const top = await files.listDir(root, context);\n if (!top.ok) return [];\n const out: string[] = [];\n for (const entry of top.value) {\n if (entry.kind !== 'directory' || entry.name.startsWith('.')) continue;\n if (!entry.name.startsWith('@')) {\n out.push(`${root}/${entry.name}`);\n continue;\n }\n const scoped = await files.listDir(`${root}/${entry.name}`, context);\n if (scoped.ok)\n for (const inner of scoped.value)\n if (inner.kind === 'directory') out.push(`${root}/${entry.name}/${inner.name}`);\n }\n return out;\n}\n\ntype Manifest = {\n 'pi-subagents'?: { agents?: unknown };\n pi?: { subagents?: { agents?: unknown } };\n};\n\nexport function agentPaths(dir: string, text: string): string[] {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(text) as Manifest;\n } catch {\n return [];\n }\n const agents = manifest['pi-subagents']?.agents ?? manifest.pi?.subagents?.agents;\n const listed = Array.isArray(agents) ? agents : typeof agents === 'string' ? [agents] : [];\n return listed\n .filter((path): path is string => typeof path === 'string')\n .map((path) => `${dir}/${path.replace(/^\\.\\//, '').replace(/\\/$/, '')}`);\n}\n\nexport async function packageDirs(\n files: RoleFiles,\n root: string,\n context: Context\n): Promise<string[]> {\n const out: string[] = [];\n for (const dir of await manifestDirs(files, root, context)) {\n const read = await files.readTextFile(`${dir}/package.json`, context);\n if (read.ok) out.push(...agentPaths(dir, read.value));\n }\n return out;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -66,7 +66,8 @@ function setupScoops(registry, licks, fileTools = []) {
66
66
  tools: fileTools,
67
67
  groups,
68
68
  reads: options.reads,
69
- files: env
69
+ files: env,
70
+ ...options.mcp ? { mcp: options.mcp } : {}
70
71
  });
71
72
  const builtin = async () => {
72
73
  const out = [];