@subimpact/e 0.99.2 → 0.99.4
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/CHANGELOG.md +4 -21
- package/dist/bundle/chunks/{chunk-75XIWY7P.js → chunk-4GK5QWPL.js} +1 -1
- package/dist/bundle/chunks/{chunk-5ZENNE67.js → chunk-EWH2CBXL.js} +5 -5
- package/dist/bundle/chunks/{pi-logo-animation-MA3YLQTM.js → pi-logo-animation-5NR3P2W2.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-VX2P5PB3.js → virtual-modules-33PKUUYB.js} +1 -1
- package/dist/bundle/cli-runtime.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/modes/interactive/components/pi-logo-animation.js +2 -2
- package/dist/modes/interactive/components/pi-logo-animation.js.map +1 -1
- package/dist/modes/interactive/components/pi-logo.d.ts +7 -6
- package/dist/modes/interactive/components/pi-logo.d.ts.map +1 -1
- package/dist/modes/interactive/components/pi-logo.js +12 -11
- package/dist/modes/interactive/components/pi-logo.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.js +1 -1
- package/dist/modes/interactive/session-share.js.map +1 -1
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +1 -1
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/package.json +1 -1
- package/examples/extensions/subagent/README.md +0 -177
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -157
- package/examples/extensions/subagent/index.ts +0 -1038
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -98,7 +98,7 @@ async function tryShareViaRadius(tmpFile, context) {
|
|
|
98
98
|
const body = fs.readFileSync(tmpFile);
|
|
99
99
|
const url = new URL("/v1/artifacts", DEFAULT_RADIUS_GATEWAY);
|
|
100
100
|
url.searchParams.set("visibility", "organization");
|
|
101
|
-
url.searchParams.set("title", "
|
|
101
|
+
url.searchParams.set("title", "e session");
|
|
102
102
|
const response = await fetch(url, {
|
|
103
103
|
method: "POST",
|
|
104
104
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-share.js","sourceRoot":"","sources":["../../../src/modes/interactive/session-share.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, spawnSync } from \"node:child_process\";\nimport * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { DEFAULT_RADIUS_GATEWAY } from \"@earendil-works/pi-ai/providers/radius-config\";\nimport { type Container, type EditorComponent, hyperlink, type TUI } from \"@earendil-works/pi-tui\";\nimport { getAuthCredential } from \"../../cli/auth-command.ts\";\nimport { getShareViewerUrl } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { exportSessionToJsonl } from \"../../core/session-export.ts\";\nimport { BorderedLoader } from \"./components/bordered-loader.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\ninterface SessionShareContext {\n\tsession: AgentSession;\n\tui: TUI;\n\teditorContainer: Container;\n\teditor: EditorComponent;\n\tshowStatus: (message: string) => void;\n\tshowError: (message: string) => void;\n}\n\n/** Trailing `pi.share` entry carrying the system prompt and tool schemas for the session viewer. */\nexport function createShareTrailingEntries(\n\tsession: AgentSession,\n\tparentId: string | null,\n\ttimestamp: string,\n): object[] {\n\treturn [\n\t\t{\n\t\t\ttype: \"custom\",\n\t\t\tcustomType: \"pi.share\",\n\t\t\tid: crypto.randomUUID().slice(0, 8),\n\t\t\tparentId,\n\t\t\ttimestamp,\n\t\t\tdata: {\n\t\t\t\tsystemPrompt: session.state.systemPrompt,\n\t\t\t\ttools: session.state.tools.map((tool) => ({\n\t\t\t\t\tname: tool.name,\n\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\tparameters: tool.parameters,\n\t\t\t\t})),\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** Export the current branch with presentation metadata for Radius. */\nexport function exportSessionForShare(filePath: string, session: AgentSession): void {\n\texportSessionToJsonl(session.sessionManager, filePath, (parentId, timestamp) =>\n\t\tcreateShareTrailingEntries(session, parentId, timestamp),\n\t);\n}\n\n/** Share the current session through Radius, falling back to a private gist. */\nexport async function shareSession(context: SessionShareContext): Promise<void> {\n\tconst tempDir = fs.mkdtempSync(path.join(os.tmpdir(), \"pi-share-\"));\n\tconst jsonlFile = path.join(tempDir, \"session.jsonl\");\n\tconst htmlFile = path.join(tempDir, \"session.html\");\n\n\ttry {\n\t\ttry {\n\t\t\texportSessionForShare(jsonlFile, context.session);\n\t\t} catch (error: unknown) {\n\t\t\tcontext.showError(`Failed to export session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\t\tif (await tryShareViaRadius(jsonlFile, context)) return;\n\n\t\ttry {\n\t\t\tconst authResult = spawnSync(\"gh\", [\"auth\", \"status\"], { encoding: \"utf-8\" });\n\t\t\tif (authResult.status !== 0) {\n\t\t\t\tcontext.showError(\"GitHub CLI is not logged in. Run 'gh auth login' first.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\tcontext.showError(\"GitHub CLI (gh) is not installed. Install it from https://cli.github.com/\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait context.session.exportToHtml(htmlFile, { themeName: theme.name });\n\t\t} catch (error: unknown) {\n\t\t\tcontext.showError(`Failed to export session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\t\tawait shareViaGist(htmlFile, context);\n\t} finally {\n\t\ttry {\n\t\t\tfs.rmSync(tempDir, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Ignore cleanup errors\n\t\t}\n\t}\n}\n\nasync function tryShareViaRadius(tmpFile: string, context: SessionShareContext): Promise<boolean> {\n\tconst provider = context.session.modelRuntime.getProvider(\"radius\");\n\tif (!provider) return false;\n\n\tconst token = getAuthCredential(\n\t\tawait context.session.modelRuntime.getAuth(\"radius\", { minOAuthValidityMs: 5 * 60_000 }),\n\t);\n\tif (!token) return false;\n\n\tconst loader = new BorderedLoader(context.ui, theme, \"Uploading to Radius...\");\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(loader);\n\tcontext.ui.setFocus(loader);\n\tcontext.ui.requestRender();\n\tloader.onAbort = () => {\n\t\trestoreEditor(loader, context);\n\t\tcontext.showStatus(\"Share cancelled\");\n\t};\n\n\ttry {\n\t\tconst body = fs.readFileSync(tmpFile);\n\t\tconst url = new URL(\"/v1/artifacts\", DEFAULT_RADIUS_GATEWAY);\n\t\turl.searchParams.set(\"visibility\", \"organization\");\n\t\turl.searchParams.set(\"title\", \"Pi session\");\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t\"Content-Type\": \"application/x-ndjson\",\n\t\t\t\t\"Content-Length\": String(body.byteLength),\n\t\t\t},\n\t\t\tbody,\n\t\t\tsignal: loader.signal,\n\t\t});\n\t\tif (loader.signal.aborted) return true;\n\t\tconst json = (await response.json().catch(() => null)) as {\n\t\t\tartifact?: { canonical_url: string };\n\t\t\terror?: string;\n\t\t} | null;\n\t\tif (loader.signal.aborted) return true;\n\t\trestoreEditor(loader, context);\n\t\tif (!response.ok || !json?.artifact) {\n\t\t\tcontext.showError(\n\t\t\t\t`Failed to upload Radius artifact: ${json?.error || response.statusText || response.status}`,\n\t\t\t);\n\t\t\treturn true;\n\t\t}\n\t\tconst shareUrl = json.artifact.canonical_url;\n\t\tcontext.showStatus(`Share URL: ${hyperlink(shareUrl, shareUrl)}`);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (!loader.signal.aborted) {\n\t\t\trestoreEditor(loader, context);\n\t\t\tcontext.showError(\n\t\t\t\t`Failed to upload Radius artifact: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t\t);\n\t\t}\n\t\treturn true;\n\t}\n}\n\nasync function shareViaGist(tmpFile: string, context: SessionShareContext): Promise<void> {\n\tconst loader = new BorderedLoader(context.ui, theme, \"Creating gist...\");\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(loader);\n\tcontext.ui.setFocus(loader);\n\tcontext.ui.requestRender();\n\n\tlet proc: ReturnType<typeof spawn> | null = null;\n\tloader.onAbort = () => {\n\t\tproc?.kill();\n\t\trestoreEditor(loader, context);\n\t\tcontext.showStatus(\"Share cancelled\");\n\t};\n\n\ttry {\n\t\tconst result = await new Promise<{ stdout: string; stderr: string; code: number | null }>((resolve) => {\n\t\t\tproc = spawn(\"gh\", [\"gist\", \"create\", \"--public=false\", tmpFile]);\n\t\t\tlet stdout = \"\";\n\t\t\tlet stderr = \"\";\n\t\t\tproc.stdout?.on(\"data\", (data) => {\n\t\t\t\tstdout += data.toString();\n\t\t\t});\n\t\t\tproc.stderr?.on(\"data\", (data) => {\n\t\t\t\tstderr += data.toString();\n\t\t\t});\n\t\t\tproc.on(\"close\", (code) => resolve({ stdout, stderr, code }));\n\t\t});\n\n\t\tif (loader.signal.aborted) return;\n\t\trestoreEditor(loader, context);\n\n\t\tif (result.code !== 0) {\n\t\t\tcontext.showError(`Failed to create gist: ${result.stderr?.trim() || \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst gistUrl = result.stdout?.trim();\n\t\tconst gistId = gistUrl?.split(\"/\").pop();\n\t\tif (!gistId) {\n\t\t\tcontext.showError(\"Failed to parse gist ID from gh output\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst previewUrl = getShareViewerUrl(gistId);\n\t\tcontext.showStatus(`Share URL: ${hyperlink(previewUrl, previewUrl)}\\nGist: ${hyperlink(gistUrl, gistUrl)}`);\n\t} catch (error: unknown) {\n\t\tif (!loader.signal.aborted) {\n\t\t\trestoreEditor(loader, context);\n\t\t\tcontext.showError(`Failed to create gist: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t}\n\t}\n}\n\nfunction restoreEditor(loader: BorderedLoader, context: SessionShareContext): void {\n\tloader.dispose();\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(context.editor);\n\tcontext.ui.setFocus(context.editor);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-share.js","sourceRoot":"","sources":["../../../src/modes/interactive/session-share.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, spawnSync } from \"node:child_process\";\nimport * as crypto from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { DEFAULT_RADIUS_GATEWAY } from \"@earendil-works/pi-ai/providers/radius-config\";\nimport { type Container, type EditorComponent, hyperlink, type TUI } from \"@earendil-works/pi-tui\";\nimport { getAuthCredential } from \"../../cli/auth-command.ts\";\nimport { getShareViewerUrl } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { exportSessionToJsonl } from \"../../core/session-export.ts\";\nimport { BorderedLoader } from \"./components/bordered-loader.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\ninterface SessionShareContext {\n\tsession: AgentSession;\n\tui: TUI;\n\teditorContainer: Container;\n\teditor: EditorComponent;\n\tshowStatus: (message: string) => void;\n\tshowError: (message: string) => void;\n}\n\n/** Trailing `pi.share` entry carrying the system prompt and tool schemas for the session viewer. */\nexport function createShareTrailingEntries(\n\tsession: AgentSession,\n\tparentId: string | null,\n\ttimestamp: string,\n): object[] {\n\treturn [\n\t\t{\n\t\t\ttype: \"custom\",\n\t\t\tcustomType: \"pi.share\",\n\t\t\tid: crypto.randomUUID().slice(0, 8),\n\t\t\tparentId,\n\t\t\ttimestamp,\n\t\t\tdata: {\n\t\t\t\tsystemPrompt: session.state.systemPrompt,\n\t\t\t\ttools: session.state.tools.map((tool) => ({\n\t\t\t\t\tname: tool.name,\n\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\tparameters: tool.parameters,\n\t\t\t\t})),\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** Export the current branch with presentation metadata for Radius. */\nexport function exportSessionForShare(filePath: string, session: AgentSession): void {\n\texportSessionToJsonl(session.sessionManager, filePath, (parentId, timestamp) =>\n\t\tcreateShareTrailingEntries(session, parentId, timestamp),\n\t);\n}\n\n/** Share the current session through Radius, falling back to a private gist. */\nexport async function shareSession(context: SessionShareContext): Promise<void> {\n\tconst tempDir = fs.mkdtempSync(path.join(os.tmpdir(), \"pi-share-\"));\n\tconst jsonlFile = path.join(tempDir, \"session.jsonl\");\n\tconst htmlFile = path.join(tempDir, \"session.html\");\n\n\ttry {\n\t\ttry {\n\t\t\texportSessionForShare(jsonlFile, context.session);\n\t\t} catch (error: unknown) {\n\t\t\tcontext.showError(`Failed to export session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\t\tif (await tryShareViaRadius(jsonlFile, context)) return;\n\n\t\ttry {\n\t\t\tconst authResult = spawnSync(\"gh\", [\"auth\", \"status\"], { encoding: \"utf-8\" });\n\t\t\tif (authResult.status !== 0) {\n\t\t\t\tcontext.showError(\"GitHub CLI is not logged in. Run 'gh auth login' first.\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t} catch {\n\t\t\tcontext.showError(\"GitHub CLI (gh) is not installed. Install it from https://cli.github.com/\");\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tawait context.session.exportToHtml(htmlFile, { themeName: theme.name });\n\t\t} catch (error: unknown) {\n\t\t\tcontext.showError(`Failed to export session: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\t\tawait shareViaGist(htmlFile, context);\n\t} finally {\n\t\ttry {\n\t\t\tfs.rmSync(tempDir, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Ignore cleanup errors\n\t\t}\n\t}\n}\n\nasync function tryShareViaRadius(tmpFile: string, context: SessionShareContext): Promise<boolean> {\n\tconst provider = context.session.modelRuntime.getProvider(\"radius\");\n\tif (!provider) return false;\n\n\tconst token = getAuthCredential(\n\t\tawait context.session.modelRuntime.getAuth(\"radius\", { minOAuthValidityMs: 5 * 60_000 }),\n\t);\n\tif (!token) return false;\n\n\tconst loader = new BorderedLoader(context.ui, theme, \"Uploading to Radius...\");\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(loader);\n\tcontext.ui.setFocus(loader);\n\tcontext.ui.requestRender();\n\tloader.onAbort = () => {\n\t\trestoreEditor(loader, context);\n\t\tcontext.showStatus(\"Share cancelled\");\n\t};\n\n\ttry {\n\t\tconst body = fs.readFileSync(tmpFile);\n\t\tconst url = new URL(\"/v1/artifacts\", DEFAULT_RADIUS_GATEWAY);\n\t\turl.searchParams.set(\"visibility\", \"organization\");\n\t\turl.searchParams.set(\"title\", \"e session\");\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t\"Content-Type\": \"application/x-ndjson\",\n\t\t\t\t\"Content-Length\": String(body.byteLength),\n\t\t\t},\n\t\t\tbody,\n\t\t\tsignal: loader.signal,\n\t\t});\n\t\tif (loader.signal.aborted) return true;\n\t\tconst json = (await response.json().catch(() => null)) as {\n\t\t\tartifact?: { canonical_url: string };\n\t\t\terror?: string;\n\t\t} | null;\n\t\tif (loader.signal.aborted) return true;\n\t\trestoreEditor(loader, context);\n\t\tif (!response.ok || !json?.artifact) {\n\t\t\tcontext.showError(\n\t\t\t\t`Failed to upload Radius artifact: ${json?.error || response.statusText || response.status}`,\n\t\t\t);\n\t\t\treturn true;\n\t\t}\n\t\tconst shareUrl = json.artifact.canonical_url;\n\t\tcontext.showStatus(`Share URL: ${hyperlink(shareUrl, shareUrl)}`);\n\t\treturn true;\n\t} catch (error: unknown) {\n\t\tif (!loader.signal.aborted) {\n\t\t\trestoreEditor(loader, context);\n\t\t\tcontext.showError(\n\t\t\t\t`Failed to upload Radius artifact: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t\t);\n\t\t}\n\t\treturn true;\n\t}\n}\n\nasync function shareViaGist(tmpFile: string, context: SessionShareContext): Promise<void> {\n\tconst loader = new BorderedLoader(context.ui, theme, \"Creating gist...\");\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(loader);\n\tcontext.ui.setFocus(loader);\n\tcontext.ui.requestRender();\n\n\tlet proc: ReturnType<typeof spawn> | null = null;\n\tloader.onAbort = () => {\n\t\tproc?.kill();\n\t\trestoreEditor(loader, context);\n\t\tcontext.showStatus(\"Share cancelled\");\n\t};\n\n\ttry {\n\t\tconst result = await new Promise<{ stdout: string; stderr: string; code: number | null }>((resolve) => {\n\t\t\tproc = spawn(\"gh\", [\"gist\", \"create\", \"--public=false\", tmpFile]);\n\t\t\tlet stdout = \"\";\n\t\t\tlet stderr = \"\";\n\t\t\tproc.stdout?.on(\"data\", (data) => {\n\t\t\t\tstdout += data.toString();\n\t\t\t});\n\t\t\tproc.stderr?.on(\"data\", (data) => {\n\t\t\t\tstderr += data.toString();\n\t\t\t});\n\t\t\tproc.on(\"close\", (code) => resolve({ stdout, stderr, code }));\n\t\t});\n\n\t\tif (loader.signal.aborted) return;\n\t\trestoreEditor(loader, context);\n\n\t\tif (result.code !== 0) {\n\t\t\tcontext.showError(`Failed to create gist: ${result.stderr?.trim() || \"Unknown error\"}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst gistUrl = result.stdout?.trim();\n\t\tconst gistId = gistUrl?.split(\"/\").pop();\n\t\tif (!gistId) {\n\t\t\tcontext.showError(\"Failed to parse gist ID from gh output\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst previewUrl = getShareViewerUrl(gistId);\n\t\tcontext.showStatus(`Share URL: ${hyperlink(previewUrl, previewUrl)}\\nGist: ${hyperlink(gistUrl, gistUrl)}`);\n\t} catch (error: unknown) {\n\t\tif (!loader.signal.aborted) {\n\t\t\trestoreEditor(loader, context);\n\t\t\tcontext.showError(`Failed to create gist: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t\t}\n\t}\n}\n\nfunction restoreEditor(loader: BorderedLoader, context: SessionShareContext): void {\n\tloader.dispose();\n\tcontext.editorContainer.clear();\n\tcontext.editorContainer.addChild(context.editor);\n\tcontext.ui.setFocus(context.editor);\n}\n"]}
|
package/examples/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Programmatic usage via `createAgentSession()`. Shows how to customize models, pr
|
|
|
20
20
|
### [extensions/](extensions/)
|
|
21
21
|
Example extensions demonstrating:
|
|
22
22
|
- Lifecycle event handlers (tool interception, safety gates, context modifications)
|
|
23
|
-
- Custom tools (todo lists, questions,
|
|
23
|
+
- Custom tools (todo lists, questions, background tasks, output truncation)
|
|
24
24
|
- Commands and keyboard shortcuts
|
|
25
25
|
- Custom UI (footers, headers, editors, overlays)
|
|
26
26
|
- Git integration (checkpoints, auto-commit)
|
|
@@ -41,7 +41,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
|
|
41
41
|
| `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
|
|
42
42
|
| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
|
|
43
43
|
| `ssh.ts` | Delegate all tools to a remote machine via SSH using pluggable operations |
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
|
|
46
46
|
### Commands & UI
|
|
47
47
|
|
|
@@ -481,7 +481,7 @@ class StreamingOverflowComponent extends BaseOverlay {
|
|
|
481
481
|
"-c",
|
|
482
482
|
`
|
|
483
483
|
echo "Starting streaming overflow test (30+ seconds)..."
|
|
484
|
-
echo "This
|
|
484
|
+
echo "This simulated background-task output with colors, hyperlinks, and long paths"
|
|
485
485
|
echo ""
|
|
486
486
|
for i in $(seq 1 100); do
|
|
487
487
|
# Simulate long file paths with OSC 8 hyperlinks (clickable) - tests width overflow
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subimpact/e",
|
|
3
|
-
"version": "0.99.
|
|
3
|
+
"version": "0.99.4",
|
|
4
4
|
"description": "Minimal terminal coding harness. Fork of earendil-works/pi (MIT) with the MCP, codemode, and tool-search built-ins removed; compatibility with the classical pi extension/package ecosystem.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
# Subagent Example
|
|
2
|
-
|
|
3
|
-
Delegate tasks to specialized subagents with isolated context windows.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Isolated context**: Each subagent runs in a separate `pi` process
|
|
8
|
-
- **Streaming output**: See tool calls and progress as they happen
|
|
9
|
-
- **Parallel streaming**: All parallel tasks stream updates simultaneously
|
|
10
|
-
- **Markdown rendering**: Final output rendered with proper formatting (expanded view)
|
|
11
|
-
- **Usage tracking**: Shows turns, tokens, cost, and context usage per agent
|
|
12
|
-
- **Abort support**: Ctrl+C propagates to kill subagent processes
|
|
13
|
-
|
|
14
|
-
## Structure
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
subagent/
|
|
18
|
-
├── README.md # This file
|
|
19
|
-
├── index.ts # The extension (entry point)
|
|
20
|
-
├── agents.ts # Agent discovery logic
|
|
21
|
-
├── agents/ # Sample agent definitions
|
|
22
|
-
│ ├── scout.md # Fast recon, returns compressed context
|
|
23
|
-
│ ├── planner.md # Creates implementation plans
|
|
24
|
-
│ ├── reviewer.md # Code review
|
|
25
|
-
│ └── worker.md # General-purpose (full capabilities)
|
|
26
|
-
└── prompts/ # Workflow presets (prompt templates)
|
|
27
|
-
├── implement.md # scout -> planner -> worker
|
|
28
|
-
├── scout-and-plan.md # scout -> planner (no implementation)
|
|
29
|
-
└── implement-and-review.md # worker -> reviewer -> worker
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Installation
|
|
33
|
-
|
|
34
|
-
From the repository root, symlink the files:
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Symlink the extension (must be in a subdirectory with index.ts)
|
|
38
|
-
mkdir -p ~/.pi/agent/extensions/subagent
|
|
39
|
-
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/index.ts" ~/.pi/agent/extensions/subagent/index.ts
|
|
40
|
-
ln -sf "$(pwd)/packages/coding-agent/examples/extensions/subagent/agents.ts" ~/.pi/agent/extensions/subagent/agents.ts
|
|
41
|
-
|
|
42
|
-
# Symlink agents
|
|
43
|
-
mkdir -p ~/.pi/agent/agents
|
|
44
|
-
for f in packages/coding-agent/examples/extensions/subagent/agents/*.md; do
|
|
45
|
-
ln -sf "$(pwd)/$f" ~/.pi/agent/agents/$(basename "$f")
|
|
46
|
-
done
|
|
47
|
-
|
|
48
|
-
# Symlink workflow prompts
|
|
49
|
-
mkdir -p ~/.pi/agent/prompts
|
|
50
|
-
for f in packages/coding-agent/examples/extensions/subagent/prompts/*.md; do
|
|
51
|
-
ln -sf "$(pwd)/$f" ~/.pi/agent/prompts/$(basename "$f")
|
|
52
|
-
done
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
## Security Model
|
|
56
|
-
|
|
57
|
-
This tool executes a separate `pi` subprocess with a delegated system prompt and tool/model configuration.
|
|
58
|
-
|
|
59
|
-
**Project-local agents** (`.pi/agents/*.md`) are repo-controlled prompts that can instruct the model to read files, run bash commands, etc.
|
|
60
|
-
|
|
61
|
-
**Default behavior:** Only loads **user-level agents** from `~/.pi/agent/agents`.
|
|
62
|
-
|
|
63
|
-
To enable project-local agents, pass `agentScope: "both"` (or `"project"`). Only do this for repositories you trust.
|
|
64
|
-
|
|
65
|
-
When running interactively, the tool prompts for confirmation before running project-local agents in untrusted projects. Trusted projects skip the additional prompt. Set `confirmProjectAgents: false` to disable confirmation.
|
|
66
|
-
|
|
67
|
-
## Usage
|
|
68
|
-
|
|
69
|
-
### Single agent
|
|
70
|
-
```
|
|
71
|
-
Use scout to find all authentication code
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Parallel execution
|
|
75
|
-
```
|
|
76
|
-
Run 2 scouts in parallel: one to find models, one to find providers
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Chained workflow
|
|
80
|
-
```
|
|
81
|
-
Use a chain: first have scout find the read tool, then have planner suggest improvements
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Workflow prompts
|
|
85
|
-
```
|
|
86
|
-
/implement add Redis caching to the session store
|
|
87
|
-
/scout-and-plan refactor auth to support OAuth
|
|
88
|
-
/implement-and-review add input validation to API endpoints
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Tool Modes
|
|
92
|
-
|
|
93
|
-
| Mode | Parameter | Description |
|
|
94
|
-
|------|-----------|-------------|
|
|
95
|
-
| Single | `{ agent, task }` | One agent, one task |
|
|
96
|
-
| Parallel | `{ tasks: [...] }` | Multiple agents run concurrently (max 8, 4 concurrent) |
|
|
97
|
-
| Chain | `{ chain: [...] }` | Sequential with `{previous}` placeholder |
|
|
98
|
-
|
|
99
|
-
## Output Display
|
|
100
|
-
|
|
101
|
-
**Collapsed view** (default):
|
|
102
|
-
- Status icon (✓/✗/⏳) and agent name
|
|
103
|
-
- Last 5-10 items (tool calls and text)
|
|
104
|
-
- Usage stats: `3 turns ↑input ↓output RcacheRead WcacheWrite $cost ctx:contextTokens model`
|
|
105
|
-
|
|
106
|
-
**Expanded view** (Ctrl+O):
|
|
107
|
-
- Full task text
|
|
108
|
-
- All tool calls with formatted arguments
|
|
109
|
-
- Final output rendered as Markdown
|
|
110
|
-
- Per-task usage (for chain/parallel)
|
|
111
|
-
|
|
112
|
-
**Parallel mode streaming**:
|
|
113
|
-
- Shows all tasks with live status (⏳ running, ✓ done, ✗ failed)
|
|
114
|
-
- Updates as each task makes progress
|
|
115
|
-
- Shows "2/3 done, 1 running" status
|
|
116
|
-
- Returns each completed task's final output to the parent model, capped at 50 KB per task
|
|
117
|
-
- Returns failure diagnostics from stderr/error messages when a child exits before producing output
|
|
118
|
-
|
|
119
|
-
**Tool call formatting** (mimics built-in tools):
|
|
120
|
-
- `$ command` for bash
|
|
121
|
-
- `read ~/path:1-10` for read
|
|
122
|
-
- `grep /pattern/ in ~/path` for grep
|
|
123
|
-
- etc.
|
|
124
|
-
|
|
125
|
-
## Agent Definitions
|
|
126
|
-
|
|
127
|
-
Agents are markdown files with YAML frontmatter:
|
|
128
|
-
|
|
129
|
-
```markdown
|
|
130
|
-
---
|
|
131
|
-
name: my-agent
|
|
132
|
-
description: What this agent does
|
|
133
|
-
tools: read, grep, find, ls
|
|
134
|
-
model: claude-haiku-4-5
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
System prompt for the agent goes here.
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
When `model` is omitted, the subagent inherits the dispatching session's active model and thinking level.
|
|
141
|
-
|
|
142
|
-
**Locations:**
|
|
143
|
-
- `~/.pi/agent/agents/*.md` - User-level (always loaded)
|
|
144
|
-
- `.pi/agents/*.md` - Project-level (only with `agentScope: "project"` or `"both"`)
|
|
145
|
-
|
|
146
|
-
Project agents override user agents with the same name when `agentScope: "both"`.
|
|
147
|
-
|
|
148
|
-
## Sample Agents
|
|
149
|
-
|
|
150
|
-
| Agent | Purpose | Model | Tools |
|
|
151
|
-
|-------|---------|-------|-------|
|
|
152
|
-
| `scout` | Fast codebase recon | Haiku | read, grep, find, ls, bash |
|
|
153
|
-
| `planner` | Implementation plans | Sonnet | read, grep, find, ls |
|
|
154
|
-
| `reviewer` | Code review | Sonnet | read, grep, find, ls, bash |
|
|
155
|
-
| `worker` | General-purpose | Sonnet | (all default) |
|
|
156
|
-
|
|
157
|
-
## Workflow Prompts
|
|
158
|
-
|
|
159
|
-
| Prompt | Flow |
|
|
160
|
-
|--------|------|
|
|
161
|
-
| `/implement <query>` | scout → planner → worker |
|
|
162
|
-
| `/scout-and-plan <query>` | scout → planner |
|
|
163
|
-
| `/implement-and-review <query>` | worker → reviewer → worker |
|
|
164
|
-
|
|
165
|
-
## Error Handling
|
|
166
|
-
|
|
167
|
-
- **Exit code != 0**: Tool returns error with stderr/output
|
|
168
|
-
- **stopReason "error"**: LLM error propagated with error message
|
|
169
|
-
- **stopReason "aborted"**: User abort (Ctrl+C) kills subprocess, throws error
|
|
170
|
-
- **Chain mode**: Stops at first failing step, reports which step failed
|
|
171
|
-
|
|
172
|
-
## Limitations
|
|
173
|
-
|
|
174
|
-
- Output truncated to last 10 items in collapsed view (expand to see all)
|
|
175
|
-
- Parallel model-visible output is capped at 50 KB per task; full results remain in tool details
|
|
176
|
-
- Agents discovered fresh on each invocation (allows editing mid-session)
|
|
177
|
-
- Parallel mode limited to 8 tasks, 4 concurrent
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: planner
|
|
3
|
-
description: Creates implementation plans from context and requirements
|
|
4
|
-
tools: read, grep, find, ls
|
|
5
|
-
model: claude-sonnet-4-5
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
You are a planning specialist. You receive context (from a scout) and requirements, then produce a clear implementation plan.
|
|
9
|
-
|
|
10
|
-
You must NOT make any changes. Only read, analyze, and plan.
|
|
11
|
-
|
|
12
|
-
Input format you'll receive:
|
|
13
|
-
- Context/findings from a scout agent
|
|
14
|
-
- Original query or requirements
|
|
15
|
-
|
|
16
|
-
Output format:
|
|
17
|
-
|
|
18
|
-
## Goal
|
|
19
|
-
One sentence summary of what needs to be done.
|
|
20
|
-
|
|
21
|
-
## Plan
|
|
22
|
-
Numbered steps, each small and actionable:
|
|
23
|
-
1. Step one - specific file/function to modify
|
|
24
|
-
2. Step two - what to add/change
|
|
25
|
-
3. ...
|
|
26
|
-
|
|
27
|
-
## Files to Modify
|
|
28
|
-
- `path/to/file.ts` - what changes
|
|
29
|
-
- `path/to/other.ts` - what changes
|
|
30
|
-
|
|
31
|
-
## New Files (if any)
|
|
32
|
-
- `path/to/new.ts` - purpose
|
|
33
|
-
|
|
34
|
-
## Risks
|
|
35
|
-
Anything to watch out for.
|
|
36
|
-
|
|
37
|
-
Keep the plan concrete. The worker agent will execute it verbatim.
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: reviewer
|
|
3
|
-
description: Code review specialist for quality and security analysis
|
|
4
|
-
tools: read, grep, find, ls, bash
|
|
5
|
-
model: claude-sonnet-4-5
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
You are a senior code reviewer. Analyze code for quality, security, and maintainability.
|
|
9
|
-
|
|
10
|
-
Bash is for read-only commands only: `git diff`, `git log`, `git show`. Do NOT modify files or run builds.
|
|
11
|
-
Assume tool permissions are not perfectly enforceable; keep all bash usage strictly read-only.
|
|
12
|
-
|
|
13
|
-
Strategy:
|
|
14
|
-
1. Run `git diff` to see recent changes (if applicable)
|
|
15
|
-
2. Read the modified files
|
|
16
|
-
3. Check for bugs, security issues, code smells
|
|
17
|
-
|
|
18
|
-
Output format:
|
|
19
|
-
|
|
20
|
-
## Files Reviewed
|
|
21
|
-
- `path/to/file.ts` (lines X-Y)
|
|
22
|
-
|
|
23
|
-
## Critical (must fix)
|
|
24
|
-
- `file.ts:42` - Issue description
|
|
25
|
-
|
|
26
|
-
## Warnings (should fix)
|
|
27
|
-
- `file.ts:100` - Issue description
|
|
28
|
-
|
|
29
|
-
## Suggestions (consider)
|
|
30
|
-
- `file.ts:150` - Improvement idea
|
|
31
|
-
|
|
32
|
-
## Summary
|
|
33
|
-
Overall assessment in 2-3 sentences.
|
|
34
|
-
|
|
35
|
-
Be specific with file paths and line numbers.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: scout
|
|
3
|
-
description: Fast codebase recon that returns compressed context for handoff to other agents
|
|
4
|
-
tools: read, grep, find, ls, bash
|
|
5
|
-
model: claude-haiku-4-5
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
You are a scout. Quickly investigate a codebase and return structured findings that another agent can use without re-reading everything.
|
|
9
|
-
|
|
10
|
-
Your output will be passed to an agent who has NOT seen the files you explored.
|
|
11
|
-
|
|
12
|
-
Thoroughness (infer from task, default medium):
|
|
13
|
-
- Quick: Targeted lookups, key files only
|
|
14
|
-
- Medium: Follow imports, read critical sections
|
|
15
|
-
- Thorough: Trace all dependencies, check tests/types
|
|
16
|
-
|
|
17
|
-
Strategy:
|
|
18
|
-
1. grep/find to locate relevant code
|
|
19
|
-
2. Read key sections (not entire files)
|
|
20
|
-
3. Identify types, interfaces, key functions
|
|
21
|
-
4. Note dependencies between files
|
|
22
|
-
|
|
23
|
-
Output format:
|
|
24
|
-
|
|
25
|
-
## Files Retrieved
|
|
26
|
-
List with exact line ranges:
|
|
27
|
-
1. `path/to/file.ts` (lines 10-50) - Description of what's here
|
|
28
|
-
2. `path/to/other.ts` (lines 100-150) - Description
|
|
29
|
-
3. ...
|
|
30
|
-
|
|
31
|
-
## Key Code
|
|
32
|
-
Critical types, interfaces, or functions:
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
interface Example {
|
|
36
|
-
// actual code from the files
|
|
37
|
-
}
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
function keyFunction() {
|
|
42
|
-
// actual implementation
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Architecture
|
|
47
|
-
Brief explanation of how the pieces connect.
|
|
48
|
-
|
|
49
|
-
## Start Here
|
|
50
|
-
Which file to look at first and why.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: worker
|
|
3
|
-
description: General-purpose subagent with full capabilities, isolated context
|
|
4
|
-
model: claude-sonnet-4-5
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
You are a worker agent with full capabilities. You operate in an isolated context window to handle delegated tasks without polluting the main conversation.
|
|
8
|
-
|
|
9
|
-
Work autonomously to complete the assigned task. Use all available tools as needed.
|
|
10
|
-
|
|
11
|
-
Output format when finished:
|
|
12
|
-
|
|
13
|
-
## Completed
|
|
14
|
-
What was done.
|
|
15
|
-
|
|
16
|
-
## Files Changed
|
|
17
|
-
- `path/to/file.ts` - what changed
|
|
18
|
-
|
|
19
|
-
## Notes (if any)
|
|
20
|
-
Anything the main agent should know.
|
|
21
|
-
|
|
22
|
-
If handing off to another agent (e.g. reviewer), include:
|
|
23
|
-
- Exact file paths changed
|
|
24
|
-
- Key functions/types touched (short list)
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent discovery and configuration
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as fs from "node:fs";
|
|
6
|
-
import * as path from "node:path";
|
|
7
|
-
import { CONFIG_DIR_NAME, getAgentDir, parseFrontmatter } from "@earendil-works/pi-coding-agent";
|
|
8
|
-
|
|
9
|
-
export type AgentScope = "user" | "project" | "both";
|
|
10
|
-
|
|
11
|
-
export interface AgentConfig {
|
|
12
|
-
name: string;
|
|
13
|
-
description: string;
|
|
14
|
-
tools?: string[];
|
|
15
|
-
model?: string;
|
|
16
|
-
systemPrompt: string;
|
|
17
|
-
source: "user" | "project";
|
|
18
|
-
filePath: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface AgentDiscoveryResult {
|
|
22
|
-
agents: AgentConfig[];
|
|
23
|
-
projectAgentsDir: string | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Raw agent frontmatter. Values are `unknown` because `parseFrontmatter` runs a
|
|
28
|
-
* real YAML parser, so any scalar or collection can appear here.
|
|
29
|
-
*
|
|
30
|
-
* A type alias rather than an interface: `parseFrontmatter` constrains its
|
|
31
|
-
* parameter to `Record<string, unknown>`, and only an alias picks up the
|
|
32
|
-
* implicit index signature that satisfies it.
|
|
33
|
-
*/
|
|
34
|
-
type AgentFrontmatter = {
|
|
35
|
-
name?: unknown;
|
|
36
|
-
description?: unknown;
|
|
37
|
-
tools?: unknown;
|
|
38
|
-
model?: unknown;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Normalize a frontmatter `tools` value to a list of tool names.
|
|
43
|
-
*
|
|
44
|
-
* Both spellings are valid YAML and both are in use:
|
|
45
|
-
*
|
|
46
|
-
* tools: read, bash # string
|
|
47
|
-
* tools: [read, bash] # array
|
|
48
|
-
*
|
|
49
|
-
* so accept either. Anything else (a number, a map, a nested list) yields no
|
|
50
|
-
* tools rather than throwing: this runs inside agent discovery, where a single
|
|
51
|
-
* bad file must not take down every other agent in the same directory.
|
|
52
|
-
*/
|
|
53
|
-
function parseToolList(value: unknown): string[] | undefined {
|
|
54
|
-
const raw = Array.isArray(value) ? value : typeof value === "string" ? value.split(",") : [];
|
|
55
|
-
const tools = raw
|
|
56
|
-
.filter((t): t is string => typeof t === "string")
|
|
57
|
-
.map((t) => t.trim())
|
|
58
|
-
.filter(Boolean);
|
|
59
|
-
return tools.length > 0 ? tools : undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function loadAgentsFromDir(dir: string, source: "user" | "project"): AgentConfig[] {
|
|
63
|
-
const agents: AgentConfig[] = [];
|
|
64
|
-
|
|
65
|
-
if (!fs.existsSync(dir)) {
|
|
66
|
-
return agents;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let entries: fs.Dirent[];
|
|
70
|
-
try {
|
|
71
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
72
|
-
} catch {
|
|
73
|
-
return agents;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
for (const entry of entries) {
|
|
77
|
-
if (!entry.name.endsWith(".md")) continue;
|
|
78
|
-
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
79
|
-
|
|
80
|
-
const filePath = path.join(dir, entry.name);
|
|
81
|
-
let content: string;
|
|
82
|
-
try {
|
|
83
|
-
content = fs.readFileSync(filePath, "utf-8");
|
|
84
|
-
} catch {
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const { frontmatter, body } = parseFrontmatter<AgentFrontmatter>(content);
|
|
89
|
-
|
|
90
|
-
if (typeof frontmatter.name !== "string" || typeof frontmatter.description !== "string") {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
agents.push({
|
|
95
|
-
name: frontmatter.name,
|
|
96
|
-
description: frontmatter.description,
|
|
97
|
-
tools: parseToolList(frontmatter.tools),
|
|
98
|
-
model: typeof frontmatter.model === "string" ? frontmatter.model : undefined,
|
|
99
|
-
systemPrompt: body,
|
|
100
|
-
source,
|
|
101
|
-
filePath,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return agents;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function isDirectory(p: string): boolean {
|
|
109
|
-
try {
|
|
110
|
-
return fs.statSync(p).isDirectory();
|
|
111
|
-
} catch {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function findNearestProjectAgentsDir(cwd: string): string | null {
|
|
117
|
-
let currentDir = cwd;
|
|
118
|
-
while (true) {
|
|
119
|
-
const candidate = path.join(currentDir, CONFIG_DIR_NAME, "agents");
|
|
120
|
-
if (isDirectory(candidate)) return candidate;
|
|
121
|
-
|
|
122
|
-
const parentDir = path.dirname(currentDir);
|
|
123
|
-
if (parentDir === currentDir) return null;
|
|
124
|
-
currentDir = parentDir;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
|
|
129
|
-
const userDir = path.join(getAgentDir(), "agents");
|
|
130
|
-
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
131
|
-
|
|
132
|
-
const userAgents = scope === "project" ? [] : loadAgentsFromDir(userDir, "user");
|
|
133
|
-
const projectAgents = scope === "user" || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, "project");
|
|
134
|
-
|
|
135
|
-
const agentMap = new Map<string, AgentConfig>();
|
|
136
|
-
|
|
137
|
-
if (scope === "both") {
|
|
138
|
-
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
139
|
-
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
140
|
-
} else if (scope === "user") {
|
|
141
|
-
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
142
|
-
} else {
|
|
143
|
-
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function formatAgentList(agents: AgentConfig[], maxItems: number): { text: string; remaining: number } {
|
|
150
|
-
if (agents.length === 0) return { text: "none", remaining: 0 };
|
|
151
|
-
const listed = agents.slice(0, maxItems);
|
|
152
|
-
const remaining = agents.length - listed.length;
|
|
153
|
-
return {
|
|
154
|
-
text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join("; "),
|
|
155
|
-
remaining,
|
|
156
|
-
};
|
|
157
|
-
}
|