gsd-pi 2.76.0-dev.82e249f7b → 2.76.0-dev.fe143342a
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/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +66 -4
- package/dist/resources/extensions/gsd/auto-start.js +27 -14
- package/dist/resources/extensions/gsd/auto.js +11 -11
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +35 -0
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/error-classifier.js +10 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gsd-db.js +62 -4
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +6 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +13 -3
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +1 -1
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +84 -43
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +9 -5
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +25 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +36 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +9 -5
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +67 -4
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +137 -2
- package/src/resources/extensions/gsd/auto-start.ts +28 -15
- package/src/resources/extensions/gsd/auto.ts +11 -11
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +36 -0
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/error-classifier.ts +10 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gsd-db.ts +68 -4
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/key-manager.ts +6 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +13 -3
- package/src/resources/extensions/gsd/preferences-types.ts +38 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +1 -1
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +2 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- /package/dist/web/standalone/.next/static/{ecSsu49rxxcpbNmVP4mLD → n21VtX2hZlkpdEUO_nU4z}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ecSsu49rxxcpbNmVP4mLD → n21VtX2hZlkpdEUO_nU4z}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-frame.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAwB,MAAM,gBAAgB,CAAC;AAIvE,SAAS,mBAAmB,CAAC,KAAe;IAC3C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,OAAO,KAAK,GAAG,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,EAAE,CAAC;IAChE,OAAO,GAAG,GAAG,KAAK,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,EAAE,CAAC;IAChE,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,eAAe,CAC9B,YAAsB,EACtB,KAAa,EACb,IAMC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACvC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB;IACnE,MAAM,WAAW,GAChB,IAAI,CAAC,IAAI,KAAK,MAAM;QACnB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"chat-frame.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/chat-frame.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@gsd/pi-tui\";\nimport { theme } from \"../theme/theme.js\";\nimport { formatTimestamp, type TimestampFormat } from \"./timestamp.js\";\n\ntype FrameTone = \"assistant\" | \"user\" | \"compaction\" | \"skill\";\n\nfunction trimOuterBlankLines(lines: string[]): string[] {\n\tlet start = 0;\n\tlet end = lines.length;\n\twhile (start < end && lines[start].trim().length === 0) start++;\n\twhile (end > start && lines[end - 1].trim().length === 0) end--;\n\treturn lines.slice(start, end);\n}\n\nexport function renderChatFrame(\n\tcontentLines: string[],\n\twidth: number,\n\topts: {\n\t\tlabel: string;\n\t\ttone: FrameTone;\n\t\ttimestamp?: number;\n\t\ttimestampFormat: TimestampFormat;\n\t\tshowTimestamp?: boolean;\n\t},\n): string[] {\n\tconst outerWidth = Math.max(20, width);\n\tconst contentWidth = Math.max(1, outerWidth - 2); // \"│ \" + content\n\tconst isPurple = opts.tone === \"compaction\" || opts.tone === \"skill\";\n\tconst borderColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"border\"\n\t\t\t: isPurple\n\t\t\t\t? \"customMessageLabel\"\n\t\t\t\t: \"borderAccent\";\n\tconst borderMuted = isPurple ? \"customMessageLabel\" : \"borderMuted\";\n\tconst border = (s: string) => theme.fg(borderColor, s);\n\tconst leftRaw = `• ${opts.label}`;\n\tconst rightRaw =\n\t\topts.showTimestamp === false || !opts.timestamp\n\t\t\t? \"\"\n\t\t\t: formatTimestamp(opts.timestamp, opts.timestampFormat);\n\n\tconst leftBudget = rightRaw\n\t\t? Math.max(1, outerWidth - visibleWidth(rightRaw) - 1)\n\t\t: outerWidth;\n\tconst left = truncateToWidth(leftRaw, leftBudget, \"\");\n\tconst labelColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"border\"\n\t\t\t: isPurple\n\t\t\t\t? \"customMessageLabel\"\n\t\t\t\t: \"borderAccent\";\n\tconst dashIdx = left.indexOf(\" - \");\n\tconst leftStyled =\n\t\tdashIdx >= 0\n\t\t\t? theme.fg(labelColor, theme.bold(left.slice(0, dashIdx))) +\n\t\t\t\ttheme.fg(\"dim\", left.slice(dashIdx))\n\t\t\t: theme.fg(labelColor, theme.bold(left));\n\tconst rightStyled = rightRaw ? theme.fg(\"dim\", rightRaw) : \"\";\n\tconst gap =\n\t\trightRaw.length > 0\n\t\t\t? Math.max(\n\t\t\t\t\t1,\n\t\t\t\t\touterWidth - visibleWidth(leftStyled) - visibleWidth(rightStyled),\n\t\t\t\t)\n\t\t\t: Math.max(0, outerWidth - visibleWidth(leftStyled));\n\tconst headerRow = `${leftStyled}${\" \".repeat(gap)}${rightStyled}`;\n\tconst headerPad = Math.max(0, outerWidth - visibleWidth(headerRow));\n\n\tconst sourceLines = trimOuterBlankLines(contentLines);\n\tconst bodyColor =\n\t\topts.tone === \"user\"\n\t\t\t? \"userMessageText\"\n\t\t\t: isPurple\n\t\t\t\t? \"customMessageText\"\n\t\t\t\t: \"assistantMessageText\";\n\tconst bodyLines = (sourceLines.length > 0 ? sourceLines : [\"\"]).map((line) => {\n\t\tconst clipped = truncateToWidth(line, contentWidth, \"\");\n\t\treturn border(\"│ \") + theme.fg(bodyColor, clipped);\n\t});\n\n\treturn [\n\t\ttheme.fg(borderMuted, \"─\".repeat(outerWidth)),\n\t\theaderRow + \" \".repeat(headerPad),\n\t\t...bodyLines,\n\t];\n}\n"]}
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Container, type MarkdownTheme } from "@gsd/pi-tui";
|
|
2
2
|
import type { ParsedSkillBlock } from "../../../core/agent-session.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Renders a skill invocation in the shared chat-frame style (top rule,
|
|
5
|
+
* `• skill - <name>` header, `│ ` body margin) with purple border/label
|
|
6
|
+
* matching compaction so it visually aligns with user/assistant messages.
|
|
7
7
|
*/
|
|
8
|
-
export declare class SkillInvocationMessageComponent extends
|
|
8
|
+
export declare class SkillInvocationMessageComponent extends Container {
|
|
9
9
|
private expanded;
|
|
10
10
|
private skillBlock;
|
|
11
11
|
private markdownTheme;
|
|
12
12
|
constructor(skillBlock: ParsedSkillBlock, markdownTheme?: MarkdownTheme);
|
|
13
13
|
setExpanded(expanded: boolean): void;
|
|
14
14
|
invalidate(): void;
|
|
15
|
-
private
|
|
15
|
+
private rebuild;
|
|
16
|
+
render(width: number): string[];
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=skill-invocation-message.d.ts.map
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-invocation-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"skill-invocation-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAQ,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAKvE;;;;GAIG;AACH,qBAAa,+BAAgC,SAAQ,SAAS;IAC7D,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,UAAU,EAAE,gBAAgB,EAAE,aAAa,GAAE,aAAkC;IAO3F,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAO3B,UAAU,IAAI,IAAI;IAK3B,OAAO,CAAC,OAAO;IAoBN,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAYxC"}
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js
CHANGED
|
@@ -1,45 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
// GSD / pi-coding-agent — Skill invocation message component
|
|
2
|
+
import { Container, Markdown, Text } from "@gsd/pi-tui";
|
|
2
3
|
import { getMarkdownTheme, theme } from "../theme/theme.js";
|
|
4
|
+
import { renderChatFrame } from "./chat-frame.js";
|
|
3
5
|
import { editorKey } from "./keybinding-hints.js";
|
|
4
6
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Renders a skill invocation in the shared chat-frame style (top rule,
|
|
8
|
+
* `• skill - <name>` header, `│ ` body margin) with purple border/label
|
|
9
|
+
* matching compaction so it visually aligns with user/assistant messages.
|
|
8
10
|
*/
|
|
9
|
-
export class SkillInvocationMessageComponent extends
|
|
11
|
+
export class SkillInvocationMessageComponent extends Container {
|
|
10
12
|
constructor(skillBlock, markdownTheme = getMarkdownTheme()) {
|
|
11
|
-
super(
|
|
13
|
+
super();
|
|
12
14
|
this.expanded = false;
|
|
13
15
|
this.skillBlock = skillBlock;
|
|
14
16
|
this.markdownTheme = markdownTheme;
|
|
15
|
-
this.
|
|
17
|
+
this.rebuild();
|
|
16
18
|
}
|
|
17
19
|
setExpanded(expanded) {
|
|
18
|
-
this.expanded
|
|
19
|
-
|
|
20
|
+
if (this.expanded !== expanded) {
|
|
21
|
+
this.expanded = expanded;
|
|
22
|
+
this.rebuild();
|
|
23
|
+
}
|
|
20
24
|
}
|
|
21
25
|
invalidate() {
|
|
22
26
|
super.invalidate();
|
|
23
|
-
this.
|
|
27
|
+
this.rebuild();
|
|
24
28
|
}
|
|
25
|
-
|
|
29
|
+
rebuild() {
|
|
26
30
|
this.clear();
|
|
27
31
|
if (this.expanded) {
|
|
28
|
-
|
|
29
|
-
const label = theme.fg("customMessageLabel", theme.bold("[skill]"));
|
|
30
|
-
this.addChild(new Text(label, 0, 0));
|
|
31
|
-
const header = `**${this.skillBlock.name}**\n\n`;
|
|
32
|
-
this.addChild(new Markdown(header + this.skillBlock.content, 0, 0, this.markdownTheme, {
|
|
32
|
+
this.addChild(new Markdown(this.skillBlock.content, 0, 0, this.markdownTheme, {
|
|
33
33
|
color: (text) => theme.fg("customMessageText", text),
|
|
34
34
|
}));
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
|
|
38
|
-
const line = theme.fg("customMessageLabel", theme.bold("[skill]") + " ") +
|
|
39
|
-
theme.fg("customMessageText", this.skillBlock.name) +
|
|
40
|
-
theme.fg("dim", ` (${editorKey("expandTools")} to expand)`);
|
|
41
|
-
this.addChild(new Text(line, 0, 0));
|
|
37
|
+
this.addChild(new Text(theme.fg("dim", `(${editorKey("expandTools")} to expand)`), 0, 0));
|
|
42
38
|
}
|
|
43
39
|
}
|
|
40
|
+
render(width) {
|
|
41
|
+
const frameWidth = Math.max(20, width);
|
|
42
|
+
const contentWidth = Math.max(1, frameWidth - 4);
|
|
43
|
+
const lines = super.render(contentWidth);
|
|
44
|
+
const framed = renderChatFrame(lines, frameWidth, {
|
|
45
|
+
label: `skill - ${this.skillBlock.name}`,
|
|
46
|
+
tone: "skill",
|
|
47
|
+
timestampFormat: "date-time-iso",
|
|
48
|
+
showTimestamp: false,
|
|
49
|
+
});
|
|
50
|
+
return framed.length > 0 ? ["", ...framed] : framed;
|
|
51
|
+
}
|
|
44
52
|
}
|
|
45
53
|
//# sourceMappingURL=skill-invocation-message.js.map
|
package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-invocation-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"skill-invocation-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/skill-invocation-message.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAsB,IAAI,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAElD;;;;GAIG;AACH,MAAM,OAAO,+BAAgC,SAAQ,SAAS;IAK7D,YAAY,UAA4B,EAAE,gBAA+B,gBAAgB,EAAE;QAC1F,KAAK,EAAE,CAAC;QALD,aAAQ,GAAG,KAAK,CAAC;QAMxB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,QAAiB;QAC5B,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACzB,IAAI,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC;IACF,CAAC;IAEQ,UAAU;QAClB,KAAK,CAAC,UAAU,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAEO,OAAO;QACd,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CACZ,IAAI,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE;gBAC/D,KAAK,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,mBAAmB,EAAE,IAAI,CAAC;aAC5D,CAAC,CACF,CAAC;QACH,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,QAAQ,CACZ,IAAI,IAAI,CACP,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC,EAC1D,CAAC,EACD,CAAC,CACD,CACD,CAAC;QACH,CAAC;IACF,CAAC;IAEQ,MAAM,CAAC,KAAa;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE;YACjD,KAAK,EAAE,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;YACxC,IAAI,EAAE,OAAO;YACb,eAAe,EAAE,eAAe;YAChC,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACrD,CAAC;CACD","sourcesContent":["// GSD / pi-coding-agent — Skill invocation message component\nimport { Container, Markdown, type MarkdownTheme, Text } from \"@gsd/pi-tui\";\nimport type { ParsedSkillBlock } from \"../../../core/agent-session.js\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.js\";\nimport { renderChatFrame } from \"./chat-frame.js\";\nimport { editorKey } from \"./keybinding-hints.js\";\n\n/**\n * Renders a skill invocation in the shared chat-frame style (top rule,\n * `• skill - <name>` header, `│ ` body margin) with purple border/label\n * matching compaction so it visually aligns with user/assistant messages.\n */\nexport class SkillInvocationMessageComponent extends Container {\n\tprivate expanded = false;\n\tprivate skillBlock: ParsedSkillBlock;\n\tprivate markdownTheme: MarkdownTheme;\n\n\tconstructor(skillBlock: ParsedSkillBlock, markdownTheme: MarkdownTheme = getMarkdownTheme()) {\n\t\tsuper();\n\t\tthis.skillBlock = skillBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.rebuild();\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tif (this.expanded !== expanded) {\n\t\t\tthis.expanded = expanded;\n\t\t\tthis.rebuild();\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.rebuild();\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\n\t\tif (this.expanded) {\n\t\t\tthis.addChild(\n\t\t\t\tnew Markdown(this.skillBlock.content, 0, 0, this.markdownTheme, {\n\t\t\t\t\tcolor: (text: string) => theme.fg(\"customMessageText\", text),\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tthis.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\ttheme.fg(\"dim\", `(${editorKey(\"expandTools\")} to expand)`),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst frameWidth = Math.max(20, width);\n\t\tconst contentWidth = Math.max(1, frameWidth - 4);\n\t\tconst lines = super.render(contentWidth);\n\t\tconst framed = renderChatFrame(lines, frameWidth, {\n\t\t\tlabel: `skill - ${this.skillBlock.name}`,\n\t\t\ttone: \"skill\",\n\t\t\ttimestampFormat: \"date-time-iso\",\n\t\t\tshowTimestamp: false,\n\t\t});\n\t\treturn framed.length > 0 ? [\"\", ...framed] : framed;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// pi-coding-agent — unit tests for session-log secret redaction
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { describe, it } from "node:test";
|
|
5
|
+
|
|
6
|
+
import { redactSecrets } from "./redact-secrets.js";
|
|
7
|
+
|
|
8
|
+
describe("redactSecrets", () => {
|
|
9
|
+
it("is a no-op on plain text with no secret markers", () => {
|
|
10
|
+
const input = "Hello world — this is just some prose with numbers 12345 and dashes - - -.";
|
|
11
|
+
assert.equal(redactSecrets(input), input);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("redacts Anthropic keys before generic openai sk- pattern", () => {
|
|
15
|
+
const out = redactSecrets("key=sk-ant-api03-abcDEF1234567890abcDEF1234567890");
|
|
16
|
+
assert.equal(out, "key=[REDACTED:anthropic]");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("redacts legacy OpenAI sk- keys", () => {
|
|
20
|
+
const out = redactSecrets("OPENAI_API_KEY=sk-abcDEF1234567890abcDEF12");
|
|
21
|
+
assert.equal(out, "OPENAI_API_KEY=[REDACTED:openai]");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("redacts OpenAI project sk-proj- keys with hyphens/underscores in body", () => {
|
|
25
|
+
const out = redactSecrets("OPENAI_API_KEY=sk-proj-AbCd_1234-EfGh_5678-IjKl_9012");
|
|
26
|
+
assert.equal(out, "OPENAI_API_KEY=[REDACTED:openai]");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("redacts OpenAI admin sk-admin- keys", () => {
|
|
30
|
+
const out = redactSecrets("OPENAI_ADMIN_KEY=sk-admin-AbCd1234EfGh5678IjKl9012");
|
|
31
|
+
assert.equal(out, "OPENAI_ADMIN_KEY=[REDACTED:openai]");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("redacts LlamaCloud llx- keys", () => {
|
|
35
|
+
const out = redactSecrets("LLAMA_CLOUD_API_KEY=llx-abcDEF1234567890abcDEF1234567890");
|
|
36
|
+
assert.equal(out, "LLAMA_CLOUD_API_KEY=[REDACTED:llamacloud]");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("redacts AWS access key ids", () => {
|
|
40
|
+
const out = redactSecrets("aws_access_key_id = AKIAIOSFODNN7EXAMPLE");
|
|
41
|
+
assert.equal(out, "aws_access_key_id = [REDACTED:aws-access-key]");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("redacts GitHub personal/oauth/app/server/refresh tokens", () => {
|
|
45
|
+
const out = redactSecrets("token=ghp_abcdefghijklmnopqrstuvwxyz0123456789");
|
|
46
|
+
assert.equal(out, "token=[REDACTED:github-token]");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("redacts Slack tokens", () => {
|
|
50
|
+
const out = redactSecrets("slack=xoxb-1234567890-abcdefghij");
|
|
51
|
+
assert.equal(out, "slack=[REDACTED:slack-token]");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("redacts Google API keys", () => {
|
|
55
|
+
// Google API keys are exactly AIza + 35 chars (39 total).
|
|
56
|
+
const out = redactSecrets("key=AIzaSyA-1234567890abcdefghijklmnopqrstu");
|
|
57
|
+
assert.equal(out, "key=[REDACTED:google-api-key]");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("redacts PEM private key blocks across newlines", () => {
|
|
61
|
+
const pem = [
|
|
62
|
+
"-----BEGIN RSA PRIVATE KEY-----",
|
|
63
|
+
"MIIEowIBAAKCAQEAabcDEF...",
|
|
64
|
+
"morekeymaterial==",
|
|
65
|
+
"-----END RSA PRIVATE KEY-----",
|
|
66
|
+
].join("\n");
|
|
67
|
+
const out = redactSecrets(`before\n${pem}\nafter`);
|
|
68
|
+
assert.equal(out, "before\n[REDACTED:pem-private-key]\nafter");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("redacts multiple secrets in the same string", () => {
|
|
72
|
+
const out = redactSecrets(
|
|
73
|
+
"AZURE_CLIENT_SECRET: also llx-abcDEF1234567890abcDEF1234567890 and AKIAIOSFODNN7EXAMPLE",
|
|
74
|
+
);
|
|
75
|
+
assert.equal(
|
|
76
|
+
out,
|
|
77
|
+
"AZURE_CLIENT_SECRET: also [REDACTED:llamacloud] and [REDACTED:aws-access-key]",
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("does not redact short strings that merely contain sk- prose", () => {
|
|
82
|
+
// "sk-foo" is too short to match the openai pattern — must be 20+ chars.
|
|
83
|
+
const input = "the sk- prefix isn't always a secret";
|
|
84
|
+
assert.equal(redactSecrets(input), input);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// pi-coding-agent — secret redaction for session log persistence
|
|
2
|
+
//
|
|
3
|
+
// Called by prepareForPersistence() in session-manager.ts on every string
|
|
4
|
+
// before it lands in the JSONL transcript. Replaces well-known secret shapes
|
|
5
|
+
// with [REDACTED:<kind>] placeholders so credentials pasted by the user or
|
|
6
|
+
// read from .env-style files never persist to disk.
|
|
7
|
+
//
|
|
8
|
+
// Pattern selection bias: high-specificity shapes only. Loose patterns
|
|
9
|
+
// (e.g. FOO_SECRET=...) produce too many false positives in docs and code
|
|
10
|
+
// samples and are intentionally excluded.
|
|
11
|
+
|
|
12
|
+
interface SecretPattern {
|
|
13
|
+
kind: string;
|
|
14
|
+
regex: RegExp;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Order matters: more-specific patterns first (sk-ant- before generic sk-).
|
|
18
|
+
const PATTERNS: readonly SecretPattern[] = [
|
|
19
|
+
{ kind: "anthropic", regex: /sk-ant-[A-Za-z0-9_-]{20,}/g },
|
|
20
|
+
{ kind: "llamacloud", regex: /llx-[A-Za-z0-9_-]{20,}/g },
|
|
21
|
+
// Covers all three official OpenAI key shapes: legacy `sk-…`, project `sk-proj-…`,
|
|
22
|
+
// and admin `sk-admin-…`. Hyphens and underscores appear inside real project keys
|
|
23
|
+
// so the remainder class must allow them. `sk-ant-` is matched earlier by the
|
|
24
|
+
// anthropic pattern and already replaced by the time this runs.
|
|
25
|
+
{ kind: "openai", regex: /sk-(?:proj-|admin-)?[A-Za-z0-9_-]{20,}/g },
|
|
26
|
+
{ kind: "aws-access-key", regex: /\b(?:AKIA|ASIA|AROA)[0-9A-Z]{16}\b/g },
|
|
27
|
+
{ kind: "github-token", regex: /\bgh[pousr]_[A-Za-z0-9]{30,}\b/g },
|
|
28
|
+
{ kind: "slack-token", regex: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
|
|
29
|
+
{ kind: "google-api-key", regex: /\bAIza[0-9A-Za-z_-]{35}\b/g },
|
|
30
|
+
{
|
|
31
|
+
kind: "pem-private-key",
|
|
32
|
+
regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
33
|
+
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export function redactSecrets(input: string): string {
|
|
37
|
+
// Short-circuit: skip regex work on strings with no plausible secret markers.
|
|
38
|
+
// Cheap heuristic — if none of these substrings are present, no pattern can match.
|
|
39
|
+
if (
|
|
40
|
+
!input.includes("sk-") &&
|
|
41
|
+
!input.includes("llx-") &&
|
|
42
|
+
!input.includes("AKIA") &&
|
|
43
|
+
!input.includes("ASIA") &&
|
|
44
|
+
!input.includes("AROA") &&
|
|
45
|
+
!input.includes("gh") &&
|
|
46
|
+
!input.includes("xox") &&
|
|
47
|
+
!input.includes("AIza") &&
|
|
48
|
+
!input.includes("PRIVATE KEY")
|
|
49
|
+
) {
|
|
50
|
+
return input;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let out = input;
|
|
54
|
+
for (const { kind, regex } of PATTERNS) {
|
|
55
|
+
out = out.replace(regex, `[REDACTED:${kind}]`);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { describe, it, afterEach } from "node:test";
|
|
3
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
|
|
@@ -63,3 +63,38 @@ describe("SessionManager usage totals", () => {
|
|
|
63
63
|
});
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
|
+
|
|
67
|
+
describe("SessionManager secret redaction on persistence", () => {
|
|
68
|
+
let dir: string;
|
|
69
|
+
|
|
70
|
+
afterEach(() => {
|
|
71
|
+
if (dir) {
|
|
72
|
+
rmSync(dir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("scrubs known secret shapes from JSONL on disk", () => {
|
|
77
|
+
dir = mkdtempSync(join(tmpdir(), "gsd-session-redact-test-"));
|
|
78
|
+
const manager = SessionManager.create(dir, dir);
|
|
79
|
+
|
|
80
|
+
const leakedKey = "llx-abcDEF1234567890abcDEF1234567890";
|
|
81
|
+
manager.appendMessage({
|
|
82
|
+
role: "user",
|
|
83
|
+
content: [{ type: "text", text: `here is my key: ${leakedKey}` }],
|
|
84
|
+
} as any);
|
|
85
|
+
// Persistence is gated on an assistant message being present.
|
|
86
|
+
manager.appendMessage(makeAssistantMessage(1, 1, 0, 0, 0));
|
|
87
|
+
|
|
88
|
+
const sessionFile = manager.getSessionFile();
|
|
89
|
+
assert.ok(sessionFile, "session file should be set");
|
|
90
|
+
const contents = readFileSync(sessionFile!, "utf8");
|
|
91
|
+
assert.ok(
|
|
92
|
+
!contents.includes(leakedKey),
|
|
93
|
+
"raw secret must not appear in persisted JSONL",
|
|
94
|
+
);
|
|
95
|
+
assert.ok(
|
|
96
|
+
contents.includes("[REDACTED:llamacloud]"),
|
|
97
|
+
"redaction placeholder must appear in persisted JSONL",
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
createCustomMessage,
|
|
27
27
|
} from "./messages.js";
|
|
28
28
|
import { BlobStore, externalizeImageData, isBlobRef, resolveImageData } from "./blob-store.js";
|
|
29
|
+
import { redactSecrets } from "./redact-secrets.js";
|
|
29
30
|
|
|
30
31
|
/** Inline concurrency limiter to cap parallel async operations. */
|
|
31
32
|
function pLimit(concurrency: number) {
|
|
@@ -499,15 +500,18 @@ function prepareForPersistence(obj: unknown, blobStore: BlobStore, key?: string)
|
|
|
499
500
|
if (obj === null || obj === undefined) return obj;
|
|
500
501
|
|
|
501
502
|
if (typeof obj === "string") {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
503
|
+
// Cryptographic signatures must be preserved byte-exact — never redact or truncate
|
|
504
|
+
// their contents, only the oversize-clear path below handles them.
|
|
505
|
+
const isSignature = key === "thinkingSignature" || key === "thoughtSignature" || key === "textSignature";
|
|
506
|
+
const redacted = isSignature ? obj : redactSecrets(obj);
|
|
507
|
+
if (redacted.length > MAX_PERSIST_CHARS) {
|
|
508
|
+
if (isSignature) {
|
|
505
509
|
return "";
|
|
506
510
|
}
|
|
507
511
|
const limit = Math.max(0, MAX_PERSIST_CHARS - TRUNCATION_NOTICE.length);
|
|
508
|
-
return `${truncateString(
|
|
512
|
+
return `${truncateString(redacted, limit)}${TRUNCATION_NOTICE}`;
|
|
509
513
|
}
|
|
510
|
-
return
|
|
514
|
+
return redacted;
|
|
511
515
|
}
|
|
512
516
|
|
|
513
517
|
if (Array.isArray(obj)) {
|
|
@@ -2,7 +2,7 @@ import { truncateToWidth, visibleWidth } from "@gsd/pi-tui";
|
|
|
2
2
|
import { theme } from "../theme/theme.js";
|
|
3
3
|
import { formatTimestamp, type TimestampFormat } from "./timestamp.js";
|
|
4
4
|
|
|
5
|
-
type FrameTone = "assistant" | "user" | "compaction";
|
|
5
|
+
type FrameTone = "assistant" | "user" | "compaction" | "skill";
|
|
6
6
|
|
|
7
7
|
function trimOuterBlankLines(lines: string[]): string[] {
|
|
8
8
|
let start = 0;
|
|
@@ -25,14 +25,14 @@ export function renderChatFrame(
|
|
|
25
25
|
): string[] {
|
|
26
26
|
const outerWidth = Math.max(20, width);
|
|
27
27
|
const contentWidth = Math.max(1, outerWidth - 2); // "│ " + content
|
|
28
|
+
const isPurple = opts.tone === "compaction" || opts.tone === "skill";
|
|
28
29
|
const borderColor =
|
|
29
30
|
opts.tone === "user"
|
|
30
31
|
? "border"
|
|
31
|
-
:
|
|
32
|
+
: isPurple
|
|
32
33
|
? "customMessageLabel"
|
|
33
34
|
: "borderAccent";
|
|
34
|
-
const borderMuted =
|
|
35
|
-
opts.tone === "compaction" ? "customMessageLabel" : "borderMuted";
|
|
35
|
+
const borderMuted = isPurple ? "customMessageLabel" : "borderMuted";
|
|
36
36
|
const border = (s: string) => theme.fg(borderColor, s);
|
|
37
37
|
const leftRaw = `• ${opts.label}`;
|
|
38
38
|
const rightRaw =
|
|
@@ -47,7 +47,7 @@ export function renderChatFrame(
|
|
|
47
47
|
const labelColor =
|
|
48
48
|
opts.tone === "user"
|
|
49
49
|
? "border"
|
|
50
|
-
:
|
|
50
|
+
: isPurple
|
|
51
51
|
? "customMessageLabel"
|
|
52
52
|
: "borderAccent";
|
|
53
53
|
const dashIdx = left.indexOf(" - ");
|
|
@@ -71,7 +71,7 @@ export function renderChatFrame(
|
|
|
71
71
|
const bodyColor =
|
|
72
72
|
opts.tone === "user"
|
|
73
73
|
? "userMessageText"
|
|
74
|
-
:
|
|
74
|
+
: isPurple
|
|
75
75
|
? "customMessageText"
|
|
76
76
|
: "assistantMessageText";
|
|
77
77
|
const bodyLines = (sourceLines.length > 0 ? sourceLines : [""]).map((line) => {
|
package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts
CHANGED
|
@@ -1,55 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
// GSD / pi-coding-agent — Skill invocation message component
|
|
2
|
+
import { Container, Markdown, type MarkdownTheme, Text } from "@gsd/pi-tui";
|
|
2
3
|
import type { ParsedSkillBlock } from "../../../core/agent-session.js";
|
|
3
4
|
import { getMarkdownTheme, theme } from "../theme/theme.js";
|
|
5
|
+
import { renderChatFrame } from "./chat-frame.js";
|
|
4
6
|
import { editorKey } from "./keybinding-hints.js";
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
9
|
+
* Renders a skill invocation in the shared chat-frame style (top rule,
|
|
10
|
+
* `• skill - <name>` header, `│ ` body margin) with purple border/label
|
|
11
|
+
* matching compaction so it visually aligns with user/assistant messages.
|
|
10
12
|
*/
|
|
11
|
-
export class SkillInvocationMessageComponent extends
|
|
13
|
+
export class SkillInvocationMessageComponent extends Container {
|
|
12
14
|
private expanded = false;
|
|
13
15
|
private skillBlock: ParsedSkillBlock;
|
|
14
16
|
private markdownTheme: MarkdownTheme;
|
|
15
17
|
|
|
16
18
|
constructor(skillBlock: ParsedSkillBlock, markdownTheme: MarkdownTheme = getMarkdownTheme()) {
|
|
17
|
-
super(
|
|
19
|
+
super();
|
|
18
20
|
this.skillBlock = skillBlock;
|
|
19
21
|
this.markdownTheme = markdownTheme;
|
|
20
|
-
this.
|
|
22
|
+
this.rebuild();
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
setExpanded(expanded: boolean): void {
|
|
24
|
-
this.expanded
|
|
25
|
-
|
|
26
|
+
if (this.expanded !== expanded) {
|
|
27
|
+
this.expanded = expanded;
|
|
28
|
+
this.rebuild();
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
override invalidate(): void {
|
|
29
33
|
super.invalidate();
|
|
30
|
-
this.
|
|
34
|
+
this.rebuild();
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
private
|
|
37
|
+
private rebuild(): void {
|
|
34
38
|
this.clear();
|
|
35
39
|
|
|
36
40
|
if (this.expanded) {
|
|
37
|
-
// Expanded: label + skill name header + full content
|
|
38
|
-
const label = theme.fg("customMessageLabel", theme.bold("[skill]"));
|
|
39
|
-
this.addChild(new Text(label, 0, 0));
|
|
40
|
-
const header = `**${this.skillBlock.name}**\n\n`;
|
|
41
41
|
this.addChild(
|
|
42
|
-
new Markdown(
|
|
42
|
+
new Markdown(this.skillBlock.content, 0, 0, this.markdownTheme, {
|
|
43
43
|
color: (text: string) => theme.fg("customMessageText", text),
|
|
44
44
|
}),
|
|
45
45
|
);
|
|
46
46
|
} else {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
this.addChild(
|
|
48
|
+
new Text(
|
|
49
|
+
theme.fg("dim", `(${editorKey("expandTools")} to expand)`),
|
|
50
|
+
0,
|
|
51
|
+
0,
|
|
52
|
+
),
|
|
53
|
+
);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
56
|
+
|
|
57
|
+
override render(width: number): string[] {
|
|
58
|
+
const frameWidth = Math.max(20, width);
|
|
59
|
+
const contentWidth = Math.max(1, frameWidth - 4);
|
|
60
|
+
const lines = super.render(contentWidth);
|
|
61
|
+
const framed = renderChatFrame(lines, frameWidth, {
|
|
62
|
+
label: `skill - ${this.skillBlock.name}`,
|
|
63
|
+
tone: "skill",
|
|
64
|
+
timestampFormat: "date-time-iso",
|
|
65
|
+
showTimestamp: false,
|
|
66
|
+
});
|
|
67
|
+
return framed.length > 0 ? ["", ...framed] : framed;
|
|
68
|
+
}
|
|
55
69
|
}
|