gsd-pi 2.11.0 → 2.12.0

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 (113) hide show
  1. package/dist/onboarding.js +3 -0
  2. package/dist/resources/extensions/bg-shell/index.ts +51 -7
  3. package/dist/resources/extensions/gsd/auto.ts +159 -2
  4. package/dist/resources/extensions/gsd/commands.ts +9 -3
  5. package/dist/resources/extensions/gsd/doctor.ts +60 -3
  6. package/dist/resources/extensions/gsd/guided-flow.ts +81 -9
  7. package/dist/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  8. package/dist/resources/extensions/gsd/preferences.ts +192 -0
  9. package/dist/resources/extensions/gsd/prompt-loader.ts +28 -1
  10. package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  11. package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  12. package/dist/resources/extensions/gsd/prompts/discuss.md +10 -8
  13. package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
  14. package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  15. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  16. package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  17. package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  18. package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  19. package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  20. package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  21. package/dist/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  22. package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  23. package/dist/resources/extensions/gsd/prompts/queue.md +3 -1
  24. package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  25. package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
  26. package/dist/resources/extensions/gsd/templates/context.md +1 -1
  27. package/dist/resources/extensions/gsd/templates/state.md +3 -3
  28. package/dist/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  29. package/dist/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  30. package/dist/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  31. package/dist/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  32. package/dist/resources/extensions/gsd/types.ts +109 -0
  33. package/dist/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  34. package/dist/resources/extensions/search-the-web/provider.ts +19 -2
  35. package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  36. package/dist/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  37. package/dist/resources/extensions/search-the-web/tool-search.ts +62 -3
  38. package/dist/wizard.js +1 -0
  39. package/package.json +1 -1
  40. package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
  41. package/packages/pi-agent-core/dist/agent-loop.js +169 -55
  42. package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
  43. package/packages/pi-agent-core/dist/agent.d.ts +13 -1
  44. package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
  45. package/packages/pi-agent-core/dist/agent.js +16 -0
  46. package/packages/pi-agent-core/dist/agent.js.map +1 -1
  47. package/packages/pi-agent-core/dist/types.d.ts +91 -1
  48. package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
  49. package/packages/pi-agent-core/dist/types.js.map +1 -1
  50. package/packages/pi-agent-core/src/agent-loop.ts +273 -63
  51. package/packages/pi-agent-core/src/agent.ts +24 -0
  52. package/packages/pi-agent-core/src/types.ts +98 -0
  53. package/packages/pi-ai/dist/env-api-keys.js +1 -0
  54. package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
  55. package/packages/pi-ai/dist/models.generated.d.ts +314 -0
  56. package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
  57. package/packages/pi-ai/dist/models.generated.js +236 -0
  58. package/packages/pi-ai/dist/models.generated.js.map +1 -1
  59. package/packages/pi-ai/dist/types.d.ts +1 -1
  60. package/packages/pi-ai/dist/types.d.ts.map +1 -1
  61. package/packages/pi-ai/dist/types.js.map +1 -1
  62. package/packages/pi-ai/src/env-api-keys.ts +1 -0
  63. package/packages/pi-ai/src/models.generated.ts +236 -0
  64. package/packages/pi-ai/src/types.ts +2 -1
  65. package/packages/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  66. package/packages/pi-coding-agent/dist/cli/args.js +1 -0
  67. package/packages/pi-coding-agent/dist/cli/args.js.map +1 -1
  68. package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -0
  69. package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  70. package/packages/pi-coding-agent/dist/core/agent-session.js +69 -8
  71. package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  72. package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  73. package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -0
  74. package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  75. package/packages/pi-coding-agent/src/cli/args.ts +1 -0
  76. package/packages/pi-coding-agent/src/core/agent-session.ts +76 -7
  77. package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
  78. package/src/resources/extensions/bg-shell/index.ts +51 -7
  79. package/src/resources/extensions/gsd/auto.ts +159 -2
  80. package/src/resources/extensions/gsd/commands.ts +9 -3
  81. package/src/resources/extensions/gsd/doctor.ts +60 -3
  82. package/src/resources/extensions/gsd/guided-flow.ts +81 -9
  83. package/src/resources/extensions/gsd/post-unit-hooks.ts +449 -0
  84. package/src/resources/extensions/gsd/preferences.ts +192 -0
  85. package/src/resources/extensions/gsd/prompt-loader.ts +28 -1
  86. package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
  87. package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -3
  88. package/src/resources/extensions/gsd/prompts/discuss.md +10 -8
  89. package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
  90. package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +3 -1
  91. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +3 -1
  92. package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +3 -1
  93. package/src/resources/extensions/gsd/prompts/guided-execute-task.md +3 -1
  94. package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +4 -2
  95. package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +3 -1
  96. package/src/resources/extensions/gsd/prompts/guided-research-slice.md +3 -1
  97. package/src/resources/extensions/gsd/prompts/plan-milestone.md +9 -12
  98. package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -3
  99. package/src/resources/extensions/gsd/prompts/queue.md +3 -1
  100. package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
  101. package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
  102. package/src/resources/extensions/gsd/templates/context.md +1 -1
  103. package/src/resources/extensions/gsd/templates/state.md +3 -3
  104. package/src/resources/extensions/gsd/tests/doctor.test.ts +115 -1
  105. package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +297 -0
  106. package/src/resources/extensions/gsd/tests/preferences-hooks.test.ts +226 -0
  107. package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +12 -0
  108. package/src/resources/extensions/gsd/types.ts +109 -0
  109. package/src/resources/extensions/search-the-web/command-search-provider.ts +8 -4
  110. package/src/resources/extensions/search-the-web/provider.ts +19 -2
  111. package/src/resources/extensions/search-the-web/tool-fetch-page.ts +62 -0
  112. package/src/resources/extensions/search-the-web/tool-llm-context.ts +62 -3
  113. package/src/resources/extensions/search-the-web/tool-search.ts +62 -3
@@ -24,7 +24,7 @@ import { calculateContextTokens, collectEntriesForBranchSummary, compact, estima
24
24
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
25
25
  import { exportSessionToHtml } from "./export-html/index.js";
26
26
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
27
- import { ExtensionRunner, wrapRegisteredTools, wrapToolsWithExtensions, } from "./extensions/index.js";
27
+ import { ExtensionRunner, wrapRegisteredTools, } from "./extensions/index.js";
28
28
  import { FallbackResolver } from "./fallback-resolver.js";
29
29
  import { expandPromptTemplate } from "./prompt-templates.js";
30
30
  import { getLatestCompactionEntry } from "./session-manager.js";
@@ -119,6 +119,10 @@ export class AgentSession {
119
119
  // Always subscribe to agent events for internal handling
120
120
  // (session persistence, extensions, auto-compaction, retry logic)
121
121
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
122
+ // Install tool hooks that await the event queue before emitting extension events.
123
+ // This ensures extensions always see settled state (e.g., assistant message appended)
124
+ // even when tools execute in parallel.
125
+ this._installAgentToolHooks();
122
126
  this._buildRuntime({
123
127
  activeToolNames: this._initialActiveToolNames,
124
128
  includeAllExtensionTools: true,
@@ -246,6 +250,66 @@ export class AgentSession {
246
250
  this._retryPromise = undefined;
247
251
  }
248
252
  }
253
+ /**
254
+ * Install beforeToolCall/afterToolCall hooks on the Agent.
255
+ *
256
+ * These hooks await `_agentEventQueue` before emitting extension events,
257
+ * ensuring that all prior events (including `message_end` which appends
258
+ * the assistant message) have fully settled. This prevents a race condition
259
+ * in parallel tool execution where extension `tool_call` handlers could
260
+ * see stale agent state.
261
+ */
262
+ _installAgentToolHooks() {
263
+ this.agent.setBeforeToolCall(async ({ toolCall, args }) => {
264
+ // Wait for all queued agent events to settle before emitting to extensions
265
+ await this._agentEventQueue;
266
+ if (!this._extensionRunner?.hasHandlers("tool_call"))
267
+ return undefined;
268
+ try {
269
+ const callResult = await this._extensionRunner.emitToolCall({
270
+ type: "tool_call",
271
+ toolName: toolCall.name,
272
+ toolCallId: toolCall.id,
273
+ input: args,
274
+ });
275
+ if (callResult?.block) {
276
+ return {
277
+ block: true,
278
+ reason: callResult.reason || "Tool execution was blocked by an extension",
279
+ };
280
+ }
281
+ }
282
+ catch (err) {
283
+ if (err instanceof Error) {
284
+ return { block: true, reason: err.message };
285
+ }
286
+ return { block: true, reason: `Extension failed, blocking execution: ${String(err)}` };
287
+ }
288
+ return undefined;
289
+ });
290
+ this.agent.setAfterToolCall(async ({ toolCall, args, result, isError }) => {
291
+ // Wait for all queued agent events to settle
292
+ await this._agentEventQueue;
293
+ if (!this._extensionRunner?.hasHandlers("tool_result"))
294
+ return undefined;
295
+ const resultResult = await this._extensionRunner.emitToolResult({
296
+ type: "tool_result",
297
+ toolName: toolCall.name,
298
+ toolCallId: toolCall.id,
299
+ input: args,
300
+ content: result.content,
301
+ details: result.details,
302
+ isError,
303
+ });
304
+ if (resultResult) {
305
+ return {
306
+ content: resultResult.content ?? undefined,
307
+ details: resultResult.details ?? undefined,
308
+ };
309
+ }
310
+ return undefined;
311
+ });
312
+ }
249
313
  /** Extract text content from a message */
250
314
  _getUserMessageText(message) {
251
315
  if (message.role !== "user")
@@ -1724,13 +1788,10 @@ export class AgentSession {
1724
1788
  for (const tool of wrappedExtensionTools) {
1725
1789
  toolRegistry.set(tool.name, tool);
1726
1790
  }
1727
- if (this._extensionRunner) {
1728
- const wrappedAllTools = wrapToolsWithExtensions(Array.from(toolRegistry.values()), this._extensionRunner);
1729
- this._toolRegistry = new Map(wrappedAllTools.map((tool) => [tool.name, tool]));
1730
- }
1731
- else {
1732
- this._toolRegistry = toolRegistry;
1733
- }
1791
+ // Tool interception (tool_call/tool_result extension events) is handled by
1792
+ // beforeToolCall/afterToolCall hooks installed in _installAgentToolHooks(),
1793
+ // which await _agentEventQueue for safe parallel execution.
1794
+ this._toolRegistry = toolRegistry;
1734
1795
  const nextActiveToolNames = options?.activeToolNames
1735
1796
  ? [...options.activeToolNames]
1736
1797
  : [...previousActiveToolNames];