@oh-my-pi/pi-coding-agent 14.9.2 → 14.9.5
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 +89 -0
- package/package.json +7 -7
- package/scripts/format-prompts.ts +3 -3
- package/src/async/job-manager.ts +66 -9
- package/src/capability/rule.ts +20 -0
- package/src/config/model-registry.ts +13 -0
- package/src/config/model-resolver.ts +8 -2
- package/src/config/prompt-templates.ts +0 -5
- package/src/config/settings-schema.ts +39 -1
- package/src/edit/index.ts +8 -0
- package/src/edit/renderer.ts +6 -1
- package/src/edit/streaming.ts +53 -2
- package/src/eval/eval.lark +10 -31
- package/src/eval/index.ts +1 -0
- package/src/eval/js/context-manager.ts +1 -38
- package/src/eval/js/prelude.txt +0 -2
- package/src/eval/parse.ts +156 -255
- package/src/eval/py/executor.ts +24 -8
- package/src/eval/py/index.ts +1 -0
- package/src/eval/py/prelude.py +11 -80
- package/src/eval/sniff.ts +28 -0
- package/src/export/html/template.css +50 -0
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +229 -17
- package/src/extensibility/plugins/loader.ts +31 -6
- package/src/extensibility/skills.ts +20 -0
- package/src/hashline/constants.ts +20 -0
- package/src/hashline/grammar.lark +16 -23
- package/src/hashline/hash.ts +4 -34
- package/src/hashline/input.ts +16 -2
- package/src/hashline/parser.ts +12 -1
- package/src/internal-urls/agent-protocol.ts +64 -52
- package/src/internal-urls/artifact-protocol.ts +52 -51
- package/src/internal-urls/docs-index.generated.ts +34 -1
- package/src/internal-urls/index.ts +6 -19
- package/src/internal-urls/local-protocol.ts +50 -7
- package/src/internal-urls/mcp-protocol.ts +3 -8
- package/src/internal-urls/memory-protocol.ts +90 -59
- package/src/internal-urls/pi-protocol.ts +1 -0
- package/src/internal-urls/router.ts +40 -23
- package/src/internal-urls/rule-protocol.ts +3 -20
- package/src/internal-urls/skill-protocol.ts +5 -27
- package/src/internal-urls/types.ts +18 -2
- package/src/main.ts +1 -1
- package/src/mcp/manager.ts +17 -0
- package/src/modes/components/session-observer-overlay.ts +2 -2
- package/src/modes/components/tool-execution.ts +6 -0
- package/src/modes/components/tree-selector.ts +4 -0
- package/src/modes/controllers/event-controller.ts +23 -2
- package/src/modes/controllers/mcp-command-controller.ts +7 -10
- package/src/modes/interactive-mode.ts +2 -2
- package/src/modes/theme/theme.ts +27 -27
- package/src/modes/types.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +14 -9
- package/src/prompts/commands/orchestrate.md +1 -0
- package/src/prompts/system/custom-system-prompt.md +0 -2
- package/src/prompts/system/project-prompt.md +10 -0
- package/src/prompts/system/subagent-system-prompt.md +18 -9
- package/src/prompts/system/subagent-user-prompt.md +1 -10
- package/src/prompts/system/system-prompt.md +159 -232
- package/src/prompts/tools/ask.md +0 -1
- package/src/prompts/tools/bash.md +0 -34
- package/src/prompts/tools/eval.md +27 -16
- package/src/prompts/tools/github.md +6 -5
- package/src/prompts/tools/hashline.md +1 -0
- package/src/prompts/tools/job.md +14 -6
- package/src/prompts/tools/task.md +20 -3
- package/src/registry/agent-registry.ts +2 -1
- package/src/sdk.ts +87 -89
- package/src/session/agent-session.ts +107 -37
- package/src/session/artifacts.ts +7 -4
- package/src/session/session-manager.ts +30 -1
- package/src/ssh/connection-manager.ts +32 -16
- package/src/ssh/sshfs-mount.ts +10 -7
- package/src/system-prompt.ts +3 -9
- package/src/task/executor.ts +23 -7
- package/src/task/index.ts +57 -36
- package/src/tool-discovery/tool-index.ts +21 -8
- package/src/tools/ast-edit.ts +3 -2
- package/src/tools/ast-grep.ts +3 -2
- package/src/tools/bash.ts +30 -50
- package/src/tools/browser/tab-supervisor.ts +12 -2
- package/src/tools/eval.ts +59 -44
- package/src/tools/fetch.ts +1 -1
- package/src/tools/gh.ts +140 -4
- package/src/tools/index.ts +12 -11
- package/src/tools/job.ts +48 -12
- package/src/tools/path-utils.ts +21 -1
- package/src/tools/read.ts +74 -31
- package/src/tools/search.ts +16 -3
- package/src/tools/todo-write.ts +1 -1
- package/src/utils/file-display-mode.ts +11 -5
- package/src/web/scrapers/mastodon.ts +1 -1
- package/src/web/scrapers/repology.ts +7 -7
- package/src/internal-urls/jobs-protocol.ts +0 -119
- package/src/task/template.ts +0 -47
- package/src/tools/bash-normalize.ts +0 -107
|
@@ -539,6 +539,10 @@ class TreeList implements Component {
|
|
|
539
539
|
const msgWithContent = msg as { content?: unknown };
|
|
540
540
|
const content = normalize(this.#extractContent(msgWithContent.content));
|
|
541
541
|
result = theme.fg("accent", "user: ") + content;
|
|
542
|
+
} else if (role === "developer") {
|
|
543
|
+
const msgWithContent = msg as { content?: unknown };
|
|
544
|
+
const content = normalize(this.#extractContent(msgWithContent.content));
|
|
545
|
+
result = theme.fg("dim", "developer: ") + theme.fg("muted", content);
|
|
542
546
|
} else if (role === "assistant") {
|
|
543
547
|
const msgWithContent = msg as { content?: unknown; stopReason?: string; errorMessage?: string };
|
|
544
548
|
const textContent = normalize(this.#extractContent(msgWithContent.content));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { INTENT_FIELD } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, ImageContent } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import { Loader, TERMINAL, Text } from "@oh-my-pi/pi-tui";
|
|
3
|
+
import { type Component, Loader, TERMINAL, Text } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { settings } from "../../config/settings";
|
|
5
5
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
6
6
|
import { ReadToolGroupComponent } from "../../modes/components/read-tool-group";
|
|
@@ -15,6 +15,8 @@ import type { ExitPlanModeDetails } from "../../tools";
|
|
|
15
15
|
|
|
16
16
|
type AgentSessionEventKind = AgentSessionEvent["type"];
|
|
17
17
|
|
|
18
|
+
const IRC_MESSAGE_VISIBLE_TTL_MS = 10_000;
|
|
19
|
+
|
|
18
20
|
type AgentSessionEventHandlers = {
|
|
19
21
|
[E in AgentSessionEventKind]: (event: Extract<AgentSessionEvent, { type: E }>) => Promise<void>;
|
|
20
22
|
};
|
|
@@ -29,6 +31,7 @@ export class EventController {
|
|
|
29
31
|
#readToolCallAssistantComponents = new Map<string, AssistantMessageComponent>();
|
|
30
32
|
#lastAssistantComponent: AssistantMessageComponent | undefined = undefined;
|
|
31
33
|
#idleCompactionTimer?: NodeJS.Timeout;
|
|
34
|
+
#ircExpiryTimers = new Map<string, NodeJS.Timeout>();
|
|
32
35
|
#handlers: AgentSessionEventHandlers;
|
|
33
36
|
|
|
34
37
|
constructor(private ctx: InteractiveModeContext) {
|
|
@@ -59,6 +62,10 @@ export class EventController {
|
|
|
59
62
|
|
|
60
63
|
dispose(): void {
|
|
61
64
|
this.#cancelIdleCompaction();
|
|
65
|
+
for (const timer of this.#ircExpiryTimers.values()) {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
}
|
|
68
|
+
this.#ircExpiryTimers.clear();
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
#resetReadGroup(): void {
|
|
@@ -222,10 +229,24 @@ export class EventController {
|
|
|
222
229
|
}
|
|
223
230
|
this.#renderedCustomMessages.add(signature);
|
|
224
231
|
this.#resetReadGroup();
|
|
225
|
-
this.ctx.addMessageToChat(event.message);
|
|
232
|
+
const components = this.ctx.addMessageToChat(event.message);
|
|
233
|
+
this.#scheduleIrcExpiry(signature, components);
|
|
226
234
|
this.ctx.ui.requestRender();
|
|
227
235
|
}
|
|
228
236
|
|
|
237
|
+
#scheduleIrcExpiry(signature: string, components: Component[]): void {
|
|
238
|
+
if (components.length === 0 || this.#ircExpiryTimers.has(signature)) return;
|
|
239
|
+
const timer = setTimeout(() => {
|
|
240
|
+
this.#ircExpiryTimers.delete(signature);
|
|
241
|
+
for (const component of components) {
|
|
242
|
+
this.ctx.chatContainer.removeChild(component);
|
|
243
|
+
}
|
|
244
|
+
this.ctx.ui.requestRender();
|
|
245
|
+
}, IRC_MESSAGE_VISIBLE_TTL_MS);
|
|
246
|
+
timer.unref?.();
|
|
247
|
+
this.#ircExpiryTimers.set(signature, timer);
|
|
248
|
+
}
|
|
249
|
+
|
|
229
250
|
async #handleNotice(event: Extract<AgentSessionEvent, { type: "notice" }>): Promise<void> {
|
|
230
251
|
const message = event.source ? `${event.source}: ${event.message}` : event.message;
|
|
231
252
|
if (event.level === "error") {
|
|
@@ -1238,12 +1238,12 @@ export class MCPCommandController {
|
|
|
1238
1238
|
? theme.fg("muted", "Connecting")
|
|
1239
1239
|
: theme.fg("warning", "Not connected yet");
|
|
1240
1240
|
this.#showMessage(
|
|
1241
|
-
["", theme.fg("success",
|
|
1241
|
+
["", theme.fg("success", `✓ Enabled "${name}"`), "", ` Status: ${status}`, ""].join("\n"),
|
|
1242
1242
|
);
|
|
1243
1243
|
} else {
|
|
1244
1244
|
await this.ctx.mcpManager?.disconnectServer(name);
|
|
1245
1245
|
await this.ctx.session.refreshMCPTools(this.ctx.mcpManager?.getTools() ?? []);
|
|
1246
|
-
this.#showMessage(["", theme.fg("success",
|
|
1246
|
+
this.#showMessage(["", theme.fg("success", `✓ Disabled "${name}"`), ""].join("\n"));
|
|
1247
1247
|
}
|
|
1248
1248
|
return;
|
|
1249
1249
|
}
|
|
@@ -1429,12 +1429,9 @@ export class MCPCommandController {
|
|
|
1429
1429
|
await this.ctx.session.refreshMCPTools(this.ctx.mcpManager.getTools());
|
|
1430
1430
|
const serverTools = this.ctx.mcpManager.getTools().filter(t => t.mcpServerName === name);
|
|
1431
1431
|
this.#showMessage(
|
|
1432
|
-
[
|
|
1433
|
-
"\n",
|
|
1434
|
-
theme.fg("success", `\u2713 Reconnected to "${name}"`),
|
|
1435
|
-
` Tools: ${serverTools.length}`,
|
|
1432
|
+
["\n", theme.fg("success", `✓ Reconnected to "${name}"`), ` Tools: ${serverTools.length}`, "\n"].join(
|
|
1436
1433
|
"\n",
|
|
1437
|
-
|
|
1434
|
+
),
|
|
1438
1435
|
);
|
|
1439
1436
|
} else {
|
|
1440
1437
|
this.ctx.showError(`Failed to reconnect to "${name}". Check server status and logs.`);
|
|
@@ -1589,8 +1586,8 @@ export class MCPCommandController {
|
|
|
1589
1586
|
hasAny = true;
|
|
1590
1587
|
|
|
1591
1588
|
lines.push(`${theme.fg("accent", name)}:`);
|
|
1592
|
-
const check = theme.fg("success", "
|
|
1593
|
-
const cross = theme.fg("dim", "
|
|
1589
|
+
const check = theme.fg("success", "✓");
|
|
1590
|
+
const cross = theme.fg("dim", "✗");
|
|
1594
1591
|
if (supportsToolsChanged) lines.push(` ${check} tools/list_changed`);
|
|
1595
1592
|
if (supportsResourcesChanged) lines.push(` ${check} resources/list_changed`);
|
|
1596
1593
|
if (supportsPromptsChanged) lines.push(` ${check} prompts/list_changed`);
|
|
@@ -1607,7 +1604,7 @@ export class MCPCommandController {
|
|
|
1607
1604
|
lines.push(` ${check} resources/subscribe ${subStatus}`);
|
|
1608
1605
|
if (enabled && subscribedUris && subscribedUris.size > 0) {
|
|
1609
1606
|
for (const uri of subscribedUris) {
|
|
1610
|
-
lines.push(` ${theme.fg("success", "
|
|
1607
|
+
lines.push(` ${theme.fg("success", "✓")} ${theme.fg("dim", uri)}`);
|
|
1611
1608
|
}
|
|
1612
1609
|
}
|
|
1613
1610
|
} else if (supportsResources) {
|
|
@@ -1502,8 +1502,8 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
1502
1502
|
return this.#uiHelpers.isKnownSlashCommand(text);
|
|
1503
1503
|
}
|
|
1504
1504
|
|
|
1505
|
-
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }):
|
|
1506
|
-
this.#uiHelpers.addMessageToChat(message, options);
|
|
1505
|
+
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): Component[] {
|
|
1506
|
+
return this.#uiHelpers.addMessageToChat(message, options);
|
|
1507
1507
|
}
|
|
1508
1508
|
|
|
1509
1509
|
renderSessionContext(
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -387,51 +387,51 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
387
387
|
"nav.back": "\uf060",
|
|
388
388
|
// Tree Connectors (same as unicode)
|
|
389
389
|
// pick: ├─ | alt: ├╴ ├╌ ╠═ ┣━
|
|
390
|
-
"tree.branch": "
|
|
390
|
+
"tree.branch": "├─",
|
|
391
391
|
// pick: └─ | alt: └╴ └╌ ╚═ ┗━
|
|
392
|
-
"tree.last": "
|
|
392
|
+
"tree.last": "└─",
|
|
393
393
|
// pick: │ | alt: ┃ ║ ▏ ▕
|
|
394
|
-
"tree.vertical": "
|
|
394
|
+
"tree.vertical": "│",
|
|
395
395
|
// pick: ─ | alt: ━ ═ ╌ ┄
|
|
396
|
-
"tree.horizontal": "
|
|
396
|
+
"tree.horizontal": "─",
|
|
397
397
|
// pick: └ | alt: ╰ ⎿ ↳
|
|
398
|
-
"tree.hook": "
|
|
398
|
+
"tree.hook": "└",
|
|
399
399
|
// Box Drawing - Rounded (same as unicode)
|
|
400
400
|
// pick: ╭ | alt: ┌ ┏ ╔
|
|
401
|
-
"boxRound.topLeft": "
|
|
401
|
+
"boxRound.topLeft": "╭",
|
|
402
402
|
// pick: ╮ | alt: ┐ ┓ ╗
|
|
403
|
-
"boxRound.topRight": "
|
|
403
|
+
"boxRound.topRight": "╮",
|
|
404
404
|
// pick: ╰ | alt: └ ┗ ╚
|
|
405
|
-
"boxRound.bottomLeft": "
|
|
405
|
+
"boxRound.bottomLeft": "╰",
|
|
406
406
|
// pick: ╯ | alt: ┘ ┛ ╝
|
|
407
|
-
"boxRound.bottomRight": "
|
|
407
|
+
"boxRound.bottomRight": "╯",
|
|
408
408
|
// pick: ─ | alt: ━ ═ ╌
|
|
409
|
-
"boxRound.horizontal": "
|
|
409
|
+
"boxRound.horizontal": "─",
|
|
410
410
|
// pick: │ | alt: ┃ ║ ▏
|
|
411
|
-
"boxRound.vertical": "
|
|
411
|
+
"boxRound.vertical": "│",
|
|
412
412
|
// Box Drawing - Sharp (same as unicode)
|
|
413
413
|
// pick: ┌ | alt: ┏ ╭ ╔
|
|
414
|
-
"boxSharp.topLeft": "
|
|
414
|
+
"boxSharp.topLeft": "┌",
|
|
415
415
|
// pick: ┐ | alt: ┓ ╮ ╗
|
|
416
|
-
"boxSharp.topRight": "
|
|
416
|
+
"boxSharp.topRight": "┐",
|
|
417
417
|
// pick: └ | alt: ┗ ╰ ╚
|
|
418
|
-
"boxSharp.bottomLeft": "
|
|
418
|
+
"boxSharp.bottomLeft": "└",
|
|
419
419
|
// pick: ┘ | alt: ┛ ╯ ╝
|
|
420
|
-
"boxSharp.bottomRight": "
|
|
420
|
+
"boxSharp.bottomRight": "┘",
|
|
421
421
|
// pick: ─ | alt: ━ ═ ╌
|
|
422
|
-
"boxSharp.horizontal": "
|
|
422
|
+
"boxSharp.horizontal": "─",
|
|
423
423
|
// pick: │ | alt: ┃ ║ ▏
|
|
424
|
-
"boxSharp.vertical": "
|
|
424
|
+
"boxSharp.vertical": "│",
|
|
425
425
|
// pick: ┼ | alt: ╋ ╬ ┿
|
|
426
|
-
"boxSharp.cross": "
|
|
426
|
+
"boxSharp.cross": "┼",
|
|
427
427
|
// pick: ┬ | alt: ╦ ┯ ┳
|
|
428
|
-
"boxSharp.teeDown": "
|
|
428
|
+
"boxSharp.teeDown": "┬",
|
|
429
429
|
// pick: ┴ | alt: ╩ ┷ ┻
|
|
430
|
-
"boxSharp.teeUp": "
|
|
430
|
+
"boxSharp.teeUp": "┴",
|
|
431
431
|
// pick: ├ | alt: ╠ ┝ ┣
|
|
432
|
-
"boxSharp.teeRight": "
|
|
432
|
+
"boxSharp.teeRight": "├",
|
|
433
433
|
// pick: ┤ | alt: ╣ ┥ ┫
|
|
434
|
-
"boxSharp.teeLeft": "
|
|
434
|
+
"boxSharp.teeLeft": "┤",
|
|
435
435
|
// Separators - Nerd Font specific
|
|
436
436
|
// pick: | alt:
|
|
437
437
|
"sep.powerline": "\ue0b0",
|
|
@@ -446,7 +446,7 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
446
446
|
// pick: | alt:
|
|
447
447
|
"sep.powerlineThinRight": "\ue0b3",
|
|
448
448
|
// pick: █ | alt: ▓ ▒ ░ ▉ ▌
|
|
449
|
-
"sep.block": "
|
|
449
|
+
"sep.block": "█",
|
|
450
450
|
// pick: space | alt: ␠ ·
|
|
451
451
|
"sep.space": " ",
|
|
452
452
|
// pick: > | alt: › » ▸
|
|
@@ -454,7 +454,7 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
454
454
|
// pick: < | alt: ‹ « ◂
|
|
455
455
|
"sep.asciiRight": "<",
|
|
456
456
|
// pick: · | alt: • ⋅
|
|
457
|
-
"sep.dot": "
|
|
457
|
+
"sep.dot": " · ",
|
|
458
458
|
// pick: | alt: / ∕ ⁄
|
|
459
459
|
"sep.slash": "\ue0bb",
|
|
460
460
|
// pick: | alt: │ ┃ |
|
|
@@ -545,16 +545,16 @@ const NERD_SYMBOLS: SymbolMap = {
|
|
|
545
545
|
// pick: | alt: •
|
|
546
546
|
"format.bullet": "\uf111",
|
|
547
547
|
// pick: – | alt: — ― -
|
|
548
|
-
"format.dash": "
|
|
548
|
+
"format.dash": "–",
|
|
549
549
|
// pick: ⟨ | alt: [ ⟦
|
|
550
550
|
"format.bracketLeft": "⟨",
|
|
551
551
|
// pick: ⟩ | alt: ] ⟧
|
|
552
552
|
"format.bracketRight": "⟩",
|
|
553
553
|
// Markdown-specific
|
|
554
554
|
// pick: │ | alt: ┃ ║
|
|
555
|
-
"md.quoteBorder": "
|
|
555
|
+
"md.quoteBorder": "│",
|
|
556
556
|
// pick: ─ | alt: ━ ═
|
|
557
|
-
"md.hrChar": "
|
|
557
|
+
"md.hrChar": "─",
|
|
558
558
|
// pick: | alt: •
|
|
559
559
|
"md.bullet": "\uf111",
|
|
560
560
|
// Language icons (nerd font devicons)
|
package/src/modes/types.ts
CHANGED
|
@@ -170,7 +170,7 @@ export interface InteractiveModeContext {
|
|
|
170
170
|
*/
|
|
171
171
|
withLocalSubmission<T>(text: string, fn: () => Promise<T>, options?: { imageCount?: number }): Promise<T>;
|
|
172
172
|
isKnownSlashCommand(text: string): boolean;
|
|
173
|
-
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }):
|
|
173
|
+
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): Component[];
|
|
174
174
|
renderSessionContext(
|
|
175
175
|
sessionContext: SessionContext,
|
|
176
176
|
options?: { updateFooter?: boolean; populateHistory?: boolean },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { AssistantMessage, ImageContent, Message } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import { Spacer, Text, TruncatedText } from "@oh-my-pi/pi-tui";
|
|
3
|
+
import { type Component, Spacer, Text, TruncatedText } from "@oh-my-pi/pi-tui";
|
|
4
4
|
import { settings } from "../../config/settings";
|
|
5
5
|
import { AssistantMessageComponent } from "../../modes/components/assistant-message";
|
|
6
6
|
import { BashExecutionComponent } from "../../modes/components/bash-execution";
|
|
@@ -70,7 +70,7 @@ export class UiHelpers {
|
|
|
70
70
|
this.ctx.ui.requestRender();
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }):
|
|
73
|
+
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): Component[] {
|
|
74
74
|
switch (message.role) {
|
|
75
75
|
case "bashExecution": {
|
|
76
76
|
const component = new BashExecutionComponent(message.command, this.ctx.ui, message.excludeFromContext);
|
|
@@ -147,26 +147,30 @@ export class UiHelpers {
|
|
|
147
147
|
if (message.customType === "irc:incoming") {
|
|
148
148
|
const peer = details?.from ?? "?";
|
|
149
149
|
body = details?.message ?? "";
|
|
150
|
-
arrow =
|
|
150
|
+
arrow = `⇦ ${peer}`;
|
|
151
151
|
} else if (message.customType === "irc:autoreply") {
|
|
152
152
|
const peer = details?.to ?? "?";
|
|
153
153
|
body = details?.reply ?? "";
|
|
154
|
-
arrow =
|
|
154
|
+
arrow = `⇨ ${peer}`;
|
|
155
155
|
} else {
|
|
156
156
|
const from = details?.from ?? "?";
|
|
157
157
|
const to = details?.to ?? "?";
|
|
158
158
|
body = details?.body ?? "";
|
|
159
|
-
|
|
160
|
-
arrow = `${from} \u21e8 ${to}${suffix}`;
|
|
159
|
+
arrow = `${from} ⇨ ${to}`;
|
|
161
160
|
}
|
|
161
|
+
const components: Component[] = [];
|
|
162
162
|
const header = `${theme.fg("accent", `[IRC] ${arrow}`)}`;
|
|
163
|
-
|
|
163
|
+
const headerComponent = new Text(header, 1, 0);
|
|
164
|
+
this.ctx.chatContainer.addChild(headerComponent);
|
|
165
|
+
components.push(headerComponent);
|
|
164
166
|
if (body) {
|
|
165
167
|
for (const line of body.split("\n")) {
|
|
166
|
-
|
|
168
|
+
const lineComponent = new Text(theme.fg("muted", ` ${line}`), 0, 0);
|
|
169
|
+
this.ctx.chatContainer.addChild(lineComponent);
|
|
170
|
+
components.push(lineComponent);
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
|
-
|
|
173
|
+
return components;
|
|
170
174
|
}
|
|
171
175
|
const renderer = this.ctx.session.extensionRunner?.getMessageRenderer(message.customType);
|
|
172
176
|
// Both HookMessage and CustomMessage have the same structure, cast for compatibility
|
|
@@ -240,6 +244,7 @@ export class UiHelpers {
|
|
|
240
244
|
const _exhaustive: never = message;
|
|
241
245
|
}
|
|
242
246
|
}
|
|
247
|
+
return [];
|
|
243
248
|
}
|
|
244
249
|
|
|
245
250
|
/**
|
|
@@ -26,6 +26,7 @@ You decompose, dispatch, verify, and iterate. You do **not** edit code. Every fi
|
|
|
26
26
|
6. **Commit policy.** If the task asks for commits or the repo workflow expects them, commit after each green phase with a focused message. Never commit a red tree. Never commit work the user did not ask to commit.
|
|
27
27
|
7. **Respawn, do not absorb.** If a subagent returns incomplete or wrong work, spawn a corrective subagent with the specific gap — do not silently fix it yourself.
|
|
28
28
|
8. **No scope creep, no scope shrink.** Do not add work the user did not ask for. Do not relabel unfinished items as "follow-up", "v1", or "MVP" to imply completion.
|
|
29
|
+
9. **Subagents do not verify, lint, or format.** Every `task` assignment **MUST** instruct the subagent to skip all gates and formatters. Their job is the edit only. You — the orchestrator — run verification and formatting **once** at the end of the phase across the union of changed files. Avoids redundant runs and racing formatter passes.
|
|
29
30
|
</rules>
|
|
30
31
|
|
|
31
32
|
<workflow>
|
|
@@ -57,8 +57,6 @@ Rules are local constraints. You **MUST** read `rule://<name>` when working in t
|
|
|
57
57
|
{{/list}}
|
|
58
58
|
</rules>
|
|
59
59
|
{{/if}}
|
|
60
|
-
Current date: {{date}}
|
|
61
|
-
Current working directory: {{cwd}}
|
|
62
60
|
{{#if secretsEnabled}}
|
|
63
61
|
<redacted-content>
|
|
64
62
|
Some values in tool output are redacted for security. They appear as `#XXXX#` tokens (4 uppercase-alphanumeric characters wrapped in `#`). These are **not errors** — they are intentional placeholders for sensitive values (API keys, passwords, tokens). Treat them as opaque strings. Do not attempt to decode, fix, or report them as problems.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
[PROJECT]
|
|
1
2
|
<workstation>
|
|
2
3
|
{{#list environment prefix="- " join="\n"}}{{label}}: {{value}}{{/list}}
|
|
3
4
|
</workstation>
|
|
@@ -31,6 +32,15 @@ Working directory layout (sorted by mtime, recent first; depth ≤ 3):
|
|
|
31
32
|
</workspace-tree>
|
|
32
33
|
{{/if}}
|
|
33
34
|
|
|
35
|
+
Today is {{date}}, and the current working directory is '{{cwd}}'.
|
|
36
|
+
|
|
37
|
+
<critical>
|
|
38
|
+
- Each response **MUST** advance the task. There is no stopping condition other than completion.
|
|
39
|
+
- You **MUST** default to informed action; do not ask for confirmation when tools or repo context can answer.
|
|
40
|
+
- You **MUST** verify the effect of significant behavioral changes before yielding: run the specific test, command, or scenario that covers your change.
|
|
41
|
+
</critical>
|
|
42
|
+
|
|
34
43
|
{{#if appendPrompt}}
|
|
35
44
|
{{appendPrompt}}
|
|
36
45
|
{{/if}}
|
|
46
|
+
[/PROJECT]
|
|
@@ -1,31 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
{{SECTION_SEPARATOR "Acting as"}}
|
|
1
|
+
[ROLE]
|
|
4
2
|
{{agent}}
|
|
3
|
+
[/ROLE]
|
|
4
|
+
|
|
5
|
+
{{#if context}}
|
|
6
|
+
[CONTEXT]
|
|
7
|
+
{{context}}
|
|
8
|
+
[/CONTEXT]
|
|
9
|
+
{{/if}}
|
|
10
|
+
|
|
11
|
+
[COOP]
|
|
12
|
+
You are operating on a piece of work assigned to you by the main agent.
|
|
5
13
|
|
|
6
|
-
{{SECTION_SEPARATOR "Job"}}
|
|
7
|
-
You are operating on a delegated sub-task.
|
|
8
14
|
{{#if worktree}}
|
|
15
|
+
# Working Tree
|
|
9
16
|
You are working in an isolated working tree at `{{worktree}}` for this sub-task.
|
|
10
17
|
You **MUST NOT** modify files outside this tree or in the original repository.
|
|
11
18
|
{{/if}}
|
|
12
19
|
|
|
13
20
|
{{#if contextFile}}
|
|
21
|
+
# Conversation Context
|
|
14
22
|
If you need additional information, you can find your conversation with the user in {{contextFile}} (`tail` or `grep` relevant terms).
|
|
15
23
|
{{/if}}
|
|
16
24
|
|
|
17
25
|
{{#if ircPeers}}
|
|
18
|
-
|
|
26
|
+
# IRC Peers
|
|
19
27
|
You can reach other live agents via the `irc` tool. Your id is `{{ircSelfId}}`. Currently visible peers:
|
|
20
28
|
{{ircPeers}}
|
|
21
29
|
|
|
22
30
|
Use `irc` only when you need a quick answer from a peer; do not use it for long-form content. Address peers by id or use `"all"` to broadcast.
|
|
23
31
|
{{/if}}
|
|
32
|
+
[/COOP]
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
[COMPLETION]
|
|
26
35
|
No TODO tracking, no progress updates. Execute, call `yield`, done.
|
|
27
36
|
|
|
28
|
-
|
|
37
|
+
While work remains, always continue with another tool call — investigate, edit, run, verify. Save narrative for the final `yield` payload.
|
|
29
38
|
|
|
30
39
|
When finished, you **MUST** call `yield` exactly once. This is like writing to a ticket: provide what is required and close it.
|
|
31
40
|
|
|
@@ -38,8 +47,8 @@ Your result **MUST** match this TypeScript interface:
|
|
|
38
47
|
```
|
|
39
48
|
{{/if}}
|
|
40
49
|
|
|
41
|
-
{{SECTION_SEPARATOR "Giving Up"}}
|
|
42
50
|
Giving up is a last resort. If truly blocked, you **MUST** call `yield` exactly once with `result.error` describing what you tried and the exact blocker.
|
|
43
51
|
You **MUST NOT** give up due to uncertainty, missing information obtainable via tools or repo context, or needing a design decision you can derive yourself.
|
|
44
52
|
|
|
45
53
|
You **MUST** keep going until this ticket is closed. This matters.
|
|
54
|
+
[/COMPLETION]
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
{{SECTION_SEPARATOR "Background"}}
|
|
3
|
-
<context>
|
|
4
|
-
{{context}}
|
|
5
|
-
</context>
|
|
6
|
-
{{/if}}
|
|
1
|
+
Complete the assignment below, thoroughly:
|
|
7
2
|
|
|
8
|
-
{{SECTION_SEPARATOR "Task"}}
|
|
9
|
-
Your assignment is below. Your work begins now.
|
|
10
|
-
<goal>
|
|
11
3
|
{{assignment}}
|
|
12
|
-
</goal>
|