gsd-pi 2.28.0-dev.e19bf89 → 2.29.0-dev.2ccf3fb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -17
- package/dist/cli.js +15 -9
- package/dist/resource-loader.js +80 -8
- package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/dist/resources/extensions/gsd/auto-dashboard.ts +186 -65
- package/dist/resources/extensions/gsd/auto-post-unit.ts +14 -6
- package/dist/resources/extensions/gsd/auto-recovery.ts +33 -23
- package/dist/resources/extensions/gsd/auto-start.ts +25 -10
- package/dist/resources/extensions/gsd/auto-verification.ts +41 -7
- package/dist/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
- package/dist/resources/extensions/gsd/auto.ts +67 -22
- package/dist/resources/extensions/gsd/commands-handlers.ts +3 -11
- package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
- package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/dist/resources/extensions/gsd/commands.ts +75 -29
- package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/dist/resources/extensions/gsd/doctor-types.ts +13 -0
- package/dist/resources/extensions/gsd/doctor.ts +2 -6
- package/dist/resources/extensions/gsd/export.ts +28 -2
- package/dist/resources/extensions/gsd/gsd-db.ts +19 -0
- package/dist/resources/extensions/gsd/index.ts +2 -1
- package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
- package/dist/resources/extensions/gsd/metrics.ts +17 -31
- package/dist/resources/extensions/gsd/paths.ts +0 -8
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/dist/resources/extensions/gsd/queue-order.ts +10 -11
- package/dist/resources/extensions/gsd/routing-history.ts +13 -17
- package/dist/resources/extensions/gsd/session-lock.ts +284 -0
- package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
- package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
- package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
- package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
- package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
- package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
- package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/dist/resources/extensions/gsd/types.ts +1 -0
- package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
- package/dist/resources/extensions/gsd/verification-evidence.ts +2 -0
- package/dist/resources/extensions/gsd/verification-gate.ts +13 -2
- package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/dist/resources/extensions/mcp-client/index.ts +459 -0
- package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
- package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
- package/dist/resources/extensions/remote-questions/notify.ts +1 -2
- package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
- package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
- package/dist/resources/extensions/remote-questions/types.ts +3 -0
- package/dist/resources/extensions/shared/mod.ts +3 -0
- package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/dist/resources/skills/create-skill/SKILL.md +184 -0
- package/dist/resources/skills/create-skill/references/api-security.md +226 -0
- package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
- package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
- package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/package.json +6 -3
- package/packages/native/dist/native.d.ts +2 -0
- package/packages/native/dist/native.js +19 -5
- package/packages/native/src/native.ts +23 -9
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
- package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -1
- package/packages/pi-tui/dist/autocomplete.d.ts +3 -0
- package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
- package/packages/pi-tui/dist/autocomplete.js +14 -0
- package/packages/pi-tui/dist/autocomplete.js.map +1 -1
- package/packages/pi-tui/src/autocomplete.ts +19 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +186 -65
- package/src/resources/extensions/gsd/auto-post-unit.ts +14 -6
- package/src/resources/extensions/gsd/auto-recovery.ts +33 -23
- package/src/resources/extensions/gsd/auto-start.ts +25 -10
- package/src/resources/extensions/gsd/auto-verification.ts +41 -7
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
- package/src/resources/extensions/gsd/auto.ts +67 -22
- package/src/resources/extensions/gsd/commands-handlers.ts +3 -11
- package/src/resources/extensions/gsd/commands-logs.ts +536 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
- package/src/resources/extensions/gsd/commands.ts +75 -29
- package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
- package/src/resources/extensions/gsd/doctor-types.ts +13 -0
- package/src/resources/extensions/gsd/doctor.ts +2 -6
- package/src/resources/extensions/gsd/export.ts +28 -2
- package/src/resources/extensions/gsd/gsd-db.ts +19 -0
- package/src/resources/extensions/gsd/index.ts +2 -1
- package/src/resources/extensions/gsd/json-persistence.ts +67 -0
- package/src/resources/extensions/gsd/metrics.ts +17 -31
- package/src/resources/extensions/gsd/paths.ts +0 -8
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
- package/src/resources/extensions/gsd/queue-order.ts +10 -11
- package/src/resources/extensions/gsd/routing-history.ts +13 -17
- package/src/resources/extensions/gsd/session-lock.ts +284 -0
- package/src/resources/extensions/gsd/session-status-io.ts +23 -41
- package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
- package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
- package/src/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
- package/src/resources/extensions/gsd/types.ts +1 -0
- package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
- package/src/resources/extensions/gsd/verification-evidence.ts +2 -0
- package/src/resources/extensions/gsd/verification-gate.ts +13 -2
- package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
- package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
- package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
- package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
- package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
- package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
- package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
- package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
- package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
- package/src/resources/extensions/mcp-client/index.ts +459 -0
- package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
- package/src/resources/extensions/remote-questions/http-client.ts +76 -0
- package/src/resources/extensions/remote-questions/notify.ts +1 -2
- package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
- package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
- package/src/resources/extensions/remote-questions/types.ts +3 -0
- package/src/resources/extensions/shared/mod.ts +3 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
- package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
- package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
- package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
- package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
- package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
- package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
- package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
- package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
- package/src/resources/skills/create-skill/SKILL.md +184 -0
- package/src/resources/skills/create-skill/references/api-security.md +226 -0
- package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
- package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
- package/src/resources/skills/create-skill/references/core-principles.md +437 -0
- package/src/resources/skills/create-skill/references/executable-code.md +175 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
- package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
- package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
- package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
- package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
- package/src/resources/skills/create-skill/references/using-templates.md +112 -0
- package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
- package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
- package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
- package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
- package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
- package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
- package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
- package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
- package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
- package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
- package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
- package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
- package/dist/resources/extensions/gsd/preferences-hooks.ts +0 -10
- package/dist/resources/extensions/mcporter/index.ts +0 -525
- package/dist/resources/extensions/shared/progress-widget.ts +0 -282
- package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
- package/src/resources/extensions/gsd/preferences-hooks.ts +0 -10
- package/src/resources/extensions/mcporter/index.ts +0 -525
- package/src/resources/extensions/shared/progress-widget.ts +0 -282
- package/src/resources/extensions/shared/thinking-widget.ts +0 -107
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Complete event reference with handler signatures, return types, and type narrowing utilities.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<event_categories>
|
|
6
|
+
|
|
7
|
+
**Session events:** `session_start`, `session_before_switch`, `session_switch`, `session_before_fork`, `session_fork`, `session_before_compact`, `session_compact`, `session_before_tree`, `session_tree`, `session_shutdown`
|
|
8
|
+
|
|
9
|
+
**Agent events:** `before_agent_start`, `agent_start`, `agent_end`, `turn_start`, `turn_end`, `context`, `before_provider_request`, `message_start`, `message_update`, `message_end`
|
|
10
|
+
|
|
11
|
+
**Tool events:** `tool_call`, `tool_execution_start`, `tool_execution_update`, `tool_execution_end`, `tool_result`
|
|
12
|
+
|
|
13
|
+
**Input events:** `input`
|
|
14
|
+
|
|
15
|
+
**Model events:** `model_select`
|
|
16
|
+
|
|
17
|
+
**User bash events:** `user_bash`
|
|
18
|
+
|
|
19
|
+
**Special:** `session_directory` (CLI startup only, no `ctx` — receives only event)
|
|
20
|
+
|
|
21
|
+
</event_categories>
|
|
22
|
+
|
|
23
|
+
<handler_signature>
|
|
24
|
+
```typescript
|
|
25
|
+
pi.on("event_name", async (event, ctx: ExtensionContext) => {
|
|
26
|
+
// event — typed payload for this event
|
|
27
|
+
// ctx — access to UI, session, model, control flow
|
|
28
|
+
// Return undefined for no action, or a typed response
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
</handler_signature>
|
|
32
|
+
|
|
33
|
+
<key_events>
|
|
34
|
+
|
|
35
|
+
**before_agent_start** — Fired after user prompt, before agent loop. Primary hook for context injection and system prompt modification.
|
|
36
|
+
```typescript
|
|
37
|
+
pi.on("before_agent_start", async (event, ctx) => {
|
|
38
|
+
// event.prompt — user's prompt text
|
|
39
|
+
// event.images — attached images
|
|
40
|
+
// event.systemPrompt — current system prompt
|
|
41
|
+
return {
|
|
42
|
+
message: { customType: "my-ext", content: "Extra context", display: true },
|
|
43
|
+
systemPrompt: event.systemPrompt + "\n\nExtra instructions...",
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**tool_call** — Fired before tool executes. Can block.
|
|
49
|
+
```typescript
|
|
50
|
+
import { isToolCallEventType } from "@mariozechner/pi-coding-agent";
|
|
51
|
+
|
|
52
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
53
|
+
if (isToolCallEventType("bash", event)) {
|
|
54
|
+
// event.input is typed as { command: string; timeout?: number }
|
|
55
|
+
if (event.input.command.includes("rm -rf")) {
|
|
56
|
+
return { block: true, reason: "Dangerous command" };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**tool_result** — Fired after tool executes. Can modify result. Handlers chain like middleware.
|
|
63
|
+
```typescript
|
|
64
|
+
import { isBashToolResult } from "@mariozechner/pi-coding-agent";
|
|
65
|
+
|
|
66
|
+
pi.on("tool_result", async (event, ctx) => {
|
|
67
|
+
if (isBashToolResult(event)) {
|
|
68
|
+
// event.details is typed as BashToolDetails
|
|
69
|
+
}
|
|
70
|
+
// Return partial patch: { content, details, isError }
|
|
71
|
+
// Omitted fields keep current values
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**context** — Fired before each LLM call. Modify messages non-destructively.
|
|
76
|
+
```typescript
|
|
77
|
+
pi.on("context", async (event, ctx) => {
|
|
78
|
+
// event.messages is a deep copy — safe to modify
|
|
79
|
+
const filtered = event.messages.filter(m => !shouldPrune(m));
|
|
80
|
+
return { messages: filtered };
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**input** — Fired when user input is received, before skill/template expansion.
|
|
85
|
+
```typescript
|
|
86
|
+
pi.on("input", async (event, ctx) => {
|
|
87
|
+
// event.text — raw input
|
|
88
|
+
// event.source — "interactive", "rpc", or "extension"
|
|
89
|
+
if (event.text.startsWith("?quick "))
|
|
90
|
+
return { action: "transform", text: `Respond briefly: ${event.text.slice(7)}` };
|
|
91
|
+
return { action: "continue" };
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**model_select** — Fired when model changes.
|
|
96
|
+
```typescript
|
|
97
|
+
pi.on("model_select", async (event, ctx) => {
|
|
98
|
+
// event.model, event.previousModel, event.source ("set"|"cycle"|"restore")
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
</key_events>
|
|
103
|
+
|
|
104
|
+
<type_narrowing>
|
|
105
|
+
Built-in type guards for tool events:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import { isToolCallEventType, isBashToolResult } from "@mariozechner/pi-coding-agent";
|
|
109
|
+
|
|
110
|
+
// Tool calls — narrows event.input type
|
|
111
|
+
if (isToolCallEventType("bash", event)) { /* event.input: { command, timeout? } */ }
|
|
112
|
+
if (isToolCallEventType("read", event)) { /* event.input: { path, offset?, limit? } */ }
|
|
113
|
+
if (isToolCallEventType("write", event)) { /* event.input: { path, content } */ }
|
|
114
|
+
if (isToolCallEventType("edit", event)) { /* event.input: { path, oldText, newText } */ }
|
|
115
|
+
|
|
116
|
+
// Tool results — narrows event.details type
|
|
117
|
+
if (isBashToolResult(event)) { /* event.details: BashToolDetails */ }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
For custom tools, export your input type and use explicit type params:
|
|
121
|
+
```typescript
|
|
122
|
+
if (isToolCallEventType<"my_tool", MyToolInput>("my_tool", event)) {
|
|
123
|
+
event.input.action; // typed
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
</type_narrowing>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
The extension lifecycle from load to shutdown, including the full event flow.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<loading>
|
|
6
|
+
Extensions load when GSD starts (or on `/reload`). The default export function runs synchronously — subscribe to events and register tools/commands during this call.
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
GSD starts
|
|
10
|
+
└─► Extension default function runs
|
|
11
|
+
├── pi.on("event", handler) ← Subscribe
|
|
12
|
+
├── pi.registerTool({...}) ← Register tools
|
|
13
|
+
├── pi.registerCommand(...) ← Register commands
|
|
14
|
+
└── pi.registerShortcut(...) ← Register shortcuts
|
|
15
|
+
└─► session_start fires
|
|
16
|
+
```
|
|
17
|
+
</loading>
|
|
18
|
+
|
|
19
|
+
<event_flow>
|
|
20
|
+
Full event flow per user prompt:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
user sends prompt
|
|
24
|
+
├─► Extension commands checked (bypass if match)
|
|
25
|
+
├─► input event (can intercept/transform/handle)
|
|
26
|
+
├─► Skill/template expansion
|
|
27
|
+
├─► before_agent_start (inject message, modify system prompt)
|
|
28
|
+
├─► agent_start
|
|
29
|
+
│
|
|
30
|
+
│ ┌── Turn loop (repeats while LLM calls tools) ──┐
|
|
31
|
+
│ │ turn_start │
|
|
32
|
+
│ │ context (can modify messages sent to LLM) │
|
|
33
|
+
│ │ before_provider_request (inspect/replace payload)│
|
|
34
|
+
│ │ LLM responds → may call tools: │
|
|
35
|
+
│ │ tool_call (can BLOCK) │
|
|
36
|
+
│ │ tool_execution_start/update/end │
|
|
37
|
+
│ │ tool_result (can MODIFY) │
|
|
38
|
+
│ │ turn_end │
|
|
39
|
+
│ └────────────────────────────────────────────────┘
|
|
40
|
+
│
|
|
41
|
+
└─► agent_end
|
|
42
|
+
```
|
|
43
|
+
</event_flow>
|
|
44
|
+
|
|
45
|
+
<session_events>
|
|
46
|
+
| Event | When | Can Return |
|
|
47
|
+
|-------|------|------------|
|
|
48
|
+
| `session_start` | Session loads | — |
|
|
49
|
+
| `session_before_switch` | Before `/new` or `/resume` | `{ cancel: true }` |
|
|
50
|
+
| `session_switch` | After switch | — |
|
|
51
|
+
| `session_before_fork` | Before `/fork` | `{ cancel: true }`, `{ skipConversationRestore: true }` |
|
|
52
|
+
| `session_fork` | After fork | — |
|
|
53
|
+
| `session_before_compact` | Before compaction | `{ cancel: true }`, `{ compaction: {...} }` |
|
|
54
|
+
| `session_compact` | After compaction | — |
|
|
55
|
+
| `session_shutdown` | On exit | — |
|
|
56
|
+
</session_events>
|
|
57
|
+
|
|
58
|
+
<hot_reload>
|
|
59
|
+
Extensions in auto-discovered locations hot-reload with `/reload`:
|
|
60
|
+
- `session_shutdown` fires for old runtime
|
|
61
|
+
- Resources re-scanned
|
|
62
|
+
- `session_start` fires for new runtime
|
|
63
|
+
- Code after `await ctx.reload()` still runs from the pre-reload version — treat as terminal
|
|
64
|
+
</hot_reload>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
ExtensionAPI methods — the `pi` object received in the default export function.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<core_registration>
|
|
6
|
+
| Method | Purpose |
|
|
7
|
+
|--------|---------|
|
|
8
|
+
| `pi.on(event, handler)` | Subscribe to events |
|
|
9
|
+
| `pi.registerTool(definition)` | Register LLM-callable tool |
|
|
10
|
+
| `pi.registerCommand(name, options)` | Register `/command` |
|
|
11
|
+
| `pi.registerShortcut(key, options)` | Register keyboard shortcut |
|
|
12
|
+
| `pi.registerFlag(name, options)` | Register CLI flag |
|
|
13
|
+
| `pi.registerMessageRenderer(customType, renderer)` | Custom message rendering |
|
|
14
|
+
| `pi.registerProvider(name, config)` | Register/override model provider |
|
|
15
|
+
| `pi.unregisterProvider(name)` | Remove a provider |
|
|
16
|
+
</core_registration>
|
|
17
|
+
|
|
18
|
+
<messaging>
|
|
19
|
+
| Method | Purpose |
|
|
20
|
+
|--------|---------|
|
|
21
|
+
| `pi.sendMessage(message, options?)` | Inject custom message into session |
|
|
22
|
+
| `pi.sendUserMessage(content, options?)` | Send user message (triggers turn) |
|
|
23
|
+
|
|
24
|
+
**Delivery modes for `sendMessage`:**
|
|
25
|
+
- `"steer"` (default) — Interrupts streaming after current tool
|
|
26
|
+
- `"followUp"` — Waits for agent to finish all tools
|
|
27
|
+
- `"nextTurn"` — Queued for next user prompt
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
pi.sendMessage({
|
|
31
|
+
customType: "my-extension",
|
|
32
|
+
content: "Additional context",
|
|
33
|
+
display: true,
|
|
34
|
+
details: { ... },
|
|
35
|
+
}, { deliverAs: "steer", triggerTurn: true });
|
|
36
|
+
```
|
|
37
|
+
</messaging>
|
|
38
|
+
|
|
39
|
+
<state_session>
|
|
40
|
+
| Method | Purpose |
|
|
41
|
+
|--------|---------|
|
|
42
|
+
| `pi.appendEntry(customType, data?)` | Persist state (NOT sent to LLM) |
|
|
43
|
+
| `pi.setSessionName(name)` | Set session display name |
|
|
44
|
+
| `pi.getSessionName()` | Get session name |
|
|
45
|
+
| `pi.setLabel(entryId, label)` | Bookmark entry for `/tree` |
|
|
46
|
+
</state_session>
|
|
47
|
+
|
|
48
|
+
<tool_management>
|
|
49
|
+
```typescript
|
|
50
|
+
const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
|
|
51
|
+
const all = pi.getAllTools(); // [{ name, description }, ...]
|
|
52
|
+
pi.setActiveTools(["read", "bash"]); // Enable/disable tools
|
|
53
|
+
```
|
|
54
|
+
</tool_management>
|
|
55
|
+
|
|
56
|
+
<model_management>
|
|
57
|
+
```typescript
|
|
58
|
+
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
59
|
+
if (model) {
|
|
60
|
+
const success = await pi.setModel(model); // Returns false if no API key
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"
|
|
64
|
+
pi.setThinkingLevel("high");
|
|
65
|
+
```
|
|
66
|
+
</model_management>
|
|
67
|
+
|
|
68
|
+
<utilities>
|
|
69
|
+
| Method | Purpose |
|
|
70
|
+
|--------|---------|
|
|
71
|
+
| `pi.exec(cmd, args, opts?)` | Shell command (prefer over child_process) |
|
|
72
|
+
| `pi.events` | Shared event bus for inter-extension communication |
|
|
73
|
+
| `pi.getFlag(name)` | Get CLI flag value |
|
|
74
|
+
| `pi.getCommands()` | All available slash commands |
|
|
75
|
+
</utilities>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
ExtensionContext (`ctx`) — available in all event handlers (except `session_directory`).
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<ui_methods>
|
|
6
|
+
**Dialogs (blocking — wait for user response):**
|
|
7
|
+
```typescript
|
|
8
|
+
const choice = await ctx.ui.select("Pick one:", ["A", "B", "C"]);
|
|
9
|
+
const ok = await ctx.ui.confirm("Delete?", "This cannot be undone");
|
|
10
|
+
const name = await ctx.ui.input("Name:", "placeholder");
|
|
11
|
+
const text = await ctx.ui.editor("Edit:", "prefilled text");
|
|
12
|
+
|
|
13
|
+
// Timed dialog — auto-dismiss after timeout
|
|
14
|
+
const ok = await ctx.ui.confirm("Auto-confirm?", "Proceeds in 5s", { timeout: 5000 });
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Non-blocking UI:**
|
|
18
|
+
```typescript
|
|
19
|
+
ctx.ui.notify("Done!", "info"); // Toast: "info" | "warning" | "error"
|
|
20
|
+
ctx.ui.setStatus("my-ext", "● Active"); // Footer status
|
|
21
|
+
ctx.ui.setStatus("my-ext", undefined); // Clear
|
|
22
|
+
ctx.ui.setWidget("my-id", ["Line 1", "Line 2"]); // Widget above editor
|
|
23
|
+
ctx.ui.setWidget("my-id", ["Below!"], { placement: "belowEditor" });
|
|
24
|
+
ctx.ui.setTitle("gsd - my project"); // Terminal title
|
|
25
|
+
ctx.ui.setEditorText("Prefill"); // Set editor content
|
|
26
|
+
ctx.ui.setWorkingMessage("Analyzing..."); // Working message during streaming
|
|
27
|
+
ctx.ui.setToolsExpanded(true); // Expand tool output
|
|
28
|
+
```
|
|
29
|
+
</ui_methods>
|
|
30
|
+
|
|
31
|
+
<ctx_properties>
|
|
32
|
+
| Property/Method | Purpose |
|
|
33
|
+
|----------------|---------|
|
|
34
|
+
| `ctx.hasUI` | `false` in print/JSON mode — check before dialogs |
|
|
35
|
+
| `ctx.cwd` | Current working directory |
|
|
36
|
+
| `ctx.sessionManager` | Read-only session state |
|
|
37
|
+
| `ctx.modelRegistry` / `ctx.model` | Model access |
|
|
38
|
+
| `ctx.isIdle()` / `ctx.abort()` / `ctx.hasPendingMessages()` | Agent state |
|
|
39
|
+
| `ctx.shutdown()` | Request graceful exit (deferred until idle) |
|
|
40
|
+
| `ctx.getContextUsage()` | Current context token usage |
|
|
41
|
+
| `ctx.compact(options?)` | Trigger compaction |
|
|
42
|
+
| `ctx.getSystemPrompt()` | Current effective system prompt |
|
|
43
|
+
</ctx_properties>
|
|
44
|
+
|
|
45
|
+
<session_manager>
|
|
46
|
+
```typescript
|
|
47
|
+
ctx.sessionManager.getEntries() // All entries
|
|
48
|
+
ctx.sessionManager.getBranch() // Current branch
|
|
49
|
+
ctx.sessionManager.getLeafId() // Current leaf entry ID
|
|
50
|
+
ctx.sessionManager.getSessionFile() // Session JSONL path
|
|
51
|
+
ctx.sessionManager.getLabel(entryId) // Entry label
|
|
52
|
+
```
|
|
53
|
+
</session_manager>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Non-negotiable rules and common gotchas when building GSD extensions.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<must_follow>
|
|
6
|
+
1. **Use `StringEnum` for string enums** — `Type.Union`/`Type.Literal` breaks Google's API.
|
|
7
|
+
2. **Truncate tool output** — Large output causes context overflow, compaction failures, degraded performance. Limit: 50KB / 2000 lines.
|
|
8
|
+
3. **Use theme from callback** — Don't import theme directly. Use the `theme` parameter from `ctx.ui.custom()` or render functions.
|
|
9
|
+
4. **`DynamicBorder` color param** — Type as `(s: string) => theme.fg("accent", s)`.
|
|
10
|
+
5. **Call `tui.requestRender()` after state changes** in `handleInput`.
|
|
11
|
+
6. **Return `{ render, invalidate, handleInput }`** from custom components.
|
|
12
|
+
7. **Lines must not exceed `width`** in `render()` — use `truncateToWidth()`.
|
|
13
|
+
8. **Session control methods ONLY in commands** — `waitForIdle()`, `newSession()`, `fork()`, `navigateTree()`, `reload()` will **deadlock** in event handlers.
|
|
14
|
+
9. **Strip leading `@` from path arguments** — some models add it.
|
|
15
|
+
10. **Store state in tool result `details`** for proper branching support.
|
|
16
|
+
</must_follow>
|
|
17
|
+
|
|
18
|
+
<common_patterns>
|
|
19
|
+
- Rebuild component on `invalidate()` when pre-baking theme colors
|
|
20
|
+
- Check `signal?.aborted` in long-running tool executions
|
|
21
|
+
- Use `pi.exec()` instead of `child_process` for shell commands
|
|
22
|
+
- Overlay components are **disposed when closed** — create fresh instances each time
|
|
23
|
+
- Treat `ctx.reload()` as terminal — code after runs from pre-reload version
|
|
24
|
+
- Check `ctx.hasUI` before dialog methods (false in print/JSON mode)
|
|
25
|
+
- Extension errors are logged but don't crash GSD — tool_call handler errors fail-safe (block the tool)
|
|
26
|
+
</common_patterns>
|
|
27
|
+
|
|
28
|
+
<gsd_paths>
|
|
29
|
+
**GSD extension paths:**
|
|
30
|
+
- Global: `~/.gsd/agent/extensions/*.ts`
|
|
31
|
+
- Global (subdir): `~/.gsd/agent/extensions/*/index.ts`
|
|
32
|
+
- Project-local: `.gsd/extensions/*.ts`
|
|
33
|
+
- Project-local (subdir): `.gsd/extensions/*/index.ts`
|
|
34
|
+
|
|
35
|
+
The upstream pi docs reference `~/.pi` paths — GSD uses `~/.gsd` everywhere instead.
|
|
36
|
+
</gsd_paths>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Mode behavior determines which UI methods work. Extensions may run in non-interactive modes where dialogs are unavailable.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<mode_table>
|
|
6
|
+
| Mode | UI Methods | Notes |
|
|
7
|
+
|------|-----------|-------|
|
|
8
|
+
| **Interactive** (default) | Full TUI | Normal operation — all UI works |
|
|
9
|
+
| **RPC** (`--mode rpc`) | JSON protocol | Host handles UI, dialogs work via sub-protocol |
|
|
10
|
+
| **JSON** (`--mode json`) | No-op | Event stream to stdout, no UI |
|
|
11
|
+
| **Print** (`-p`) | No-op | Extensions run but can't prompt users |
|
|
12
|
+
</mode_table>
|
|
13
|
+
|
|
14
|
+
<checking_ui>
|
|
15
|
+
**Always check `ctx.hasUI`** before calling dialog methods:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
if (ctx.hasUI) {
|
|
19
|
+
const ok = await ctx.ui.confirm("Delete?", "Sure?");
|
|
20
|
+
if (!ok) return;
|
|
21
|
+
} else {
|
|
22
|
+
// Default behavior for non-interactive mode
|
|
23
|
+
// Or just proceed without confirmation
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`ctx.hasUI` is `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode.
|
|
28
|
+
</checking_ui>
|
|
29
|
+
|
|
30
|
+
<fire_and_forget>
|
|
31
|
+
Non-blocking methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) are safe in all modes — they're no-ops when no UI is available.
|
|
32
|
+
</fire_and_forget>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Model and provider management — switching models, registering custom providers with OAuth, and reacting to model changes.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<switching_models>
|
|
6
|
+
```typescript
|
|
7
|
+
const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
|
|
8
|
+
if (model) {
|
|
9
|
+
const success = await pi.setModel(model);
|
|
10
|
+
if (!success) ctx.ui.notify("No API key for this model", "error");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Thinking level
|
|
14
|
+
pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"
|
|
15
|
+
pi.setThinkingLevel("high"); // Clamped to model capabilities
|
|
16
|
+
```
|
|
17
|
+
</switching_models>
|
|
18
|
+
|
|
19
|
+
<register_provider>
|
|
20
|
+
```typescript
|
|
21
|
+
pi.registerProvider("my-proxy", {
|
|
22
|
+
baseUrl: "https://proxy.example.com",
|
|
23
|
+
apiKey: "PROXY_API_KEY", // Env var name or literal
|
|
24
|
+
api: "anthropic-messages", // or "openai-completions", "openai-responses"
|
|
25
|
+
headers: { "X-Custom": "value" }, // Optional custom headers
|
|
26
|
+
authHeader: true, // Auto-add Authorization: Bearer header
|
|
27
|
+
models: [
|
|
28
|
+
{
|
|
29
|
+
id: "claude-sonnet-4-20250514",
|
|
30
|
+
name: "Claude 4 Sonnet (proxy)",
|
|
31
|
+
reasoning: false,
|
|
32
|
+
input: ["text", "image"],
|
|
33
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
34
|
+
contextWindow: 200000,
|
|
35
|
+
maxTokens: 16384,
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Override just baseUrl for an existing provider (keeps all models)
|
|
41
|
+
pi.registerProvider("anthropic", {
|
|
42
|
+
baseUrl: "https://proxy.example.com",
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Remove a provider (restores any overridden built-in models)
|
|
46
|
+
pi.unregisterProvider("my-proxy");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Takes effect immediately after initial load phase — no `/reload` required.
|
|
50
|
+
</register_provider>
|
|
51
|
+
|
|
52
|
+
<oauth_provider>
|
|
53
|
+
Register a provider with OAuth support for `/login`:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
pi.registerProvider("corporate-ai", {
|
|
57
|
+
baseUrl: "https://ai.corp.com",
|
|
58
|
+
api: "openai-responses",
|
|
59
|
+
models: [/* ... */],
|
|
60
|
+
oauth: {
|
|
61
|
+
name: "Corporate AI (SSO)",
|
|
62
|
+
async login(callbacks) {
|
|
63
|
+
callbacks.onAuth({ url: "https://sso.corp.com/..." });
|
|
64
|
+
const code = await callbacks.onPrompt({ message: "Enter code:" });
|
|
65
|
+
return { refresh: code, access: code, expires: Date.now() + 3600000 };
|
|
66
|
+
},
|
|
67
|
+
async refreshToken(credentials) {
|
|
68
|
+
return credentials; // Refresh logic
|
|
69
|
+
},
|
|
70
|
+
getApiKey(credentials) {
|
|
71
|
+
return credentials.access;
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
</oauth_provider>
|
|
77
|
+
|
|
78
|
+
<model_events>
|
|
79
|
+
React to model changes:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
pi.on("model_select", async (event, ctx) => {
|
|
83
|
+
// event.model — newly selected model
|
|
84
|
+
// event.previousModel — previous model (undefined if first)
|
|
85
|
+
// event.source — "set" | "cycle" | "restore"
|
|
86
|
+
ctx.ui.setStatus("model", `${event.model.provider}/${event.model.id}`);
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
</model_events>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Packaging extensions for distribution via npm, git, or local paths. Creating GSD/pi packages.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<package_manifest>
|
|
6
|
+
Add a `pi` manifest to `package.json`:
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
{
|
|
10
|
+
"name": "my-gsd-package",
|
|
11
|
+
"keywords": ["pi-package"],
|
|
12
|
+
"pi": {
|
|
13
|
+
"extensions": ["./extensions"],
|
|
14
|
+
"skills": ["./skills"],
|
|
15
|
+
"prompts": ["./prompts"],
|
|
16
|
+
"themes": ["./themes"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
</package_manifest>
|
|
21
|
+
|
|
22
|
+
<installing>
|
|
23
|
+
```bash
|
|
24
|
+
gsd install npm:@foo/bar@1.0.0
|
|
25
|
+
gsd install git:github.com/user/repo@v1
|
|
26
|
+
gsd install ./local/path
|
|
27
|
+
|
|
28
|
+
# Try without installing:
|
|
29
|
+
gsd -e npm:@foo/bar
|
|
30
|
+
```
|
|
31
|
+
</installing>
|
|
32
|
+
|
|
33
|
+
<convention_directories>
|
|
34
|
+
If no `pi` manifest exists, auto-discovers:
|
|
35
|
+
- `extensions/` → `.ts` and `.js` files
|
|
36
|
+
- `skills/` → `SKILL.md` folders
|
|
37
|
+
- `prompts/` → `.md` files
|
|
38
|
+
- `themes/` → `.json` files
|
|
39
|
+
</convention_directories>
|
|
40
|
+
|
|
41
|
+
<dependencies>
|
|
42
|
+
- List `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@sinclair/typebox` in `peerDependencies` with `"*"` — they're bundled by the runtime.
|
|
43
|
+
- Other npm deps go in `dependencies`. The runtime runs `npm install` on package installation.
|
|
44
|
+
</dependencies>
|
|
45
|
+
|
|
46
|
+
<gallery_metadata>
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"pi": {
|
|
50
|
+
"video": "https://example.com/demo.mp4",
|
|
51
|
+
"image": "https://example.com/screenshot.png"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
</gallery_metadata>
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<overview>
|
|
2
|
+
Remote execution via pluggable operations, spawnHook for bash, and tool override patterns.
|
|
3
|
+
</overview>
|
|
4
|
+
|
|
5
|
+
<pluggable_operations>
|
|
6
|
+
Built-in tools support pluggable operations for SSH, containers, etc.:
|
|
7
|
+
|
|
8
|
+
```typescript
|
|
9
|
+
import { createReadTool, createBashTool, createWriteTool } from "@mariozechner/pi-coding-agent";
|
|
10
|
+
|
|
11
|
+
// Create tool with custom remote operations
|
|
12
|
+
const remoteBash = createBashTool(cwd, {
|
|
13
|
+
operations: {
|
|
14
|
+
execute: (cmd) => sshExec(remote, cmd),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
|
|
20
|
+
</pluggable_operations>
|
|
21
|
+
|
|
22
|
+
<spawn_hook>
|
|
23
|
+
The bash tool supports a `spawnHook` to modify commands before execution:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
const bashTool = createBashTool(cwd, {
|
|
27
|
+
spawnHook: ({ command, cwd, env }) => ({
|
|
28
|
+
command: `source ~/.profile\n${command}`,
|
|
29
|
+
cwd: `/mnt/sandbox${cwd}`,
|
|
30
|
+
env: { ...env, CI: "1" },
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
</spawn_hook>
|
|
35
|
+
|
|
36
|
+
<ssh_pattern>
|
|
37
|
+
Full SSH pattern with flag-based switching:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { createBashTool, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
41
|
+
|
|
42
|
+
export default function (pi: ExtensionAPI) {
|
|
43
|
+
pi.registerFlag("ssh", { description: "SSH target", type: "string" });
|
|
44
|
+
|
|
45
|
+
const localBash = createBashTool(process.cwd());
|
|
46
|
+
|
|
47
|
+
pi.registerTool({
|
|
48
|
+
...localBash,
|
|
49
|
+
async execute(id, params, signal, onUpdate, ctx) {
|
|
50
|
+
const sshTarget = pi.getFlag("--ssh");
|
|
51
|
+
if (sshTarget) {
|
|
52
|
+
const remoteBash = createBashTool(process.cwd(), {
|
|
53
|
+
operations: createSSHOperations(sshTarget),
|
|
54
|
+
});
|
|
55
|
+
return remoteBash.execute(id, params, signal, onUpdate);
|
|
56
|
+
}
|
|
57
|
+
return localBash.execute(id, params, signal, onUpdate);
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
</ssh_pattern>
|
|
63
|
+
|
|
64
|
+
<tool_override_pattern>
|
|
65
|
+
Override built-in tools for logging/access control — omit renderCall/renderResult to keep built-in rendering:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { createReadTool } from "@mariozechner/pi-coding-agent";
|
|
69
|
+
import { Type } from "@sinclair/typebox";
|
|
70
|
+
|
|
71
|
+
pi.registerTool({
|
|
72
|
+
name: "read", // Same name = overrides built-in
|
|
73
|
+
label: "Read (Logged)",
|
|
74
|
+
description: "Read file contents with logging",
|
|
75
|
+
parameters: Type.Object({
|
|
76
|
+
path: Type.String(),
|
|
77
|
+
offset: Type.Optional(Type.Number()),
|
|
78
|
+
limit: Type.Optional(Type.Number()),
|
|
79
|
+
}),
|
|
80
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
81
|
+
console.log(`[AUDIT] Reading: ${params.path}`);
|
|
82
|
+
const builtIn = createReadTool(ctx.cwd);
|
|
83
|
+
return builtIn.execute(toolCallId, params, signal, onUpdate);
|
|
84
|
+
},
|
|
85
|
+
// Omit renderCall/renderResult → built-in renderer used automatically
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Must match exact result shape** including `details` type.
|
|
90
|
+
</tool_override_pattern>
|