pi-usereq 0.86.0 → 0.88.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 +9 -7
- package/package.json +1 -1
- package/src/core/pi-notify.ts +71 -18
- package/src/core/req-reset-command.ts +23 -0
- package/src/index.ts +112 -10
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# PI-useReq/pi-usereq (0.
|
|
1
|
+
# PI-useReq/pi-usereq (0.88.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+">
|
|
@@ -60,7 +60,7 @@ in sync with the repository. All capabilities are exposed as slash commands and
|
|
|
60
60
|
- **11 built-in agent tools** - token counting, summarization, compression, construct search, and static-check tools for explicit files or for the configured project surface.
|
|
61
61
|
- **Interactive configuration menu** - `/pi-usereq` manages local (`<base-path>/.pi-usereq.json`) and global (`~/.config/pi-usereq/config.json`) configuration with no manual JSON editing required.
|
|
62
62
|
- **Worktree-isolated runs** - prompt-command executions run in an isolated git worktree (created with `<prefix><project>-<branch>-<YYYYMMDDHHMMSS>` names) and are merged back with a stash-assisted fast-forward on success.
|
|
63
|
-
- **Automatic commit guidance** - `AUTO_GIT_COMMIT=enable` (default) injects structured commit instructions (`<TYPE>(<COMPONENT>)
|
|
63
|
+
- **Automatic commit guidance** - `AUTO_GIT_COMMIT=enable` (default) injects structured commit instructions (`<TYPE>(<COMPONENT>)<BREAKING>: <DESCRIPTION> [useReq]`) into every prompt; disabling it forces read-only git behavior and turns worktree orchestration off.
|
|
64
64
|
- **Notifications** - desktop notify command, sound effects (levels `none`/`low`/`mid`/`high`, default `alt+s` toggle) and Pushover push messages on prompt completion, interruption, or failure.
|
|
65
65
|
- **Runtime status bar** - the extension renders its workflow state, current branch, context usage, elapsed time, and sound level in the pi status line.
|
|
66
66
|
- **Context-occupancy guardrails** - the `Context Files` settings row and every command invocation summary show the measured `[<percent>% context]` occupancy of the enabled context files against the selected model's max input context (or the documented 1,000,000-token fallback); prompt dispatch is aborted before worktree creation when the enabled context files exceed that limit.
|
|
@@ -72,7 +72,9 @@ in sync with the repository. All capabilities are exposed as slash commands and
|
|
|
72
72
|
Each `req-*` command is invoked as `/req-<name> <User Request>` inside pi. Prompt commands first run git validation and the
|
|
73
73
|
prompt-specific required-document checks, then (when `Auto git commit` and `Git worktree` are enabled) switch the session into an
|
|
74
74
|
isolated worktree, render the bundled prompt with the project context, and on success merge the changes back and leave the
|
|
75
|
-
repository clean.
|
|
75
|
+
repository clean. Every command prints an on-screen invocation summary (command name, passed arguments, and active
|
|
76
|
+
configuration); the full rendered prompt content is delivered only to the LLM agent and is never displayed on screen.
|
|
77
|
+
`/req-references` and `/req-reset` are non-agentic: they execute directly without starting an LLM session or
|
|
76
78
|
creating a worktree.
|
|
77
79
|
|
|
78
80
|
> **Clean context between commands** — every `/req-*` orchestration keeps the session context content in place when it
|
|
@@ -320,19 +322,19 @@ The extension renders a status field in the pi status line showing: extension id
|
|
|
320
322
|
- Config-gated slash commands that run the project tools and write the output into the editor: `debug-compress`, `debug-references`, `debug-static-check`, `debug-summarize`, `debug-tokens`.
|
|
321
323
|
- Standalone debug harness: `scripts/pi-usereq-debug.sh` (bash wrapper) and `scripts/debug-extension.ts` with subcommands `inspect`, `session-start`, `command`, `tool`, and `sdk-smoke`.
|
|
322
324
|
- Debug logging writes to the configured `DEBUG_LOG_FILE`, filtered by prompt/tool name and workflow status.
|
|
323
|
-
- **Prompt content logging** — when both `Debug` and `Enable debug prompts` are enabled (the `Debug > Enable debug prompts` menu entry), the exact rendered prompt delivered to the LLM agent through `sendMessage`/`sendUserMessage` is saved under `Log path for prompts` (`DEBUG_PROMPTS_LOG_PATH`, default `/tmp/PI-useReq`). Each run writes
|
|
325
|
+
- **Prompt content logging** — when both `Debug` and `Enable debug prompts` are enabled (the `Debug > Enable debug prompts` menu entry), the exact rendered prompt delivered to the LLM agent through `sendMessage`/`sendUserMessage` is saved under `Log path for prompts` (`DEBUG_PROMPTS_LOG_PATH`, default `/tmp/PI-useReq`). Each run writes two files named `<timestamp>-<command>-request.md` and `<timestamp>-<command>-prompt.md` (a `YYYYMMDDHHMMSSmmm` write-time timestamp plus the `/req-*` command used, e.g. `20261009072235123-req-implement-request.md` and `20261009072235123-req-implement-prompt.md`). The `-prompt.md` file is byte-identical to the rendered prompt delivered to the model; the `-request.md` file contains the exact on-screen command invocation summary. Prompt logging depends only on the global `Debug` flag plus `Enable debug prompts` (it is exempt from the `Log on status` workflow filter); nothing is written while `Debug` is disabled. Relative log paths resolve against the project root, and trailing slashes are stripped from the configured path.
|
|
324
326
|
|
|
325
327
|
Because the saved file contains exactly what pi-usereq sent, you can replicate the same send from the `pi` CLI, outside pi-usereq and without the extension installed:
|
|
326
328
|
|
|
327
329
|
```bash
|
|
328
330
|
# Replay the exact saved prompt as a one-shot task argument
|
|
329
|
-
pi -p "$(cat /tmp/PI-useReq/20261009072235123-req-implement)"
|
|
331
|
+
pi -p "$(cat /tmp/PI-useReq/20261009072235123-req-implement-prompt.md)"
|
|
330
332
|
|
|
331
333
|
# Feed extra material on stdin while replaying an analysis request
|
|
332
334
|
cat errors.log | pi -p "Analyze these errors and suggest how to fix them"
|
|
333
335
|
|
|
334
336
|
# Reuse a saved prompt as coding-style guidance through an appended system prompt
|
|
335
|
-
pi -p "Rewrite this function" --append-system-prompt /tmp/PI-useReq/20261009072235123-req-implement
|
|
337
|
+
pi -p "Rewrite this function" --append-system-prompt /tmp/PI-useReq/20261009072235123-req-implement-prompt.md
|
|
336
338
|
```
|
|
337
339
|
|
|
338
340
|
- **Provider error logging** — when a dispatched `req-*` run receives a provider response with status >= 400, pi-usereq writes the exact failing request payload into `<timestamp>-<command>-error-<status>.json` (raw provider-request JSON), the provider error message text into `<timestamp>-<command>-error-<status>-response.txt`, a byte-for-byte snapshot of the retained execution session into `<timestamp>-<command>-error-<status>-session.jsonl`, and replay metadata into `<timestamp>-<command>-error-<status>-replay.json`, all beside the run's `-request.md` and `-prompt.md` files. The `-replay.json` sidecar carries the provider, base URL, model id, thinking level, context window, max output tokens, the retained execution-session file, and ready-to-use replay commands; `replayCommands.piFork` targets the log-local `-session.jsonl` snapshot, which freezes the transcript exactly at the failing provider request (before any context edit or compaction). You can re-generate the failure for immediate pi CLI debugging:
|
|
@@ -373,7 +375,7 @@ This section describes the Git behavior of the `req-*` commands. The commands ow
|
|
|
373
375
|
- On success the extension restores the original `base-path` session, applies a stash-assisted fast-forward merge of the worktree branch, and deletes the worktree and branch.
|
|
374
376
|
- On failure or interruption the worktree and branch are **kept** and the workflow is parked in the `error` state so the produced artifacts can be inspected or recovered: run `/req-reset` to restore the original base path and force-remove the generated worktrees and branches.
|
|
375
377
|
- With `Auto git commit = enable` (default), every prompt receives structured commit instructions and commits follow the message template `<TYPE>(<COMPONENT>)<BREAKING>: <DESCRIPTION> [useReq]`. With `Auto git commit = disable`, prompts receive a read-only git restriction and worktree orchestration is forced off.
|
|
376
|
-
- The extension never rewrites history and
|
|
378
|
+
- The extension never rewrites git history; destructive cleanup is limited to the generated worktrees and branches, which only `/req-reset` force-removes (see above).
|
|
377
379
|
|
|
378
380
|
- Recommended practice:
|
|
379
381
|
- Review the changes produced by each command before pushing them.
|
package/package.json
CHANGED
package/src/core/pi-notify.ts
CHANGED
|
@@ -80,10 +80,24 @@ export const DEFAULT_PI_NOTIFY_PUSHOVER_TITLE = "%%PROMT%% @ %%BASE%% [%%TIME%%]
|
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* @brief Defines the default Pushover text template.
|
|
83
|
-
* @details
|
|
84
|
-
* @satisfies REQ-185
|
|
83
|
+
* @details Delivers the final LLM agent output as the outbound Pushover message body so completed prompt runs push the last assistant message instead of the invoked command arguments; `buildPiNotifyPushoverBody` falls back to the terminal outcome token when the substituted body resolves empty. Access complexity is O(1).
|
|
84
|
+
* @satisfies REQ-185, REQ-450
|
|
85
|
+
*/
|
|
86
|
+
export const DEFAULT_PI_NOTIFY_PUSHOVER_TEXT = "%%OUTPUT%%";
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @brief Defines the Pushover Message API `message` field limit in characters.
|
|
90
|
+
* @details Caps substituted Pushover bodies per REQ-445 so over-limit payloads are head-truncated instead of rejected by the provider. Access complexity is O(1).
|
|
91
|
+
* @satisfies REQ-445
|
|
92
|
+
*/
|
|
93
|
+
export const PI_NOTIFY_PUSHOVER_MESSAGE_LIMIT = 1024;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @brief Defines the deterministic head-truncation marker for over-limit Pushover bodies.
|
|
97
|
+
* @details Appended after the retained head characters whenever the substituted Pushover body exceeds `PI_NOTIFY_PUSHOVER_MESSAGE_LIMIT`. Access complexity is O(1).
|
|
98
|
+
* @satisfies REQ-445
|
|
85
99
|
*/
|
|
86
|
-
|
|
100
|
+
const PI_NOTIFY_PUSHOVER_TRUNCATION_MARKER = "...[truncated]";
|
|
87
101
|
|
|
88
102
|
/**
|
|
89
103
|
* @brief Enumerates supported Pushover priorities.
|
|
@@ -99,13 +113,15 @@ export type PiNotifyPushoverPriority = (typeof PI_NOTIFY_PUSHOVER_PRIORITIES)[nu
|
|
|
99
113
|
|
|
100
114
|
/**
|
|
101
115
|
* @brief Describes one prompt-end request used for command-notify and Pushover substitution.
|
|
102
|
-
* @details Stores the prompt command name, raw prompt arguments, runtime base path,
|
|
116
|
+
* @details Stores the prompt command name, raw prompt arguments, runtime base path, final prompt duration, and optional final agent output required to resolve runtime placeholders. `agentOutput` stays optional so non-agentic command callers and offline replays omit it and `%%OUTPUT%%` degrades to the empty string per REQ-444. The interface is compile-time only and introduces no runtime cost.
|
|
103
117
|
*/
|
|
104
118
|
export interface PiNotifyEventRequest {
|
|
105
119
|
promptName: string;
|
|
106
120
|
promptArgs: string;
|
|
107
121
|
basePath: string;
|
|
108
122
|
completionTimeMs: number;
|
|
123
|
+
/** Final LLM agent output printed in the pi CLI; empty when absent per REQ-443, REQ-444. */
|
|
124
|
+
agentOutput?: string;
|
|
109
125
|
}
|
|
110
126
|
|
|
111
127
|
/**
|
|
@@ -490,10 +506,11 @@ function formatPiNotifyResult(outcome: PiNotifyOutcome): string {
|
|
|
490
506
|
|
|
491
507
|
/**
|
|
492
508
|
* @brief Builds the raw runtime placeholder map for one prompt-end request.
|
|
493
|
-
* @details Resolves every placeholder value exactly once so notify-command and Pushover template substitution reuse the same prompt name, base path, elapsed time, argument string, and terminal outcome token. Runtime is O(p) in path length. No external state is mutated.
|
|
509
|
+
* @details Resolves every placeholder value exactly once so notify-command and Pushover template substitution reuse the same prompt name, base path, elapsed time, argument string, final agent output, and terminal outcome token. Runtime is O(p) in path length. No external state is mutated.
|
|
494
510
|
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
495
511
|
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
496
|
-
* @return {{ "%%PROMT%%": string; "%%BASE%%": string; "%%TIME%%": string; "%%ARGS%%": string; "%%RESULT%%": string }} Raw placeholder-value map.
|
|
512
|
+
* @return {{ "%%PROMT%%": string; "%%BASE%%": string; "%%TIME%%": string; "%%ARGS%%": string; "%%OUTPUT%%": string; "%%RESULT%%": string }} Raw placeholder-value map.
|
|
513
|
+
* @satisfies REQ-169, REQ-186, REQ-443, REQ-444
|
|
497
514
|
*/
|
|
498
515
|
function buildPiNotifyRuntimeTemplateValues(
|
|
499
516
|
request: PiNotifyEventRequest,
|
|
@@ -504,6 +521,7 @@ function buildPiNotifyRuntimeTemplateValues(
|
|
|
504
521
|
"%%BASE%%": formatPiNotifyBasePath(request.basePath),
|
|
505
522
|
"%%TIME%%": formatPiNotifyDuration(request.completionTimeMs),
|
|
506
523
|
"%%ARGS%%": request.promptArgs,
|
|
524
|
+
"%%OUTPUT%%": request.agentOutput ?? "",
|
|
507
525
|
"%%RESULT%%": formatPiNotifyResult(outcome),
|
|
508
526
|
};
|
|
509
527
|
}
|
|
@@ -555,13 +573,13 @@ export function substitutePiNotifyInstallPath(command: string, installationPath:
|
|
|
555
573
|
|
|
556
574
|
/**
|
|
557
575
|
* @brief Substitutes runtime placeholders inside one shell-command template.
|
|
558
|
-
* @details Applies shell-quoted installation-path substitution plus shell-escaped prompt, base-path, elapsed-time, raw-argument, and outcome-result substitution expected by `PI_NOTIFY_CMD`. Runtime is O(n) in template length. No external state is mutated.
|
|
576
|
+
* @details Applies shell-quoted installation-path substitution plus shell-escaped prompt, base-path, elapsed-time, raw-argument, final-output, and outcome-result substitution expected by `PI_NOTIFY_CMD`. Runtime is O(n) in template length. No external state is mutated.
|
|
559
577
|
* @param[in] template {string} Raw shell-command template.
|
|
560
578
|
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
561
579
|
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
562
580
|
* @param[in] installationPath {string} Absolute extension installation path.
|
|
563
581
|
* @return {string} Runtime-ready shell command.
|
|
564
|
-
* @satisfies REQ-169, REQ-199
|
|
582
|
+
* @satisfies REQ-169, REQ-199, REQ-443, REQ-444
|
|
565
583
|
*/
|
|
566
584
|
function substitutePiNotifyShellTemplate(
|
|
567
585
|
template: string,
|
|
@@ -579,12 +597,12 @@ function substitutePiNotifyShellTemplate(
|
|
|
579
597
|
|
|
580
598
|
/**
|
|
581
599
|
* @brief Substitutes runtime placeholders inside one text template.
|
|
582
|
-
* @details Applies raw prompt name, home-relative base path, elapsed time, raw prompt arguments, and terminal outcome text without shell escaping so Pushover payloads preserve literal text. Runtime is O(n) in template length. No external state is mutated.
|
|
600
|
+
* @details Applies raw prompt name, home-relative base path, elapsed time, raw prompt arguments, final agent output, and terminal outcome text without shell escaping so Pushover payloads preserve literal text. Runtime is O(n) in template length. No external state is mutated.
|
|
583
601
|
* @param[in] template {string} Raw text template.
|
|
584
602
|
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
585
603
|
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
586
604
|
* @return {string} Placeholder-resolved text string.
|
|
587
|
-
* @satisfies REQ-186, REQ-187, REQ-199
|
|
605
|
+
* @satisfies REQ-186, REQ-187, REQ-199, REQ-443, REQ-444
|
|
588
606
|
*/
|
|
589
607
|
function substitutePiNotifyTextTemplate(
|
|
590
608
|
template: string,
|
|
@@ -766,21 +784,40 @@ function buildPiNotifyPushoverTitle(
|
|
|
766
784
|
return substitutePiNotifyTextTemplate(config["notify-pushover-title"], request, outcome);
|
|
767
785
|
}
|
|
768
786
|
|
|
787
|
+
/**
|
|
788
|
+
* @brief Head-truncates one substituted Pushover body to the Pushover Message API limit.
|
|
789
|
+
* @details Returns the body unchanged when it fits `PI_NOTIFY_PUSHOVER_MESSAGE_LIMIT` and otherwise keeps the head characters that leave room for `PI_NOTIFY_PUSHOVER_TRUNCATION_MARKER` so over-limit bodies stay deterministic and provider-acceptable. Runtime is O(1). No external state is mutated.
|
|
790
|
+
* @param[in] body {string} Fully substituted Pushover body text.
|
|
791
|
+
* @return {string} Body within the Pushover `message` character limit.
|
|
792
|
+
* @satisfies REQ-445
|
|
793
|
+
*/
|
|
794
|
+
function truncatePiNotifyPushoverBody(body: string): string {
|
|
795
|
+
if (body.length <= PI_NOTIFY_PUSHOVER_MESSAGE_LIMIT) {
|
|
796
|
+
return body;
|
|
797
|
+
}
|
|
798
|
+
return body.slice(0, PI_NOTIFY_PUSHOVER_MESSAGE_LIMIT - PI_NOTIFY_PUSHOVER_TRUNCATION_MARKER.length)
|
|
799
|
+
+ PI_NOTIFY_PUSHOVER_TRUNCATION_MARKER;
|
|
800
|
+
}
|
|
801
|
+
|
|
769
802
|
/**
|
|
770
803
|
* @brief Builds the Pushover message body for one prompt-end request.
|
|
771
|
-
* @details Resolves the configured `notify-pushover-text` template with raw runtime placeholder substitution so the
|
|
804
|
+
* @details Resolves the configured `notify-pushover-text` template with raw runtime placeholder substitution, falls back to the terminal outcome token when the fully substituted body resolves empty so Pushover delivery never targets an empty `message` field, then head-truncates over-limit bodies to the Pushover Message API `message` limit. Runtime is O(n) in template length. No external state is mutated.
|
|
772
805
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
773
806
|
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
774
807
|
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
775
|
-
* @return {string} Pushover message body.
|
|
776
|
-
* @satisfies REQ-185, REQ-186, REQ-187, REQ-199
|
|
808
|
+
* @return {string} Pushover message body within the 1024-character API limit.
|
|
809
|
+
* @satisfies REQ-185, REQ-186, REQ-187, REQ-199, REQ-443, REQ-444, REQ-445, REQ-450
|
|
777
810
|
*/
|
|
778
811
|
function buildPiNotifyPushoverBody(
|
|
779
812
|
config: PiNotifyConfigFields,
|
|
780
813
|
outcome: PiNotifyOutcome,
|
|
781
814
|
request: PiNotifyEventRequest,
|
|
782
815
|
): string {
|
|
783
|
-
|
|
816
|
+
const substitutedBody = substitutePiNotifyTextTemplate(config["notify-pushover-text"], request, outcome);
|
|
817
|
+
const resolvedBody = substitutedBody.trim().length > 0
|
|
818
|
+
? substitutedBody
|
|
819
|
+
: formatPiNotifyResult(outcome);
|
|
820
|
+
return truncatePiNotifyPushoverBody(resolvedBody);
|
|
784
821
|
}
|
|
785
822
|
|
|
786
823
|
/**
|
|
@@ -790,7 +827,7 @@ function buildPiNotifyPushoverBody(
|
|
|
790
827
|
* @param[in] outcome {PiNotifyOutcome} Classified prompt-end outcome.
|
|
791
828
|
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata.
|
|
792
829
|
* @return {URLSearchParams} Encoded Pushover request payload.
|
|
793
|
-
* @satisfies REQ-167, REQ-172, REQ-185, REQ-186, REQ-199
|
|
830
|
+
* @satisfies REQ-167, REQ-172, REQ-185, REQ-186, REQ-199, REQ-443, REQ-444, REQ-445
|
|
794
831
|
*/
|
|
795
832
|
function buildPiNotifyPushoverPayload(
|
|
796
833
|
config: PiNotifyConfigFields,
|
|
@@ -858,19 +895,35 @@ export function setPiNotifySpawnForTests(spawnImpl: PiNotifySpawn | undefined):
|
|
|
858
895
|
|
|
859
896
|
/**
|
|
860
897
|
* @brief Dispatches prompt-end notify, sound, and Pushover effects for one agent-end payload.
|
|
861
|
-
* @details Classifies the terminal outcome
|
|
898
|
+
* @details Classifies the terminal outcome from the `agent_end` payload and delegates to `runPiNotifyEffectsForOutcome(...)`; `%%OUTPUT%%` resolves from the caller-supplied final agent output and Pushover bodies are head-truncated to the provider message limit. Runtime is O(m + c + b) in message count, command length, and Pushover payload size. Side effects include child-process spawning and outbound HTTPS requests.
|
|
862
899
|
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
863
900
|
* @param[in] event {Pick<AgentEndEvent, "messages">} Agent-end payload subset.
|
|
864
901
|
* @param[in] request {PiNotifyEventRequest | undefined} Optional prompt-end request metadata used for command-notify and Pushover substitution.
|
|
865
902
|
* @return {void} No return value.
|
|
866
|
-
* @satisfies REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-199
|
|
903
|
+
* @satisfies REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-199, REQ-443, REQ-444, REQ-445
|
|
867
904
|
*/
|
|
868
905
|
export function runPiNotifyEffects(
|
|
869
906
|
config: PiNotifyConfigFields,
|
|
870
907
|
event: Pick<AgentEndEvent, "messages">,
|
|
871
908
|
request?: PiNotifyEventRequest,
|
|
872
909
|
): void {
|
|
873
|
-
|
|
910
|
+
runPiNotifyEffectsForOutcome(config, classifyPiNotifyOutcome(event), request);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* @brief Dispatches prompt-end notify, sound, and Pushover effects for one explicit prompt-end outcome.
|
|
915
|
+
* @details Executes `PI_NOTIFY_CMD` when command-notify prerequisites are satisfied, executes the configured sound command when sound prerequisites are satisfied, and dispatches the native Pushover request when Pushover prerequisites are satisfied; `%%OUTPUT%%` resolves from the caller-supplied final agent output or command process output, and Pushover bodies head-truncate to the provider message limit with an outcome-token fallback for empty bodies. Agentic callers classify the outcome from the `agent_end` payload through `runPiNotifyEffects(...)`; non-agentic `req-references` and `req-reset` command callers pass the explicit completed or failed outcome per REQ-447. Runtime is O(c + b) in command length and Pushover payload size. Side effects include child-process spawning and outbound HTTPS requests.
|
|
916
|
+
* @param[in] config {PiNotifyConfigFields} Effective notification configuration.
|
|
917
|
+
* @param[in] outcome {PiNotifyOutcome} Explicit prompt-end outcome.
|
|
918
|
+
* @param[in] request {PiNotifyEventRequest | undefined} Optional prompt-end request metadata used for command-notify and Pushover substitution.
|
|
919
|
+
* @return {void} No return value.
|
|
920
|
+
* @satisfies REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-199, REQ-443, REQ-444, REQ-445, REQ-447, REQ-450
|
|
921
|
+
*/
|
|
922
|
+
export function runPiNotifyEffectsForOutcome(
|
|
923
|
+
config: PiNotifyConfigFields,
|
|
924
|
+
outcome: PiNotifyOutcome,
|
|
925
|
+
request?: PiNotifyEventRequest,
|
|
926
|
+
): void {
|
|
874
927
|
if (shouldRunPiNotifyCommand(config, outcome, request)) {
|
|
875
928
|
runPiNotifyCommand(config, outcome, request as PiNotifyEventRequest);
|
|
876
929
|
}
|
|
@@ -59,6 +59,29 @@ export interface ReqResetCommandExecutionResult {
|
|
|
59
59
|
errorMessage?: string;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @brief Builds the per-operation outcome lines of one `req-reset` run for `%%OUTPUT%%` notification substitution.
|
|
64
|
+
* @details Emits one machine-readable line per recovery or cleanup fact — terminal outcome, execution-transcript preservation, `base-path` restoration, removed generated worktree count, removed generated branch count — and appends the surfaced error diagnostic for failed runs so prompt-end notification effects carry exactly the output produced during the process. Runtime is O(1). No external state is mutated.
|
|
65
|
+
* @param[in] executionResult {ReqResetCommandExecutionResult} Recovery and cleanup outcome facts of the attempted run.
|
|
66
|
+
* @return {string[]} Ordered outcome lines starting with the terminal outcome.
|
|
67
|
+
* @satisfies REQ-449
|
|
68
|
+
*/
|
|
69
|
+
export function buildReqResetCommandOutcomeLines(
|
|
70
|
+
executionResult: ReqResetCommandExecutionResult,
|
|
71
|
+
): string[] {
|
|
72
|
+
const lines = [
|
|
73
|
+
`outcome: ${executionResult.errorMessage ? "error" : "success"}`,
|
|
74
|
+
`transcript preserved: ${executionResult.transcriptPreserved ? "yes" : "no"}`,
|
|
75
|
+
`base-path restored: ${executionResult.restoredBasePath ? "yes" : "no"}`,
|
|
76
|
+
`worktrees removed: ${executionResult.removedWorktreeDirs.length}`,
|
|
77
|
+
`branches removed: ${executionResult.removedBranchNames.length}`,
|
|
78
|
+
];
|
|
79
|
+
if (executionResult.errorMessage) {
|
|
80
|
+
lines.push(`error: ${executionResult.errorMessage}`);
|
|
81
|
+
}
|
|
82
|
+
return lines;
|
|
83
|
+
}
|
|
84
|
+
|
|
62
85
|
/**
|
|
63
86
|
* @brief Describes the session-bound context surface reused during `req-reset` recovery.
|
|
64
87
|
* @details Reuses the session-switching contract already accepted by `restorePromptCommandExecution(...)` so the dedicated reset command can restore the original session without depending on concrete pi runtime classes. The alias is compile-time only and introduces no runtime cost.
|
package/src/index.ts
CHANGED
|
@@ -61,7 +61,9 @@ import {
|
|
|
61
61
|
normalizePiNotifyTemplateValue,
|
|
62
62
|
parsePiNotifyControlSequenceText,
|
|
63
63
|
runPiNotifyEffects,
|
|
64
|
+
runPiNotifyEffectsForOutcome,
|
|
64
65
|
type PiNotifyEventRequest,
|
|
66
|
+
type PiNotifyOutcome,
|
|
65
67
|
type PiNotifyPushoverPriority,
|
|
66
68
|
type PiNotifySoundLevel,
|
|
67
69
|
} from "./core/pi-notify.js";
|
|
@@ -118,6 +120,7 @@ import {
|
|
|
118
120
|
} from "./core/req-references-command.js";
|
|
119
121
|
import {
|
|
120
122
|
REQ_RESET_COMMAND_DESCRIPTION,
|
|
123
|
+
buildReqResetCommandOutcomeLines,
|
|
121
124
|
executeReqResetCommandExecution,
|
|
122
125
|
prepareReqResetCommandExecution,
|
|
123
126
|
type ReqResetCommandExecutionResult,
|
|
@@ -178,6 +181,7 @@ import {
|
|
|
178
181
|
appendCommandReportEntry,
|
|
179
182
|
buildCommandReportErrorEntryData,
|
|
180
183
|
buildReqReferencesCommandReportEntryData,
|
|
184
|
+
buildReqReferencesCommandReportLines,
|
|
181
185
|
registerCommandReportEntryRenderer,
|
|
182
186
|
} from "./core/command-report-entry.js";
|
|
183
187
|
import { ReqError } from "./core/errors.js";
|
|
@@ -1239,6 +1243,32 @@ function notifyContextSafely(
|
|
|
1239
1243
|
}
|
|
1240
1244
|
}
|
|
1241
1245
|
|
|
1246
|
+
/**
|
|
1247
|
+
* @brief Dispatches prompt-end notification effects for one non-agentic command outcome.
|
|
1248
|
+
* @details Builds the effective notification configuration subset with the active runtime sound level and forwards the explicit completed or failed outcome plus the command-produced process output into `runPiNotifyEffectsForOutcome(...)`, so `req-references` and `req-reset` completions feed the same command-notify, sound, and Pushover gates as `agent_end` runs. Runtime is O(1) plus delegated effect cost. Side effects include optional child-process spawning and outbound HTTPS requests.
|
|
1249
|
+
* @param[in] statusController {PiUsereqStatusController} Mutable status controller supplying the active runtime sound level.
|
|
1250
|
+
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
1251
|
+
* @param[in] outcome {PiNotifyOutcome} Explicit terminal command outcome.
|
|
1252
|
+
* @param[in] request {PiNotifyEventRequest} Prompt-end request metadata carrying the command process output.
|
|
1253
|
+
* @return {void} No return value.
|
|
1254
|
+
* @satisfies REQ-447, REQ-448, REQ-449
|
|
1255
|
+
*/
|
|
1256
|
+
function dispatchNonAgenticCommandNotifyEffects(
|
|
1257
|
+
statusController: PiUsereqStatusController,
|
|
1258
|
+
config: UseReqConfig,
|
|
1259
|
+
outcome: PiNotifyOutcome,
|
|
1260
|
+
request: PiNotifyEventRequest,
|
|
1261
|
+
): void {
|
|
1262
|
+
runPiNotifyEffectsForOutcome(
|
|
1263
|
+
{
|
|
1264
|
+
...config,
|
|
1265
|
+
"notify-sound": getPiUsereqRuntimeSoundLevel(statusController),
|
|
1266
|
+
},
|
|
1267
|
+
outcome,
|
|
1268
|
+
request,
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1242
1272
|
/**
|
|
1243
1273
|
* @brief Emits the final context-retention reminder info notification for a successfully completed `/req-*` orchestration.
|
|
1244
1274
|
* @details Builds one message stating that the session context content was retained, recommending a clean-context session start before the next `/req-*` command, and appending the current context-usage percentage when the controller holds a normalized snapshot. Delivers exclusively through `notifyContextSafely(...)`, so stale replacement-session contexts are suppressed, and performs no session message send and no session switch. Runtime is O(1). Side effect is user notification delivery only when the supplied context is still active.
|
|
@@ -1498,16 +1528,50 @@ async function finalizeMatchedPromptSuccess(
|
|
|
1498
1528
|
}
|
|
1499
1529
|
}
|
|
1500
1530
|
|
|
1531
|
+
/**
|
|
1532
|
+
* @brief Extracts the final agent output text for prompt-end `%%OUTPUT%%` substitution.
|
|
1533
|
+
* @details Scans the `agent_end` payload messages backwards for the last assistant message and concatenates its `type === "text"` content blocks while skipping `thinking` and tool-call blocks, returning the empty string for non-agent payloads and for last assistant messages without text blocks so non-agentic command notifications never substitute stale output. Runtime is O(m + n) in message and text-block count. No external state is mutated.
|
|
1534
|
+
* @param[in] event {unknown} Raw `agent_end` lifecycle event payload.
|
|
1535
|
+
* @return {string} Concatenated final assistant text blocks, or the empty string when unavailable.
|
|
1536
|
+
* @satisfies REQ-443, REQ-444
|
|
1537
|
+
*/
|
|
1538
|
+
function buildAgentEndOutputText(event: unknown): string {
|
|
1539
|
+
const messages = (event as { messages?: unknown } | undefined)?.messages;
|
|
1540
|
+
if (!Array.isArray(messages)) {
|
|
1541
|
+
return "";
|
|
1542
|
+
}
|
|
1543
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
1544
|
+
const message = messages[index] as { role?: unknown; content?: unknown } | undefined;
|
|
1545
|
+
if (typeof message !== "object" || message === null || message.role !== "assistant") {
|
|
1546
|
+
continue;
|
|
1547
|
+
}
|
|
1548
|
+
const content = Array.isArray(message.content) ? message.content : [];
|
|
1549
|
+
let output = "";
|
|
1550
|
+
for (const block of content) {
|
|
1551
|
+
if (
|
|
1552
|
+
typeof block === "object"
|
|
1553
|
+
&& block !== null
|
|
1554
|
+
&& (block as { type?: unknown }).type === "text"
|
|
1555
|
+
&& typeof (block as { text?: unknown }).text === "string"
|
|
1556
|
+
) {
|
|
1557
|
+
output += (block as { text: string }).text;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
return output;
|
|
1561
|
+
}
|
|
1562
|
+
return "";
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1501
1565
|
/**
|
|
1502
1566
|
* @brief Handles one intercepted pi lifecycle hook for pi-usereq status updates.
|
|
1503
|
-
* @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. After the status update, captures the exact `before_provider_request` provider payload for the live active or pending prompt run by reloading the prompt debug gating configuration from the prompt run's original `base-path` (worktree-backed checkouts do not contain the untracked `.pi-usereq.json`, so the cwd-derived cached config would silently disable capture), flushes the process-scoped captured payload as one `<timestamp>-<req-command>-error-<status>` file whenever `after_provider_response` reports a status >= 400 or whenever one finalized `message_end` assistant error message carries a leading HTTP status >= 400 (the provider-independent fallback for provider APIs whose SDK clients throw before emitting `after_provider_response` for non-2xx statuses) without requiring live workflow state, and discards the capture at prompt-run end so stale payloads never reach later runs. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
|
|
1567
|
+
* @details Applies session-start-specific resource validation, project-config refresh, idle-time shared-tokenizer and context-file measurement pre-warm, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. After the status update, captures the exact `before_provider_request` provider payload for the live active or pending prompt run by reloading the prompt debug gating configuration from the prompt run's original `base-path` (worktree-backed checkouts do not contain the untracked `.pi-usereq.json`, so the cwd-derived cached config would silently disable capture), flushes the process-scoped captured payload as one `<timestamp>-<req-command>-error-<status>` file whenever `after_provider_response` reports a status >= 400 or whenever one finalized `message_end` assistant error message carries a leading HTTP status >= 400 (the provider-independent fallback for provider APIs whose SDK clients throw before emitting `after_provider_response` for non-2xx statuses) without requiring live workflow state, and discards the capture at prompt-run end so stale payloads never reach later runs. Before `agent_start`, re-verifies any prepared prompt execution session switch. On `agent_end`, dispatches configured command-notify, sound, and prompt-specific Pushover effects with the final assistant output text feeding `%%OUTPUT%%` placeholder substitution, logs dedicated workflow-closure diagnostics, classifies the prompt outcome, and for every matched successful worktree-backed completion defers the restore switch, stash-assisted merge, and worktree deletion to `agent_settled` when the running pi host supports that 0.80.4+ event (because its `switchSession` awaits the active agent run to become idle and would deadlock inside `agent_end`), or executes the finalization directly at `agent_end` when the host does not emit `agent_settled`. On `agent_settled`, reuses persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the deferred stash-assisted merge-and-delete finalization path, emits a warning-only notification when restored `base-path` changes are reapplied after merge, tolerates stale replacement-session notification contexts after session replacement, retains the worktree plus notifies closure failure for interrupted or failed outcomes, logs selected prompt workflow transitions, and transitions workflow state through `merging`, `error`, and `idle` as required. On `session_shutdown`, captures pre-update prompt snapshots so workflow-shutdown diagnostics and same-runtime command continuation preserve the active prompt workflow state across switch-triggered rebinding, then disposes the shared controller. Runtime is dominated by configuration loading during `session_start` and git finalization during matched successful closure handling; all other hooks are O(1). Side effects include resource checks, active-tool mutation, active-session replacement, status updates, live-ticker disposal on shutdown, optional child-process spawning, outbound HTTPS requests, branch merges, worktree deletion, and optional debug-log writes.
|
|
1504
1568
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
1505
1569
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
1506
1570
|
* @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
|
|
1507
1571
|
* @param[in] event {unknown} Hook payload forwarded by pi.
|
|
1508
1572
|
* @param[in] ctx {ExtensionContext} Active extension context.
|
|
1509
1573
|
* @return {Promise<void>} Promise resolved when hook processing completes.
|
|
1510
|
-
* @satisfies REQ-117, REQ-118, REQ-119, REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-208, REQ-209, REQ-221, REQ-228, REQ-229, REQ-230, REQ-244, REQ-245, REQ-246, REQ-247, REQ-276, REQ-277, REQ-278, REQ-279, REQ-280, REQ-291, REQ-292, REQ-421, REQ-422, REQ-425, REQ-440
|
|
1574
|
+
* @satisfies REQ-117, REQ-118, REQ-119, REQ-131, REQ-132, REQ-133, REQ-166, REQ-167, REQ-168, REQ-169, REQ-172, REQ-176, REQ-178, REQ-184, REQ-185, REQ-186, REQ-187, REQ-208, REQ-209, REQ-221, REQ-228, REQ-229, REQ-230, REQ-244, REQ-245, REQ-246, REQ-247, REQ-276, REQ-277, REQ-278, REQ-279, REQ-280, REQ-291, REQ-292, REQ-421, REQ-422, REQ-425, REQ-440, REQ-443, REQ-444
|
|
1511
1575
|
*/
|
|
1512
1576
|
async function handleExtensionStatusEvent(
|
|
1513
1577
|
pi: ExtensionAPI,
|
|
@@ -1569,6 +1633,7 @@ async function handleExtensionStatusEvent(
|
|
|
1569
1633
|
promptArgs: activePromptRequest.promptArgs,
|
|
1570
1634
|
basePath: activePromptRequest.basePath,
|
|
1571
1635
|
completionTimeMs: Math.max(0, Date.now() - statusController.state.runStartTimeMs),
|
|
1636
|
+
agentOutput: buildAgentEndOutputText(event),
|
|
1572
1637
|
}
|
|
1573
1638
|
: undefined;
|
|
1574
1639
|
updateExtensionStatus(statusController, hookName, event, ctx);
|
|
@@ -2710,7 +2775,7 @@ async function configurePiNotifyEventMenu(
|
|
|
2710
2775
|
* @details Serializes the global enable flag, shared-event submenu launcher, priority, title, text, and credential rows into right-valued menu items appended after the sound-command rows, dims and disables the enable row until both credentials are populated, renders the locked value as `configure user/token keys first`, and escapes control characters for the single-line `Pushover text` value. Runtime is O(n) in the rendered text-template length. No external state is mutated.
|
|
2711
2776
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
2712
2777
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered direct Pushover rows.
|
|
2713
|
-
* @satisfies REQ-163, REQ-165, REQ-172, REQ-184, REQ-185, REQ-198, REQ-234, REQ-235
|
|
2778
|
+
* @satisfies REQ-163, REQ-165, REQ-172, REQ-184, REQ-185, REQ-198, REQ-234, REQ-235, REQ-443, REQ-444, REQ-446
|
|
2714
2779
|
*/
|
|
2715
2780
|
function buildPiNotifyPushoverRows(config: UseReqConfig): PiUsereqSettingsMenuChoice[] {
|
|
2716
2781
|
const pushoverCredentialsReady = hasPiNotifyPushoverCredentials(config);
|
|
@@ -2747,7 +2812,7 @@ function buildPiNotifyPushoverRows(config: UseReqConfig): PiUsereqSettingsMenuCh
|
|
|
2747
2812
|
id: "notify-pushover-text",
|
|
2748
2813
|
label: "Pushover text",
|
|
2749
2814
|
value: formatPiNotifyControlSequenceText(config["notify-pushover-text"]),
|
|
2750
|
-
description: "Edit the text template used for outbound Pushover messages.",
|
|
2815
|
+
description: "Edit the text template used for outbound Pushover messages. Tokens: %%PROMT%% %%BASE%% %%TIME%% %%ARGS%% %%OUTPUT%% %%RESULT%%.",
|
|
2751
2816
|
},
|
|
2752
2817
|
{
|
|
2753
2818
|
id: "notify-pushover-user-key",
|
|
@@ -3424,11 +3489,11 @@ function resolveReqResetPromptRequest(
|
|
|
3424
3489
|
|
|
3425
3490
|
/**
|
|
3426
3491
|
* @brief Registers the specialized `req-reset` slash command.
|
|
3427
|
-
* @details Registers the non-agentic prompt-recovery command that accepts any current workflow state, reuses persisted prompt runtime state when available, restores the original session-backed `base-path`, force-removes matching generated worktrees plus branches, clears recoverable prompt state when restoration succeeds,
|
|
3492
|
+
* @details Registers the non-agentic prompt-recovery command that accepts any current workflow state, reuses persisted prompt runtime state when available, restores the original session-backed `base-path`, force-removes matching generated worktrees plus branches, clears recoverable prompt state when restoration succeeds, notifies pi without starting an LLM session or creating a worktree, and dispatches prompt-end notification effects carrying the command process output as `%%OUTPUT%%`. Runtime is dominated by session restoration plus git cleanup. Side effects include command registration, status-controller mutation, active-session replacement, worktree deletion, branch deletion, user notifications, and optional prompt-end notify, sound, and Pushover dispatch.
|
|
3428
3493
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
3429
3494
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
3430
3495
|
* @return {void} No return value.
|
|
3431
|
-
* @satisfies REQ-304, REQ-305, REQ-306, REQ-307, REQ-308, REQ-309, REQ-310, REQ-311, REQ-312, REQ-313, REQ-441
|
|
3496
|
+
* @satisfies REQ-304, REQ-305, REQ-306, REQ-307, REQ-308, REQ-309, REQ-310, REQ-311, REQ-312, REQ-313, REQ-441, REQ-447, REQ-449
|
|
3432
3497
|
*/
|
|
3433
3498
|
function registerReqResetCommand(
|
|
3434
3499
|
pi: ExtensionAPI,
|
|
@@ -3436,7 +3501,8 @@ function registerReqResetCommand(
|
|
|
3436
3501
|
): void {
|
|
3437
3502
|
pi.registerCommand("req-reset", {
|
|
3438
3503
|
description: REQ_RESET_COMMAND_DESCRIPTION,
|
|
3439
|
-
handler: async (
|
|
3504
|
+
handler: async (args, ctx) => {
|
|
3505
|
+
const commandStartMs = Date.now();
|
|
3440
3506
|
const promptRequest = resolveReqResetPromptRequest(statusController);
|
|
3441
3507
|
const resetModelSelection = promptRequest?.originalModel
|
|
3442
3508
|
?? resolveCurrentModelSelection((ctx as unknown as PromptModelSelectionContextSurface).model);
|
|
@@ -3470,6 +3536,13 @@ function registerReqResetCommand(
|
|
|
3470
3536
|
const message = error instanceof Error ? error.message : String(error);
|
|
3471
3537
|
setPiUsereqWorkflowState(statusController, "error", resetContext);
|
|
3472
3538
|
notifyContextSafely(resetContext, message, "error");
|
|
3539
|
+
dispatchNonAgenticCommandNotifyEffects(statusController, config, "failed", {
|
|
3540
|
+
promptName: "req-reset",
|
|
3541
|
+
promptArgs: args,
|
|
3542
|
+
basePath: projectBase,
|
|
3543
|
+
completionTimeMs: Math.max(0, Date.now() - commandStartMs),
|
|
3544
|
+
agentOutput: message,
|
|
3545
|
+
});
|
|
3473
3546
|
throw error;
|
|
3474
3547
|
}
|
|
3475
3548
|
|
|
@@ -3484,6 +3557,13 @@ function registerReqResetCommand(
|
|
|
3484
3557
|
if (executionResult.errorMessage) {
|
|
3485
3558
|
setPiUsereqWorkflowState(statusController, "error", resetContext);
|
|
3486
3559
|
notifyContextSafely(resetContext, executionResult.errorMessage, "error");
|
|
3560
|
+
dispatchNonAgenticCommandNotifyEffects(statusController, config, "failed", {
|
|
3561
|
+
promptName: "req-reset",
|
|
3562
|
+
promptArgs: args,
|
|
3563
|
+
basePath: projectBase,
|
|
3564
|
+
completionTimeMs: Math.max(0, Date.now() - commandStartMs),
|
|
3565
|
+
agentOutput: buildReqResetCommandOutcomeLines(executionResult).join("\n"),
|
|
3566
|
+
});
|
|
3487
3567
|
throw new ReqError(executionResult.errorMessage, 1);
|
|
3488
3568
|
}
|
|
3489
3569
|
|
|
@@ -3492,6 +3572,13 @@ function registerReqResetCommand(
|
|
|
3492
3572
|
? `SUCCESS: req-reset restored base-path and removed ${executionResult.removedWorktreeDirs.length} worktree(s) plus ${executionResult.removedBranchNames.length} branch(es).`
|
|
3493
3573
|
: `SUCCESS: req-reset removed ${executionResult.removedWorktreeDirs.length} worktree(s) plus ${executionResult.removedBranchNames.length} branch(es) and restored idle state.`;
|
|
3494
3574
|
notifyContextSafely(resetContext, successMessage, "info");
|
|
3575
|
+
dispatchNonAgenticCommandNotifyEffects(statusController, config, "completed", {
|
|
3576
|
+
promptName: "req-reset",
|
|
3577
|
+
promptArgs: args,
|
|
3578
|
+
basePath: projectBase,
|
|
3579
|
+
completionTimeMs: Math.max(0, Date.now() - commandStartMs),
|
|
3580
|
+
agentOutput: buildReqResetCommandOutcomeLines(executionResult).join("\n"),
|
|
3581
|
+
});
|
|
3495
3582
|
notifyContextRetentionReminder(statusController, resetContext);
|
|
3496
3583
|
},
|
|
3497
3584
|
});
|
|
@@ -3499,11 +3586,11 @@ function registerReqResetCommand(
|
|
|
3499
3586
|
|
|
3500
3587
|
/**
|
|
3501
3588
|
* @brief Registers the specialized `req-references` slash command.
|
|
3502
|
-
* @details Registers the non-agentic references-maintenance command that rejects non-`idle` invocations by transitioning workflow state to `error` before direct execution, otherwise reuses slash-command-owned git validation, transitions workflow state through `checking|running|idle`, regenerates `REFERENCES.md` directly from configured source directories, stages only the generated file, creates the fixed-message git commit, verifies repository cleanliness, appends one durable `pi-usereq.command-report` session entry recording the executed operations with their outcomes so the report renders in the transcript and survives session restore,
|
|
3589
|
+
* @details Registers the non-agentic references-maintenance command that rejects non-`idle` invocations by transitioning workflow state to `error` before direct execution, otherwise reuses slash-command-owned git validation, transitions workflow state through `checking|running|idle`, regenerates `REFERENCES.md` directly from configured source directories, stages only the generated file, creates the fixed-message git commit, verifies repository cleanliness, appends one durable `pi-usereq.command-report` session entry recording the executed operations with their outcomes so the report renders in the transcript and survives session restore, emits execution notifications that conform to the operations actually performed — one stating whether the references file was updated or already matched the generated content and one stating whether the fixed-message commit was created or skipped — regardless of the update and commit outcomes, dispatches prompt-end notification effects carrying the per-operation process output as `%%OUTPUT%%`, all without starting an LLM session or creating a worktree. Runtime is dominated by git subprocess execution plus source-summary generation. Side effects include command registration, status-controller mutation, filesystem writes, git index/history mutation, session-entry persistence, user notifications, and optional prompt-end notify, sound, and Pushover dispatch.
|
|
3503
3590
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
3504
3591
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
3505
3592
|
* @return {void} No return value.
|
|
3506
|
-
* @satisfies REQ-200, REQ-221, REQ-224, REQ-298, REQ-299, REQ-300, REQ-301, REQ-302, REQ-303, REQ-436, REQ-437, REQ-438, REQ-441
|
|
3593
|
+
* @satisfies REQ-200, REQ-221, REQ-224, REQ-298, REQ-299, REQ-300, REQ-301, REQ-302, REQ-303, REQ-436, REQ-437, REQ-438, REQ-441, REQ-447, REQ-448
|
|
3507
3594
|
*/
|
|
3508
3595
|
function registerReqReferencesCommand(
|
|
3509
3596
|
pi: ExtensionAPI,
|
|
@@ -3511,7 +3598,8 @@ function registerReqReferencesCommand(
|
|
|
3511
3598
|
): void {
|
|
3512
3599
|
pi.registerCommand("req-references", {
|
|
3513
3600
|
description: REQ_REFERENCES_COMMAND_DESCRIPTION,
|
|
3514
|
-
handler: async (
|
|
3601
|
+
handler: async (args, ctx) => {
|
|
3602
|
+
const commandStartMs = Date.now();
|
|
3515
3603
|
if (statusController.state.workflowState !== "idle") {
|
|
3516
3604
|
rejectNonIdleReqCommand(statusController, ctx);
|
|
3517
3605
|
}
|
|
@@ -3554,6 +3642,13 @@ function registerReqReferencesCommand(
|
|
|
3554
3642
|
: `SUCCESS: req-references completed with a clean repository (${executionResult.referencesChanged ? "references updated" : "references unchanged"}; ${executionResult.commitCreated ? "commit created" : "commit skipped"}).`,
|
|
3555
3643
|
"info",
|
|
3556
3644
|
);
|
|
3645
|
+
dispatchNonAgenticCommandNotifyEffects(statusController, config, "completed", {
|
|
3646
|
+
promptName: "req-references",
|
|
3647
|
+
promptArgs: args,
|
|
3648
|
+
basePath: projectBase,
|
|
3649
|
+
completionTimeMs: Math.max(0, Date.now() - commandStartMs),
|
|
3650
|
+
agentOutput: buildReqReferencesCommandReportLines(executionResult).join("\n"),
|
|
3651
|
+
});
|
|
3557
3652
|
notifyContextRetentionReminder(statusController, ctx);
|
|
3558
3653
|
} catch (error) {
|
|
3559
3654
|
statusController.state.pendingPromptRequest = undefined;
|
|
@@ -3562,6 +3657,13 @@ function registerReqReferencesCommand(
|
|
|
3562
3657
|
const message = error instanceof Error ? error.message : String(error);
|
|
3563
3658
|
appendCommandReportEntry(pi, buildCommandReportErrorEntryData("req-references", message));
|
|
3564
3659
|
notifyContextSafely(ctx, message, "error");
|
|
3660
|
+
dispatchNonAgenticCommandNotifyEffects(statusController, config, "failed", {
|
|
3661
|
+
promptName: "req-references",
|
|
3662
|
+
promptArgs: args,
|
|
3663
|
+
basePath: projectBase,
|
|
3664
|
+
completionTimeMs: Math.max(0, Date.now() - commandStartMs),
|
|
3665
|
+
agentOutput: message,
|
|
3666
|
+
});
|
|
3565
3667
|
throw error;
|
|
3566
3668
|
}
|
|
3567
3669
|
},
|