pi-usereq 0.61.0 → 0.62.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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # PI-useReq/pi-usereq (0.61.0)
1
+ # PI-useReq/pi-usereq (0.62.0)
2
2
 
3
3
  <p align="center">
4
4
  <img src="https://img.shields.io/badge/python-3.11%2B-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python 3.11+">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-usereq",
3
- "version": "0.61.0",
3
+ "version": "0.62.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/Ogekuri/PI-useReq.git"
@@ -209,3 +209,49 @@ export function restorePersistedPromptCommandRuntimeStateForSession(
209
209
  }
210
210
  return undefined;
211
211
  }
212
+
213
+ /**
214
+ * @brief Describes the loosely-typed extension-api surface persisted for model re-application.
215
+ * @details Stores only the session-scoped model appliers plus thinking-level probe needed to re-apply one captured selection after session replacement. The structural shape avoids importing concrete pi SDK types into this process-scoped module. The interface is compile-time only and introduces no runtime cost.
216
+ * @satisfies REQ-367, REQ-368, REQ-369
217
+ */
218
+ export interface PersistedPromptCommandRuntimeApi {
219
+ setModel?: (model: unknown) => unknown;
220
+ setThinkingLevel?: (level: unknown) => unknown;
221
+ getThinkingLevel?: () => unknown;
222
+ }
223
+
224
+ /**
225
+ * @brief Defines the global property used for latest live extension-api persistence.
226
+ * @details The property lives on `globalThis` because pi invalidates the extension api captured by one session's extension instance whenever that session is replaced and reloads the extension against the replacement session while the host process persists. Access complexity is O(1).
227
+ */
228
+ const PI_USEREQ_PROMPT_COMMAND_RUNTIME_API_KEY = "__piUsereqPromptCommandRuntimeApi";
229
+
230
+ /**
231
+ * @brief Writes the latest live extension api into process-scoped persistence.
232
+ * @details Replaces the stored loosely-typed model-api surface so model re-application helpers always bind to the extension instance of the currently active session runner and never to an api invalidated by session replacement. Runtime is O(1). Side effect: mutates process-scoped state.
233
+ * @param[in] runtimeApi {PersistedPromptCommandRuntimeApi | undefined} Latest extension-api surface written at extension bind time, or undefined to clear the stored surface.
234
+ * @return {void} No return value.
235
+ * @satisfies REQ-367, REQ-368, REQ-369
236
+ */
237
+ export function writePersistedPromptCommandRuntimeApi(
238
+ runtimeApi: PersistedPromptCommandRuntimeApi | undefined,
239
+ ): void {
240
+ const globalState = globalThis as typeof globalThis & {
241
+ __piUsereqPromptCommandRuntimeApi?: PersistedPromptCommandRuntimeApi | undefined;
242
+ };
243
+ globalState[PI_USEREQ_PROMPT_COMMAND_RUNTIME_API_KEY] = runtimeApi;
244
+ }
245
+
246
+ /**
247
+ * @brief Reads the latest live extension api from process-scoped persistence.
248
+ * @details Returns the extension-api surface written by the most recent extension bind so post-switch model re-application uses a session-scoped api that remains valid after session replacement, returning undefined so callers degrade to their own captured api. Runtime is O(1). No external state is mutated.
249
+ * @return {PersistedPromptCommandRuntimeApi | undefined} Latest stored extension-api surface, or undefined when no extension has bound in this process.
250
+ * @satisfies REQ-367, REQ-368, REQ-369
251
+ */
252
+ export function readPersistedPromptCommandRuntimeApi(): PersistedPromptCommandRuntimeApi | undefined {
253
+ const globalState = globalThis as typeof globalThis & {
254
+ __piUsereqPromptCommandRuntimeApi?: PersistedPromptCommandRuntimeApi | undefined;
255
+ };
256
+ return globalState[PI_USEREQ_PROMPT_COMMAND_RUNTIME_API_KEY];
257
+ }
package/src/index.ts CHANGED
@@ -145,8 +145,11 @@ import { PROMPT_COMMAND_NAMES } from "./core/prompt-command-catalog.js";
145
145
  import { resolveRuntimeGitPath } from "./core/runtime-project-paths.js";
146
146
  import {
147
147
  clearPersistedPromptCommandRuntimeState,
148
+ readPersistedPromptCommandRuntimeApi,
148
149
  readPersistedPromptCommandRuntimeState,
150
+ writePersistedPromptCommandRuntimeApi,
149
151
  writePersistedPromptCommandRuntimeState,
152
+ type PersistedPromptCommandRuntimeApi,
150
153
  } from "./core/prompt-command-state.js";
151
154
  import { ensureBundledResourcesAccessible, readBundledPromptDescription } from "./core/resources.js";
152
155
  import { ReqError } from "./core/errors.js";
@@ -3148,8 +3151,8 @@ function resolveCurrentThinkingLevel(pi: ExtensionAPI, ctx: unknown): string | u
3148
3151
 
3149
3152
  /**
3150
3153
  * @brief Builds the loosely-typed model-selection surface from the runtime API plus context.
3151
- * @details Wraps `setModel` and `setThinkingLevel` with defensive function probes so the surface only exposes appliers the running host actually implements, and copies the context model, thinking level, and model registry used by the guarded re-apply comparison. Returns undefined when no context is available so re-application degrades to a not-attempted skip. Runtime is O(1). No external state is mutated.
3152
- * @param[in] pi {ExtensionAPI} Active extension API instance supplying the session-scoped model appliers.
3154
+ * @details Wraps `setModel` and `setThinkingLevel` with defensive function probes so the surface only exposes appliers the running host actually implements, and copies the context model, thinking level, and model registry used by the guarded re-apply comparison. The supplied api MUST be the latest live extension api bound to the active session runner because pi invalidates captured extension apis after session replacement. Returns undefined when no context is available so re-application degrades to a not-attempted skip. Runtime is O(1). No external state is mutated.
3155
+ * @param[in] pi {ExtensionAPI} Latest live extension api instance supplying the session-scoped model appliers; after session replacement callers pass the rebound api rather than a captured pre-switch api.
3153
3156
  * @param[in] ctx {unknown} Active extension or command context supplying model probes.
3154
3157
  * @return {PromptCommandModelSelectionSurface | undefined} Re-apply surface, or undefined when no context exists.
3155
3158
  * @satisfies REQ-367, REQ-370, REQ-371
@@ -3182,10 +3185,10 @@ function resolvePromptCommandModelSurface(
3182
3185
 
3183
3186
  /**
3184
3187
  * @brief Re-applies one captured model selection onto the active post-switch session.
3185
- * @details Builds the guarded re-apply surface from the runtime API plus context, forwards the captured selection plus thinking level into `reapplyPromptCommandSessionSelection(...)`, and routes every warning through `notifyContextSafely(...)` so stale replacement contexts after session replacement never abort orchestration. Runtime is O(1) plus one awaited model mutation. Side effects include session-scoped model and thinking-level mutation plus stale-safe warning notifications.
3188
+ * @details Builds the guarded re-apply surface from the latest process-scoped extension api plus context, preferring the api written by the most recent extension bind because pi invalidates the api captured before session replacement, and falls back to the caller-supplied api for hosts that do not rebind. Forwards the captured selection plus thinking level into `reapplyPromptCommandSessionSelection(...)` and routes every warning through `notifyContextSafely(...)` so stale replacement contexts after session replacement never abort orchestration. Runtime is O(1) plus one awaited model mutation. Side effects include session-scoped model and thinking-level mutation plus stale-safe warning notifications.
3186
3189
  * @param[in] selection {PromptCommandModelSelection | undefined} Captured model provider plus identifier.
3187
3190
  * @param[in] thinkingLevel {string | undefined} Captured thinking level.
3188
- * @param[in] pi {ExtensionAPI} Active extension API instance.
3191
+ * @param[in] pi {ExtensionAPI} Extension api captured by the running handler, used only as fallback when no rebound api is stored.
3189
3192
  * @param[in] ctx {unknown} Active extension or command context used for probes and warning delivery.
3190
3193
  * @return {Promise<void>} Promise resolved once the guarded re-application completed.
3191
3194
  * @satisfies REQ-367, REQ-368, REQ-369, REQ-370, REQ-371, REQ-372
@@ -3196,10 +3199,12 @@ async function reapplyCapturedPromptModelSelection(
3196
3199
  pi: ExtensionAPI,
3197
3200
  ctx: unknown,
3198
3201
  ): Promise<void> {
3202
+ const liveApi = readPersistedPromptCommandRuntimeApi();
3203
+ const activeApi = liveApi ?? pi;
3199
3204
  await reapplyPromptCommandSessionSelection({
3200
3205
  selection,
3201
3206
  thinkingLevel,
3202
- surface: resolvePromptCommandModelSurface(pi, ctx),
3207
+ surface: resolvePromptCommandModelSurface(activeApi as ExtensionAPI, ctx),
3203
3208
  notifyWarning: (message) => {
3204
3209
  notifyContextSafely(ctx as ExtensionContext, message, "error");
3205
3210
  },
@@ -5132,12 +5137,13 @@ function registerConfigCommands(
5132
5137
 
5133
5138
  /**
5134
5139
  * @brief Registers the complete pi-usereq extension.
5135
- * @details Validates installation-owned bundled resources, registers the specialized `req-reset` and `req-references` commands plus bundled prompt-backed commands and agent tools, conditionally registers config-gated debug tool wrapper commands when the current project enables them, registers configuration commands, registers the configurable notification-sound shortcut when the runtime supports shortcuts, and installs shared wrappers for all supported pi lifecycle hooks so status telemetry, context usage, prompt timing, cumulative runtime, prompt-specific Pushover metadata, tool-result debug logging, and prompt-orchestration effects remain synchronized with runtime events. Runtime is O(h) in hook count during registration. Side effects include filesystem reads, command/tool/shortcut registration, UI updates, active-tool changes, optional debug-log writes, and timer scheduling.
5140
+ * @details Persists the live extension api into process-scoped storage on every bind so model re-application after session replacement binds to the api of the currently active session runner instead of an invalidated captured api, then validates installation-owned bundled resources, registers the specialized `req-reset` and `req-references` commands plus bundled prompt-backed commands and agent tools, conditionally registers config-gated debug tool wrapper commands when the current project enables them, registers configuration commands, registers the configurable notification-sound shortcut when the runtime supports shortcuts, and installs shared wrappers for all supported pi lifecycle hooks so status telemetry, context usage, prompt timing, cumulative runtime, prompt-specific Pushover metadata, tool-result debug logging, and prompt-orchestration effects remain synchronized with runtime events. Runtime is O(h) in hook count during registration. Side effects include filesystem reads, command/tool/shortcut registration, UI updates, active-tool changes, process-scoped extension-api persistence, optional debug-log writes, and timer scheduling.
5136
5141
  * @param[in] pi {ExtensionAPI} Active extension API instance.
5137
5142
  * @return {void} No return value.
5138
5143
  * @satisfies DES-002, DES-015, REQ-004, REQ-005, REQ-009, REQ-044, REQ-067, REQ-068, REQ-109, REQ-111, REQ-112, REQ-113, REQ-114, REQ-115, REQ-116, REQ-117, REQ-118, REQ-119, REQ-120, REQ-121, REQ-122, REQ-123, REQ-124, REQ-125, REQ-126, REQ-127, REQ-128, REQ-131, REQ-132, REQ-133, REQ-134, REQ-137, REQ-159, REQ-163, REQ-164, REQ-165, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-174, REQ-179, REQ-180, REQ-184, REQ-188, REQ-190, REQ-191, REQ-192, REQ-193, REQ-194, REQ-195, REQ-196, REQ-197, REQ-236, REQ-237, REQ-238, REQ-239, REQ-240, REQ-241, REQ-242, REQ-243, REQ-244, REQ-245, REQ-246, REQ-247, REQ-298, REQ-299, REQ-300, REQ-301, REQ-302, REQ-303, REQ-304, REQ-305, REQ-306, REQ-312, REQ-313, REQ-323, REQ-324, REQ-325, REQ-326, REQ-327
5139
5144
  */
5140
5145
  export default function piUsereqExtension(pi: ExtensionAPI): void {
5146
+ writePersistedPromptCommandRuntimeApi(pi as unknown as PersistedPromptCommandRuntimeApi);
5141
5147
  const statusController = createPiUsereqStatusController();
5142
5148
  ensureBundledResourcesAccessible();
5143
5149
  registerReqResetCommand(pi, statusController);