@dyyz1993/pi-coding-agent 0.74.24 → 0.74.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/core/agent-session.d.ts.map +1 -1
  3. package/dist/core/agent-session.js +3 -0
  4. package/dist/core/agent-session.js.map +1 -1
  5. package/dist/core/session-manager.d.ts +5 -0
  6. package/dist/core/session-manager.d.ts.map +1 -1
  7. package/dist/core/session-manager.js +8 -0
  8. package/dist/core/session-manager.js.map +1 -1
  9. package/dist/extensions/agent-permissions/index.ts +235 -0
  10. package/dist/extensions/ask-tools/index.ts +115 -0
  11. package/dist/extensions/auto-memory/contract.d.ts +51 -0
  12. package/dist/extensions/auto-memory/contract.d.ts.map +1 -0
  13. package/dist/extensions/auto-memory/contract.js +2 -0
  14. package/dist/extensions/auto-memory/contract.js.map +1 -0
  15. package/dist/extensions/auto-memory/contract.ts +56 -0
  16. package/dist/extensions/auto-memory/index.ts +969 -0
  17. package/dist/extensions/auto-memory/prompts.ts +202 -0
  18. package/dist/extensions/auto-memory/skip-rules.ts +297 -0
  19. package/dist/extensions/auto-memory/utils.ts +208 -0
  20. package/dist/extensions/auto-session-title/index.ts +83 -0
  21. package/dist/extensions/bash-ext/contract.d.ts +79 -0
  22. package/dist/extensions/bash-ext/contract.d.ts.map +1 -0
  23. package/dist/extensions/bash-ext/contract.js +2 -0
  24. package/dist/extensions/bash-ext/contract.js.map +1 -0
  25. package/dist/extensions/bash-ext/contract.ts +69 -0
  26. package/dist/extensions/bash-ext/index.ts +858 -0
  27. package/dist/extensions/claude-hooks-compat/config-loader.ts +49 -0
  28. package/dist/extensions/claude-hooks-compat/handler-runner.ts +377 -0
  29. package/dist/extensions/claude-hooks-compat/if-parser.ts +53 -0
  30. package/dist/extensions/claude-hooks-compat/index.ts +178 -0
  31. package/dist/extensions/claude-hooks-compat/matcher.ts +17 -0
  32. package/dist/extensions/claude-hooks-compat/stdin-builder.ts +27 -0
  33. package/dist/extensions/claude-hooks-compat/types.ts +77 -0
  34. package/dist/extensions/compaction-manager/config.ts +47 -0
  35. package/dist/extensions/compaction-manager/context-fold.ts +63 -0
  36. package/dist/extensions/compaction-manager/index.ts +151 -0
  37. package/dist/extensions/compaction-manager/microcompact.ts +49 -0
  38. package/dist/extensions/compaction-manager/reactive.ts +9 -0
  39. package/dist/extensions/compaction-manager/session-memory.ts +48 -0
  40. package/dist/extensions/coordinator/INTEGRATION.md +376 -0
  41. package/dist/extensions/coordinator/handler.test.ts +277 -0
  42. package/dist/extensions/coordinator/handler.ts +189 -0
  43. package/dist/extensions/coordinator/index.ts +261 -0
  44. package/dist/extensions/coordinator/types.d.ts +100 -0
  45. package/dist/extensions/coordinator/types.d.ts.map +1 -0
  46. package/dist/extensions/coordinator/types.js +2 -0
  47. package/dist/extensions/coordinator/types.js.map +1 -0
  48. package/dist/extensions/coordinator/types.ts +72 -0
  49. package/dist/extensions/file-snapshot/index.ts +131 -0
  50. package/dist/extensions/file-time-guard/README.md +133 -0
  51. package/dist/extensions/file-time-guard/config.ts +13 -0
  52. package/dist/extensions/file-time-guard/index.ts +171 -0
  53. package/dist/extensions/hooks-engine/index.ts +117 -0
  54. package/dist/extensions/lsp/lsp/client/file-tracker.ts +70 -0
  55. package/dist/extensions/lsp/lsp/client/registry.ts +305 -0
  56. package/dist/extensions/lsp/lsp/client/runtime.ts +832 -0
  57. package/dist/extensions/lsp/lsp/config/resolver.ts +573 -0
  58. package/dist/extensions/lsp/lsp/contract.d.ts +101 -0
  59. package/dist/extensions/lsp/lsp/contract.d.ts.map +1 -0
  60. package/dist/extensions/lsp/lsp/contract.js +2 -0
  61. package/dist/extensions/lsp/lsp/contract.js.map +1 -0
  62. package/dist/extensions/lsp/lsp/contract.ts +103 -0
  63. package/dist/extensions/lsp/lsp/hooks/agent-end.ts +169 -0
  64. package/dist/extensions/lsp/lsp/hooks/diagnostics-mode.d.ts +10 -0
  65. package/dist/extensions/lsp/lsp/hooks/diagnostics-mode.d.ts.map +1 -0
  66. package/dist/extensions/lsp/lsp/hooks/diagnostics-mode.js +30 -0
  67. package/dist/extensions/lsp/lsp/hooks/diagnostics-mode.js.map +1 -0
  68. package/dist/extensions/lsp/lsp/hooks/diagnostics-mode.ts +41 -0
  69. package/dist/extensions/lsp/lsp/hooks/writethrough.ts +342 -0
  70. package/dist/extensions/lsp/lsp/index.ts +310 -0
  71. package/dist/extensions/lsp/lsp/lsp.test.ts +684 -0
  72. package/dist/extensions/lsp/lsp/monitoring/server-metrics.ts +176 -0
  73. package/dist/extensions/lsp/lsp/tools/lsp-tool.ts +402 -0
  74. package/dist/extensions/lsp/lsp/utils/dependency-resolver.ts +147 -0
  75. package/dist/extensions/lsp/lsp/utils/diagnostics-wait.ts +41 -0
  76. package/dist/extensions/lsp/lsp/utils/lsp-helpers.d.ts +20 -0
  77. package/dist/extensions/lsp/lsp/utils/lsp-helpers.d.ts.map +1 -0
  78. package/dist/extensions/lsp/lsp/utils/lsp-helpers.js +64 -0
  79. package/dist/extensions/lsp/lsp/utils/lsp-helpers.js.map +1 -0
  80. package/dist/extensions/lsp/lsp/utils/lsp-helpers.ts +76 -0
  81. package/dist/extensions/message-bridge/GUIDE.md +210 -0
  82. package/dist/extensions/message-bridge/index.ts +222 -0
  83. package/dist/extensions/output-guard/index.ts +446 -0
  84. package/dist/extensions/preview/index.ts +278 -0
  85. package/dist/extensions/rules-engine/MATCH_HISTORY_RECONCILIATION.md +111 -0
  86. package/dist/extensions/rules-engine/RULES-ENGINE-GUIDE.md +470 -0
  87. package/dist/extensions/rules-engine/cache.js +232 -0
  88. package/dist/extensions/rules-engine/cache.ts +38 -0
  89. package/dist/extensions/rules-engine/config.js +63 -0
  90. package/dist/extensions/rules-engine/config.ts +70 -0
  91. package/dist/extensions/rules-engine/index.js +1530 -0
  92. package/dist/extensions/rules-engine/index.ts +552 -0
  93. package/dist/extensions/rules-engine/injector.js +68 -0
  94. package/dist/extensions/rules-engine/injector.ts +74 -0
  95. package/dist/extensions/rules-engine/loader.js +179 -0
  96. package/dist/extensions/rules-engine/loader.ts +205 -0
  97. package/dist/extensions/rules-engine/matcher.js +534 -0
  98. package/dist/extensions/rules-engine/matcher.ts +52 -0
  99. package/dist/extensions/rules-engine/types.d.ts +156 -0
  100. package/dist/extensions/rules-engine/types.d.ts.map +1 -0
  101. package/dist/extensions/rules-engine/types.js +2 -0
  102. package/dist/extensions/rules-engine/types.js.map +1 -0
  103. package/dist/extensions/rules-engine/types.ts +169 -0
  104. package/dist/extensions/session-supervisor/checker.ts +116 -0
  105. package/dist/extensions/session-supervisor/config.ts +45 -0
  106. package/dist/extensions/session-supervisor/index.ts +726 -0
  107. package/dist/extensions/session-supervisor/prompts.ts +132 -0
  108. package/dist/extensions/session-supervisor/scheduler.ts +69 -0
  109. package/dist/extensions/session-supervisor/types.ts +215 -0
  110. package/dist/extensions/subagent/README.md +172 -0
  111. package/dist/extensions/subagent/agents/explorer.md +25 -0
  112. package/dist/extensions/subagent/agents/guide.md +27 -0
  113. package/dist/extensions/subagent/agents/planner.md +37 -0
  114. package/dist/extensions/subagent/agents/reviewer.md +35 -0
  115. package/dist/extensions/subagent/agents/scout.md +50 -0
  116. package/dist/extensions/subagent/agents/verification.md +35 -0
  117. package/dist/extensions/subagent/agents/worker.md +24 -0
  118. package/dist/extensions/subagent/agents.ts +25 -0
  119. package/dist/extensions/subagent/index.ts +987 -0
  120. package/dist/extensions/subagent/prompts/implement-and-review.md +10 -0
  121. package/dist/extensions/subagent/prompts/implement.md +10 -0
  122. package/dist/extensions/subagent/prompts/scout-and-plan.md +9 -0
  123. package/dist/extensions/subagent-ext/contract.d.ts +2 -0
  124. package/dist/extensions/subagent-ext/contract.d.ts.map +1 -0
  125. package/dist/extensions/subagent-ext/contract.js +2 -0
  126. package/dist/extensions/subagent-ext/contract.js.map +1 -0
  127. package/dist/extensions/subagent-ext/contract.ts +1 -0
  128. package/dist/extensions/subagent-ext/index.ts +347 -0
  129. package/dist/extensions/subagent-shared/contract.d.ts +25 -0
  130. package/dist/extensions/subagent-shared/contract.d.ts.map +1 -0
  131. package/dist/extensions/subagent-shared/contract.js +2 -0
  132. package/dist/extensions/subagent-shared/contract.js.map +1 -0
  133. package/dist/extensions/subagent-shared/contract.ts +28 -0
  134. package/dist/extensions/subagent-shared/index.ts +4 -0
  135. package/dist/extensions/subagent-shared/render.ts +166 -0
  136. package/dist/extensions/subagent-shared/types.ts +35 -0
  137. package/dist/extensions/subagent-shared/utils.ts +112 -0
  138. package/dist/extensions/subagent-v2/contract.d.ts +2 -0
  139. package/dist/extensions/subagent-v2/contract.d.ts.map +1 -0
  140. package/dist/extensions/subagent-v2/contract.js +2 -0
  141. package/dist/extensions/subagent-v2/contract.js.map +1 -0
  142. package/dist/extensions/subagent-v2/contract.ts +1 -0
  143. package/dist/extensions/subagent-v2/index.ts +599 -0
  144. package/dist/extensions/todo-ext/contract.d.ts +27 -0
  145. package/dist/extensions/todo-ext/contract.d.ts.map +1 -0
  146. package/dist/extensions/todo-ext/contract.js +2 -0
  147. package/dist/extensions/todo-ext/contract.js.map +1 -0
  148. package/dist/extensions/todo-ext/contract.ts +30 -0
  149. package/dist/extensions/todo-ext/index.ts +419 -0
  150. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  151. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  152. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  153. package/examples/extensions/sandbox/package-lock.json +2 -2
  154. package/examples/extensions/sandbox/package.json +1 -1
  155. package/examples/extensions/with-deps/package-lock.json +2 -2
  156. package/examples/extensions/with-deps/package.json +1 -1
  157. package/package.json +6 -5
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Agent Permissions Extension
3
+ *
4
+ * Implements Claude Code-style permissionMode for sub-agents.
5
+ * Works with AgentConfig.permissionMode to control tool access.
6
+ *
7
+ * Modes:
8
+ * auto — default behavior, all tools allowed
9
+ * acceptEdits — auto-allow edit/write, block dangerous bash
10
+ * plan — read-only: block edit/write/bash
11
+ * dontAsk — auto-allow everything (no blocking)
12
+ * always-allow — same as dontAsk
13
+ * always-deny — block everything
14
+ */
15
+
16
+ import type { AgentConfig, ExtensionAPI, ExtensionContext } from "@dyyz1993/pi-coding-agent";
17
+
18
+ const READ_TOOLS = new Set(["read", "grep", "find", "ls", "glob"]);
19
+ const EDIT_TOOLS = new Set(["edit", "write"]);
20
+ const DANGEROUS_BASH_PATTERNS = [
21
+ /\brm\s+-rf\b/,
22
+ /\bgit\s+push\s+.*--force\b/,
23
+ /--no-verify/,
24
+ /\bsudo\b/,
25
+ /\bchmod\s+777\b/,
26
+ /\.env/,
27
+ /credentials/i,
28
+ ];
29
+
30
+ interface PermissionRule {
31
+ mode: string;
32
+ allowedTools: Set<string> | null;
33
+ blockedTools: Set<string> | null;
34
+ blockBashPatterns: RegExp[] | null;
35
+ }
36
+
37
+ const RULES: Record<string, PermissionRule> = {
38
+ auto: {
39
+ mode: "auto",
40
+ allowedTools: null,
41
+ blockedTools: null,
42
+ blockBashPatterns: DANGEROUS_BASH_PATTERNS,
43
+ },
44
+ acceptEdits: {
45
+ mode: "acceptEdits",
46
+ allowedTools: null,
47
+ blockedTools: null,
48
+ blockBashPatterns: DANGEROUS_BASH_PATTERNS,
49
+ },
50
+ plan: {
51
+ mode: "plan",
52
+ allowedTools: READ_TOOLS,
53
+ blockedTools: EDIT_TOOLS,
54
+ blockBashPatterns: null,
55
+ },
56
+ dontAsk: {
57
+ mode: "dontAsk",
58
+ allowedTools: null,
59
+ blockedTools: null,
60
+ blockBashPatterns: null,
61
+ },
62
+ "always-allow": {
63
+ mode: "always-allow",
64
+ allowedTools: null,
65
+ blockedTools: null,
66
+ blockBashPatterns: null,
67
+ },
68
+ "always-deny": {
69
+ mode: "always-deny",
70
+ allowedTools: new Set(),
71
+ blockedTools: null,
72
+ blockBashPatterns: null,
73
+ },
74
+ };
75
+
76
+ function matchesToolPattern(toolName: string, input: Record<string, unknown>, pattern: string): boolean {
77
+ const parenIdx = pattern.indexOf("(");
78
+ if (parenIdx === -1) {
79
+ if (pattern === "*") return true;
80
+ if (pattern.startsWith("*") && pattern.endsWith("*")) {
81
+ const middle = pattern.slice(1, -1);
82
+ return toolName.includes(middle);
83
+ }
84
+ if (pattern.startsWith("*")) {
85
+ const suffix = pattern.slice(1);
86
+ return toolName.endsWith(suffix);
87
+ }
88
+ if (pattern.endsWith("*")) {
89
+ const prefix = pattern.slice(0, -1);
90
+ return toolName.startsWith(prefix);
91
+ }
92
+ return pattern === toolName;
93
+ }
94
+
95
+ const baseTool = pattern.substring(0, parenIdx).trim();
96
+ if (baseTool !== toolName) return false;
97
+
98
+ const globPattern = pattern.substring(parenIdx + 1, pattern.lastIndexOf(")")).trim();
99
+ if (!globPattern || globPattern === "*") return true;
100
+
101
+ const parts = globPattern.split("|");
102
+ const inputStr = JSON.stringify(input);
103
+ const command = typeof input.command === "string" ? input.command : "";
104
+ const filePath = typeof input.filePath === "string" ? input.filePath : "";
105
+
106
+ // Try to match against relevant input fields
107
+ const targets = [command, filePath, inputStr].filter(Boolean);
108
+
109
+ for (const part of parts) {
110
+ const trimmed = part.trim();
111
+ if (!trimmed) continue;
112
+
113
+ // Check if pattern starts/ends with * to determine anchors
114
+ const startsWithWildcard = trimmed.startsWith("*");
115
+ const endsWithWildcard = trimmed.endsWith("*");
116
+
117
+ // Escape special regex characters EXCEPT: * and [] brackets
118
+ let regexStr = trimmed.replace(/[.+?^$()|\\]/g, "\\$&");
119
+
120
+ // Convert * to .*
121
+ regexStr = regexStr.replace(/\*/g, ".*");
122
+
123
+ // Add anchors based on wildcards
124
+ if (!startsWithWildcard) regexStr = "^" + regexStr;
125
+ if (!endsWithWildcard) regexStr = regexStr + "$";
126
+
127
+ const regex = new RegExp(regexStr);
128
+ for (const target of targets) {
129
+ if (regex.test(target)) return true;
130
+ }
131
+ }
132
+ return false;
133
+ }
134
+
135
+ function matchesDisallowedTool(
136
+ toolName: string,
137
+ input: Record<string, unknown>,
138
+ patterns: string[],
139
+ ): boolean {
140
+ for (const pattern of patterns) {
141
+ if (matchesToolPattern(toolName, input, pattern)) {
142
+ return true;
143
+ }
144
+ }
145
+ return false;
146
+ }
147
+
148
+ export function createPermissionHandler(agentConfig: AgentConfig) {
149
+ const mode = agentConfig.permissionMode ?? "auto";
150
+ const rule = RULES[mode];
151
+ if (!rule) return null;
152
+
153
+ const disallowedTools = agentConfig.disallowedTools ?? [];
154
+ const allowedToolList = agentConfig.tools;
155
+
156
+ return (event: { toolName: string; input: Record<string, unknown> }): { block: boolean; reason?: string } | null => {
157
+ if (allowedToolList && allowedToolList.length > 0) {
158
+ const isAllowed = allowedToolList.some((pattern) => matchesToolPattern(event.toolName, event.input, pattern));
159
+ if (!isAllowed) {
160
+ return {
161
+ block: true,
162
+ reason: `[agent:${agentConfig.name}] Tool "${event.toolName}" not in agent's tool whitelist. Allowed: ${allowedToolList.join(", ")}`,
163
+ };
164
+ }
165
+ }
166
+
167
+ if (rule.allowedTools !== null && !rule.allowedTools.has(event.toolName) && event.toolName !== "bash") {
168
+ const allowed = Array.from(rule.allowedTools).join(", ");
169
+ return {
170
+ block: true,
171
+ reason: `[${mode} mode] Tool "${event.toolName}" not allowed. Allowed: ${allowed}`,
172
+ };
173
+ }
174
+
175
+ if (rule.blockedTools !== null && rule.blockedTools.has(event.toolName)) {
176
+ return {
177
+ block: true,
178
+ reason: `[${mode} mode] Tool "${event.toolName}" is blocked (read-only mode).`,
179
+ };
180
+ }
181
+
182
+ if (event.toolName === "bash" && rule.mode === "plan") {
183
+ return {
184
+ block: true,
185
+ reason: `[plan mode] Bash is not allowed in plan mode.`,
186
+ };
187
+ }
188
+
189
+ if (event.toolName === "bash" && rule.blockBashPatterns) {
190
+ const command = event.input?.command;
191
+ if (typeof command === "string") {
192
+ for (const pat of rule.blockBashPatterns) {
193
+ if (pat.test(command)) {
194
+ return {
195
+ block: true,
196
+ reason: `[${mode} mode] Blocked dangerous bash command: ${command}`,
197
+ };
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ if (disallowedTools.length > 0 && matchesDisallowedTool(event.toolName, event.input, disallowedTools)) {
204
+ return {
205
+ block: true,
206
+ reason: `[disallowedTools] Tool "${event.toolName}" is explicitly disallowed.`,
207
+ };
208
+ }
209
+
210
+ return null;
211
+ };
212
+ }
213
+
214
+ export default function agentPermissions(pi: ExtensionAPI, ctx: ExtensionContext): void {
215
+ pi.on("tool_call", (event) => {
216
+ const vars = (event as { variables?: Record<string, string> }).variables;
217
+ const mode = vars?.["permissionMode"];
218
+ if (!mode || mode === "auto" || mode === "dontAsk" || mode === "always-allow") return undefined;
219
+
220
+ const handler = createPermissionHandler({
221
+ name: vars["agentName"] ?? "unknown",
222
+ description: "",
223
+ permissionMode: mode as AgentConfig["permissionMode"],
224
+ disallowedTools: vars["disallowedTools"]?.split(",").filter(Boolean),
225
+ tools: vars["allowedTools"]?.split(",").filter(Boolean),
226
+ } as AgentConfig);
227
+
228
+ if (!handler) return undefined;
229
+ const result = handler({ toolName: event.toolName, input: event.input });
230
+ if (result?.block) {
231
+ return { block: true, reason: result.reason };
232
+ }
233
+ return undefined;
234
+ });
235
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Ask Tools Extension
3
+ *
4
+ * 注册 ask-confirm / ask-select / ask-input / ask-editor / ask-notify 工具,
5
+ * 内部调用 ctx.ui.confirm / select / input / editor / notify 触发 UI 交互。
6
+ * ask-select 支持 multiple 参数切换单选/多选模式。
7
+ * 配合 message-bridge 扩展使用时,confirm/select/input/editor 调用会被推送到 Bridge。
8
+ */
9
+
10
+ import type { ExtensionAPI, ExtensionContext } from "@dyyz1993/pi-coding-agent";
11
+ import { type Static, Type } from "@sinclair/typebox";
12
+
13
+ const ConfirmParams = Type.Object({
14
+ title: Type.String({ description: "Short title for the confirmation" }),
15
+ question: Type.String({ description: "The question to ask" }),
16
+ });
17
+
18
+ const SelectParams = Type.Object({
19
+ title: Type.String({ description: "Short title for the selection" }),
20
+ options: Type.Array(Type.String(), { description: "List of options to choose from" }),
21
+ multiple: Type.Optional(Type.Boolean({ description: "Allow multi-select (checkbox mode). Default: false (single select)." })),
22
+ });
23
+
24
+ const InputParams = Type.Object({
25
+ title: Type.String({ description: "Short title for the input" }),
26
+ placeholder: Type.Optional(Type.String({ description: "Placeholder text" })),
27
+ });
28
+
29
+ const EditorParams = Type.Object({
30
+ title: Type.String({ description: "Short title for the editor" }),
31
+ prefill: Type.Optional(Type.String({ description: "Pre-filled content in the editor" })),
32
+ });
33
+
34
+ const NotifyParams = Type.Object({
35
+ message: Type.String({ description: "The message to display" }),
36
+ type: Type.Optional(Type.String({ description: "Notification type: 'info', 'warning', or 'error'" })),
37
+ });
38
+
39
+ export default function askToolsExtension(pi: ExtensionAPI) {
40
+ pi.registerTool({
41
+ name: "ask-confirm",
42
+ label: "Ask Confirm",
43
+ description: "Asks the user a yes/no confirmation question. Use when you need user approval before proceeding.",
44
+ parameters: ConfirmParams,
45
+ execute: async (_id: string, params: Static<typeof ConfirmParams>, _signal, _onUpdate, ctx: ExtensionContext) => {
46
+ const confirmed = await ctx.ui.confirm(params.title, params.question);
47
+ return {
48
+ content: [{ type: "text" as const, text: confirmed ? "User confirmed: yes" : "User confirmed: no" }],
49
+ details: undefined,
50
+ };
51
+ },
52
+ });
53
+
54
+ pi.registerTool({
55
+ name: "ask-select",
56
+ label: "Ask Select",
57
+ description:
58
+ "Asks the user to select option(s) from a list. By default single-select (returns one choice). Set multiple=true to allow selecting multiple options (checkbox style).",
59
+ parameters: SelectParams,
60
+ execute: async (_id: string, params: Static<typeof SelectParams>, _signal, _onUpdate, ctx: ExtensionContext) => {
61
+ const isMultiple = params.multiple === true;
62
+ const result = await ctx.ui.select(params.title, params.options, { multiple: isMultiple });
63
+ if (isMultiple) {
64
+ if (!result || !Array.isArray(result) || result.length === 0) {
65
+ return { content: [{ type: "text" as const, text: "User selected: (none)" }], details: undefined };
66
+ }
67
+ return { content: [{ type: "text" as const, text: `User selected: ${(result as string[]).join(", ")}` }], details: undefined };
68
+ }
69
+ const choice = result as string | undefined;
70
+ return { content: [{ type: "text" as const, text: `User selected: ${choice ?? "(cancelled)"}` }], details: undefined };
71
+ },
72
+ });
73
+
74
+ pi.registerTool({
75
+ name: "ask-input",
76
+ label: "Ask Input",
77
+ description: "Asks user for free-form text input. Use when you need user to provide text.",
78
+ parameters: InputParams,
79
+ execute: async (_id: string, params: Static<typeof InputParams>, _signal, _onUpdate, ctx: ExtensionContext) => {
80
+ const text = await ctx.ui.input(params.title, params.placeholder);
81
+ return {
82
+ content: [{ type: "text" as const, text: `User input: ${text ?? "(empty)"}` }],
83
+ details: undefined,
84
+ };
85
+ },
86
+ });
87
+
88
+ pi.registerTool({
89
+ name: "ask-editor",
90
+ label: "Ask Editor",
91
+ description: "Opens a multi-line editor for user to edit text. Use when you need user to edit longer text (code, JSON, configs, commit messages).",
92
+ parameters: EditorParams,
93
+ execute: async (_id: string, params: Static<typeof EditorParams>, _signal, _onUpdate, ctx: ExtensionContext) => {
94
+ const text = await ctx.ui.editor(params.title, params.prefill);
95
+ return {
96
+ content: [{ type: "text" as const, text: text ?? "(cancelled)" }],
97
+ details: undefined,
98
+ };
99
+ },
100
+ });
101
+
102
+ pi.registerTool({
103
+ name: "ask-notify",
104
+ label: "Ask Notify",
105
+ description: "Shows a notification to the user. Use for informational messages (fire-and-forget, does not wait for response).",
106
+ parameters: NotifyParams,
107
+ execute: async (_id: string, params: Static<typeof NotifyParams>, _signal, _onUpdate, ctx: ExtensionContext) => {
108
+ ctx.ui.notify(params.message, params.type as "info" | "warning" | "error" | undefined);
109
+ return {
110
+ content: [{ type: "text" as const, text: "Notified user" }],
111
+ details: undefined,
112
+ };
113
+ },
114
+ });
115
+ }
@@ -0,0 +1,51 @@
1
+ import type { ChannelContract } from "@dyyz1993/pi-coding-agent";
2
+ export declare const MEMORY_CHANNEL_NAME = "memory";
3
+ export interface MemoryFileInfo {
4
+ filename: string;
5
+ filePath: string;
6
+ description: string | null;
7
+ type: string | null;
8
+ mtimeMs: number;
9
+ }
10
+ export interface MemoryListResult {
11
+ type: "list_result";
12
+ files: MemoryFileInfo[];
13
+ entrypointContent: string | null;
14
+ memoryDir: string;
15
+ }
16
+ export interface MemoryUserRememberParams {
17
+ sourceSessionId?: string;
18
+ sourceMessageIds?: string[];
19
+ content?: string;
20
+ }
21
+ export interface BookmarkCreatingEvent {
22
+ type: "bookmark_creating";
23
+ }
24
+ export interface MemoryUpdatedEvent {
25
+ type: "memory_updated";
26
+ files: MemoryFileInfo[];
27
+ }
28
+ export interface MemoryUpdateFailedEvent {
29
+ type: "memory_update_failed";
30
+ reason: string;
31
+ }
32
+ export interface MemoryChannelContract extends ChannelContract {
33
+ methods: {
34
+ "memory.list": {
35
+ params: Record<string, never>;
36
+ return: MemoryListResult;
37
+ };
38
+ "memory.userRemember": {
39
+ params: MemoryUserRememberParams;
40
+ return: {
41
+ ok: boolean;
42
+ };
43
+ };
44
+ };
45
+ events: {
46
+ bookmark_creating: BookmarkCreatingEvent;
47
+ memory_updated: MemoryUpdatedEvent;
48
+ memory_update_failed: MemoryUpdateFailedEvent;
49
+ };
50
+ }
51
+ //# sourceMappingURL=contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAEjE,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAE5C,MAAM,WAAW,cAAc;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,wBAAwB;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,mBAAmB,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,cAAc,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACvC,IAAI,EAAE,sBAAsB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAsB,SAAQ,eAAe;IAC7D,OAAO,EAAE;QACR,aAAa,EAAE;YACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9B,MAAM,EAAE,gBAAgB,CAAC;SACzB,CAAC;QACF,qBAAqB,EAAE;YACtB,MAAM,EAAE,wBAAwB,CAAC;YACjC,MAAM,EAAE;gBAAE,EAAE,EAAE,OAAO,CAAA;aAAE,CAAC;SACxB,CAAC;KACF,CAAC;IACF,MAAM,EAAE;QACP,iBAAiB,EAAE,qBAAqB,CAAC;QACzC,cAAc,EAAE,kBAAkB,CAAC;QACnC,oBAAoB,EAAE,uBAAuB,CAAC;KAC9C,CAAC;CACF","sourcesContent":["import type { ChannelContract } from \"@dyyz1993/pi-coding-agent\";\n\nexport const MEMORY_CHANNEL_NAME = \"memory\";\n\nexport interface MemoryFileInfo {\n\tfilename: string;\n\tfilePath: string;\n\tdescription: string | null;\n\ttype: string | null;\n\tmtimeMs: number;\n}\n\nexport interface MemoryListResult {\n\ttype: \"list_result\";\n\tfiles: MemoryFileInfo[];\n\tentrypointContent: string | null;\n\tmemoryDir: string;\n}\n\nexport interface MemoryUserRememberParams {\n\tsourceSessionId?: string;\n\tsourceMessageIds?: string[];\n\tcontent?: string;\n}\n\nexport interface BookmarkCreatingEvent {\n\ttype: \"bookmark_creating\";\n}\n\nexport interface MemoryUpdatedEvent {\n\ttype: \"memory_updated\";\n\tfiles: MemoryFileInfo[];\n}\n\nexport interface MemoryUpdateFailedEvent {\n\ttype: \"memory_update_failed\";\n\treason: string;\n}\n\nexport interface MemoryChannelContract extends ChannelContract {\n\tmethods: {\n\t\t\"memory.list\": {\n\t\t\tparams: Record<string, never>;\n\t\t\treturn: MemoryListResult;\n\t\t};\n\t\t\"memory.userRemember\": {\n\t\t\tparams: MemoryUserRememberParams;\n\t\t\treturn: { ok: boolean };\n\t\t};\n\t};\n\tevents: {\n\t\tbookmark_creating: BookmarkCreatingEvent;\n\t\tmemory_updated: MemoryUpdatedEvent;\n\t\tmemory_update_failed: MemoryUpdateFailedEvent;\n\t};\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export const MEMORY_CHANNEL_NAME = "memory";
2
+ //# sourceMappingURL=contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract.js","sourceRoot":"","sources":["contract.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC","sourcesContent":["import type { ChannelContract } from \"@dyyz1993/pi-coding-agent\";\n\nexport const MEMORY_CHANNEL_NAME = \"memory\";\n\nexport interface MemoryFileInfo {\n\tfilename: string;\n\tfilePath: string;\n\tdescription: string | null;\n\ttype: string | null;\n\tmtimeMs: number;\n}\n\nexport interface MemoryListResult {\n\ttype: \"list_result\";\n\tfiles: MemoryFileInfo[];\n\tentrypointContent: string | null;\n\tmemoryDir: string;\n}\n\nexport interface MemoryUserRememberParams {\n\tsourceSessionId?: string;\n\tsourceMessageIds?: string[];\n\tcontent?: string;\n}\n\nexport interface BookmarkCreatingEvent {\n\ttype: \"bookmark_creating\";\n}\n\nexport interface MemoryUpdatedEvent {\n\ttype: \"memory_updated\";\n\tfiles: MemoryFileInfo[];\n}\n\nexport interface MemoryUpdateFailedEvent {\n\ttype: \"memory_update_failed\";\n\treason: string;\n}\n\nexport interface MemoryChannelContract extends ChannelContract {\n\tmethods: {\n\t\t\"memory.list\": {\n\t\t\tparams: Record<string, never>;\n\t\t\treturn: MemoryListResult;\n\t\t};\n\t\t\"memory.userRemember\": {\n\t\t\tparams: MemoryUserRememberParams;\n\t\t\treturn: { ok: boolean };\n\t\t};\n\t};\n\tevents: {\n\t\tbookmark_creating: BookmarkCreatingEvent;\n\t\tmemory_updated: MemoryUpdatedEvent;\n\t\tmemory_update_failed: MemoryUpdateFailedEvent;\n\t};\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import type { ChannelContract } from "@dyyz1993/pi-coding-agent";
2
+
3
+ export const MEMORY_CHANNEL_NAME = "memory";
4
+
5
+ export interface MemoryFileInfo {
6
+ filename: string;
7
+ filePath: string;
8
+ description: string | null;
9
+ type: string | null;
10
+ mtimeMs: number;
11
+ }
12
+
13
+ export interface MemoryListResult {
14
+ type: "list_result";
15
+ files: MemoryFileInfo[];
16
+ entrypointContent: string | null;
17
+ memoryDir: string;
18
+ }
19
+
20
+ export interface MemoryUserRememberParams {
21
+ sourceSessionId?: string;
22
+ sourceMessageIds?: string[];
23
+ content?: string;
24
+ }
25
+
26
+ export interface BookmarkCreatingEvent {
27
+ type: "bookmark_creating";
28
+ }
29
+
30
+ export interface MemoryUpdatedEvent {
31
+ type: "memory_updated";
32
+ files: MemoryFileInfo[];
33
+ }
34
+
35
+ export interface MemoryUpdateFailedEvent {
36
+ type: "memory_update_failed";
37
+ reason: string;
38
+ }
39
+
40
+ export interface MemoryChannelContract extends ChannelContract {
41
+ methods: {
42
+ "memory.list": {
43
+ params: Record<string, never>;
44
+ return: MemoryListResult;
45
+ };
46
+ "memory.userRemember": {
47
+ params: MemoryUserRememberParams;
48
+ return: { ok: boolean };
49
+ };
50
+ };
51
+ events: {
52
+ bookmark_creating: BookmarkCreatingEvent;
53
+ memory_updated: MemoryUpdatedEvent;
54
+ memory_update_failed: MemoryUpdateFailedEvent;
55
+ };
56
+ }