pi-usereq 0.10.0 → 0.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.
- package/CHANGELOG.md +66 -0
- package/README.md +6 -6
- package/package.json +1 -1
- package/pi-usereq/docs/REFERENCES.md +861 -704
- package/pi-usereq/docs/REQUIREMENTS.md +152 -95
- package/pi-usereq/docs/WORKFLOW.md +228 -65
- package/scripts/lib/extension-debug-harness.ts +2 -2
- package/scripts/tool-args-to-params.ts +2 -2
- package/src/cli.ts +12 -12
- package/src/core/debug-runtime.ts +2 -2
- package/src/core/extension-status.ts +98 -36
- package/src/core/pi-notify.ts +5 -5
- package/src/core/pi-usereq-tools.ts +4 -2
- package/src/core/prompt-command-catalog.ts +4 -5
- package/src/core/prompt-command-runtime.ts +347 -42
- package/src/core/prompts.ts +0 -2
- package/src/core/req-references-command.ts +175 -0
- package/src/core/req-reset-command.ts +323 -0
- package/src/core/resources.ts +6 -23
- package/src/core/runtime-project-paths.ts +21 -1
- package/src/core/settings-menu.ts +85 -28
- package/src/core/tool-runner.ts +26 -6
- package/src/index.ts +530 -104
- package/tests/attended-results-scenarios.ts +5 -5
- package/tests/cli-command-option-parity.test.ts +25 -25
- package/tests/debug-extension-harness.test.ts +8 -2
- package/tests/extension-registration.test.ts +1109 -76
- package/tests/oracle-project.test.ts +4 -4
- package/tests/oracle-standalone.test.ts +5 -5
- package/src/core/reference-payload.ts +0 -752
- package/src/resources/prompts/references.md +0 -64
- /package/tests/fixtures_attended_results/project/{references.json → summarize.json} +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_c.c.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_cpp.cpp.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_csharp.cs.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_elixir.ex.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_go.go.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_haskell.hs.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_java.java.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_javascript.js.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_kotlin.kt.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_lua.lua.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_perl.pl.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_php.php.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_python.py.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_ruby.rb.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_rust.rs.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_scala.scala.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_shell.sh.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_swift.swift.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_typescript.ts.json +0 -0
- /package/tests/fixtures_attended_results/standalone/{files-references → files-summarize}/fixture_zig.zig.json +0 -0
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @brief Declares the extension version string.
|
|
9
9
|
* @details The value is exported for external inspection and packaging metadata alignment. Access complexity is O(1).
|
|
10
10
|
*/
|
|
11
|
-
export const VERSION = "0.
|
|
11
|
+
export const VERSION = "0.12.0";
|
|
12
12
|
|
|
13
13
|
import fs from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
@@ -91,6 +91,18 @@ import {
|
|
|
91
91
|
restorePromptCommandExecution,
|
|
92
92
|
type PromptCommandExecutionPlan,
|
|
93
93
|
} from "./core/prompt-command-runtime.js";
|
|
94
|
+
import {
|
|
95
|
+
REQ_REFERENCES_COMMAND_DESCRIPTION,
|
|
96
|
+
executeReqReferencesCommandExecution,
|
|
97
|
+
prepareReqReferencesCommandExecution,
|
|
98
|
+
} from "./core/req-references-command.js";
|
|
99
|
+
import {
|
|
100
|
+
REQ_RESET_COMMAND_DESCRIPTION,
|
|
101
|
+
executeReqResetCommandExecution,
|
|
102
|
+
prepareReqResetCommandExecution,
|
|
103
|
+
type ReqResetCommandExecutionResult,
|
|
104
|
+
type ReqResetCommandPlan,
|
|
105
|
+
} from "./core/req-reset-command.js";
|
|
94
106
|
import {
|
|
95
107
|
DEBUG_PROMPT_NAMES,
|
|
96
108
|
DEBUG_WORKFLOW_STATES,
|
|
@@ -114,6 +126,7 @@ import {
|
|
|
114
126
|
import { PROMPT_COMMAND_NAMES } from "./core/prompt-command-catalog.js";
|
|
115
127
|
import { resolveRuntimeGitPath } from "./core/runtime-project-paths.js";
|
|
116
128
|
import {
|
|
129
|
+
clearPersistedPromptCommandRuntimeState,
|
|
117
130
|
readPersistedPromptCommandRuntimeState,
|
|
118
131
|
writePersistedPromptCommandRuntimeState,
|
|
119
132
|
} from "./core/prompt-command-state.js";
|
|
@@ -123,8 +136,10 @@ import {
|
|
|
123
136
|
PI_USEREQ_STATUS_HOOK_NAMES,
|
|
124
137
|
createPiUsereqStatusController,
|
|
125
138
|
disposePiUsereqStatusController,
|
|
139
|
+
getPiUsereqRuntimeSoundLevel,
|
|
126
140
|
isStaleExtensionContextError,
|
|
127
141
|
renderPiUsereqStatus,
|
|
142
|
+
setPiUsereqRuntimeSoundLevel,
|
|
128
143
|
setPiUsereqStatusConfig,
|
|
129
144
|
setPiUsereqWorkflowState,
|
|
130
145
|
shouldPreservePromptCommandStateOnShutdown,
|
|
@@ -135,13 +150,14 @@ import {
|
|
|
135
150
|
import {
|
|
136
151
|
runCompress,
|
|
137
152
|
runFilesCompress,
|
|
138
|
-
runFilesReferences,
|
|
139
153
|
runFilesSearch,
|
|
140
154
|
runFilesStaticCheck,
|
|
155
|
+
runFilesSummarize,
|
|
141
156
|
runFilesTokens,
|
|
142
157
|
runProjectStaticCheck,
|
|
143
158
|
runReferences,
|
|
144
159
|
runSearch,
|
|
160
|
+
runSummarize,
|
|
145
161
|
runTokens,
|
|
146
162
|
type ToolResult,
|
|
147
163
|
} from "./core/tool-runner.js";
|
|
@@ -279,20 +295,19 @@ function formatProjectConfigPathForMenu(cwd: string): string {
|
|
|
279
295
|
|
|
280
296
|
/**
|
|
281
297
|
* @brief Builds the standardized terminal rows appended to every configuration menu.
|
|
282
|
-
* @details Returns the canonical `Reset defaults` row so all configuration menus and descendant selector menus share the same terminal ordering contract without rendering `Save and close`. Runtime is O(1). No external state is mutated.
|
|
283
|
-
* @param[in] options {{ resetDefaultsDescription: string
|
|
298
|
+
* @details Returns the canonical value-less `Reset defaults` row so all configuration menus and descendant selector menus share the same terminal ordering contract without rendering `Save and close`. Runtime is O(1). No external state is mutated.
|
|
299
|
+
* @param[in] options {{ resetDefaultsDescription: string }} Menu-specific terminal-row metadata.
|
|
284
300
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered terminal menu rows.
|
|
285
301
|
* @satisfies REQ-193
|
|
286
302
|
*/
|
|
287
303
|
function buildTerminalSettingsMenuChoices(options: {
|
|
288
304
|
resetDefaultsDescription: string;
|
|
289
|
-
resetDefaultsValue?: string;
|
|
290
305
|
}): PiUsereqSettingsMenuChoice[] {
|
|
291
306
|
return [
|
|
292
307
|
{
|
|
293
308
|
id: "reset-defaults",
|
|
294
309
|
label: "Reset defaults",
|
|
295
|
-
value:
|
|
310
|
+
value: "",
|
|
296
311
|
description: options.resetDefaultsDescription,
|
|
297
312
|
},
|
|
298
313
|
];
|
|
@@ -687,6 +702,44 @@ function executeMonolithicTool(operation: () => ToolResult): ReturnType<typeof b
|
|
|
687
702
|
}
|
|
688
703
|
}
|
|
689
704
|
|
|
705
|
+
/**
|
|
706
|
+
* @brief Executes one CLI-style runner for a status-only agent tool.
|
|
707
|
+
* @details Reuses the standalone tool-runner contract, preserves `content[0].text` as the status-only `success` or `error: <diagnostic>` payload, and strips success-path `stdout_lines` so `details.execution` stays limited to the numeric code plus optional residual stderr diagnostics. Runtime is dominated by the delegated runner. Side effects depend on the selected tool.
|
|
708
|
+
* @param[in] operation {() => ToolResult} Runner callback.
|
|
709
|
+
* @return {ReturnType<typeof buildMonolithicToolExecuteResult>} Status-only tool execute result.
|
|
710
|
+
* @satisfies REQ-294, REQ-295, REQ-296
|
|
711
|
+
*/
|
|
712
|
+
function executeStatusTool(operation: () => ToolResult): ReturnType<typeof buildMonolithicToolExecuteResult> {
|
|
713
|
+
const normalizeExecution = (
|
|
714
|
+
payload: ReturnType<typeof buildMonolithicToolExecuteResult>,
|
|
715
|
+
): ReturnType<typeof buildMonolithicToolExecuteResult> => {
|
|
716
|
+
const execution = payload.details.execution;
|
|
717
|
+
return {
|
|
718
|
+
content: payload.content,
|
|
719
|
+
details: {
|
|
720
|
+
execution: {
|
|
721
|
+
code: execution.code,
|
|
722
|
+
...(Array.isArray(execution.stderr_lines) && execution.stderr_lines.length > 0
|
|
723
|
+
? { stderr_lines: execution.stderr_lines }
|
|
724
|
+
: {}),
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
};
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
try {
|
|
731
|
+
return normalizeExecution(buildMonolithicToolExecuteResult(operation()));
|
|
732
|
+
} catch (error) {
|
|
733
|
+
const failure = normalizeToolFailure(error);
|
|
734
|
+
const diagnostic = failure.stderr.trim().replace(/^(Error|error):\s*/u, "") || "unknown failure";
|
|
735
|
+
return normalizeExecution(buildMonolithicToolExecuteResult({
|
|
736
|
+
stdout: "",
|
|
737
|
+
stderr: `error: ${diagnostic}`,
|
|
738
|
+
code: failure.code,
|
|
739
|
+
}));
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
690
743
|
/**
|
|
691
744
|
* @brief Starts delivery of one rendered prompt into the current active session.
|
|
692
745
|
* @details Prefers the replacement-session `sendUserMessage(...)` helper exposed by `withSession(...)` callbacks after session replacement so post-switch prompt delivery never reuses stale pre-switch session-bound extension objects. Returns the underlying delivery promise without awaiting it so callers can record the `running` workflow transition as soon as prompt handoff is accepted instead of waiting for the full agent turn to complete on runtimes whose async replacement-session helpers resolve only after `agent_end`. When pi later invalidates that replacement-session context during successful prompt-end restoration, the helper suppresses the documented stale-extension-context rejection because the prompt was already accepted and late rethrow would surface a false orchestration failure. Falls back to `pi.sendUserMessage(...)` only for non-replacement flows or runtimes that do not expose replacement-session helpers. Runtime is O(n) in prompt length. Side effects are limited to user-message delivery.
|
|
@@ -839,7 +892,7 @@ function transitionPromptWorkflowState(
|
|
|
839
892
|
|
|
840
893
|
/**
|
|
841
894
|
* @brief Resolves the runtime slash-command description for one bundled prompt.
|
|
842
|
-
* @details Reads the bundled prompt
|
|
895
|
+
* @details Reads the bundled prompt markdown, extracts the first `# ` heading payload, and falls back to the historical generated label when the prompt omits a level-one heading. Runtime is O(n) in prompt length. Side effects are limited to filesystem reads.
|
|
843
896
|
* @param[in] promptName {import("./core/prompt-command-catalog.js").PromptCommandName} Bundled prompt name.
|
|
844
897
|
* @return {string} Runtime command description.
|
|
845
898
|
*/
|
|
@@ -890,6 +943,38 @@ function notifyContextSafely(
|
|
|
890
943
|
}
|
|
891
944
|
}
|
|
892
945
|
|
|
946
|
+
/**
|
|
947
|
+
* @brief Rejects one non-`idle` req-command invocation and records the workflow error state.
|
|
948
|
+
* @details Builds a deterministic busy-state diagnostic from the current workflow state, transitions the shared workflow state to `error`, preserves any pending or active prompt execution metadata for later closure handling, emits an error notification, and throws `ReqError`. Bundled prompt commands reuse `transitionPromptWorkflowState(...)` when cached configuration is available so prompt debug logging captures the actual state transition; specialized non-prompt commands fall back to direct status mutation. Runtime is O(1). Side effects include workflow-state mutation, status-bar rendering, optional debug-log writes, and user notification delivery.
|
|
949
|
+
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
950
|
+
* @param[in] ctx {ExtensionContext | ExtensionCommandContext} Active extension context.
|
|
951
|
+
* @param[in] promptName {import("./core/prompt-command-catalog.js").PromptCommandName | undefined} Optional bundled prompt name used for prompt debug logging.
|
|
952
|
+
* @return {never} This helper always throws a deterministic `ReqError`.
|
|
953
|
+
* @throws {ReqError} Always throws because non-`idle` req commands are rejected.
|
|
954
|
+
* @satisfies REQ-224
|
|
955
|
+
*/
|
|
956
|
+
function rejectNonIdleReqCommand(
|
|
957
|
+
statusController: PiUsereqStatusController,
|
|
958
|
+
ctx: ExtensionContext | ExtensionCommandContext,
|
|
959
|
+
promptName?: import("./core/prompt-command-catalog.js").PromptCommandName,
|
|
960
|
+
): never {
|
|
961
|
+
const message = `ERROR: Prompt workflow state is ${statusController.state.workflowState}, expected idle.`;
|
|
962
|
+
if (promptName !== undefined && statusController.config !== undefined) {
|
|
963
|
+
transitionPromptWorkflowState(
|
|
964
|
+
statusController,
|
|
965
|
+
ctx,
|
|
966
|
+
resolveDebugProjectBase(ctx.cwd, statusController),
|
|
967
|
+
statusController.config,
|
|
968
|
+
promptName,
|
|
969
|
+
"error",
|
|
970
|
+
);
|
|
971
|
+
} else {
|
|
972
|
+
setPiUsereqWorkflowState(statusController, "error", ctx);
|
|
973
|
+
}
|
|
974
|
+
notifyContextSafely(ctx, message, "error");
|
|
975
|
+
throw new ReqError(message, 1);
|
|
976
|
+
}
|
|
977
|
+
|
|
893
978
|
/**
|
|
894
979
|
* @brief Returns the configurable active-tool inventory visible to the extension.
|
|
895
980
|
* @details Filters runtime tools against the canonical configurable-tool set, keeps only builtin-backed embedded tools, and orders the result by the documented custom/files/embedded/default-disabled grouping. Runtime is O(t log t). No external state is mutated.
|
|
@@ -948,14 +1033,14 @@ function applyConfiguredPiUsereqTools(pi: ExtensionAPI, config: UseReqConfig): v
|
|
|
948
1033
|
|
|
949
1034
|
/**
|
|
950
1035
|
* @brief Handles one intercepted pi lifecycle hook for pi-usereq status updates.
|
|
951
|
-
* @details Applies session-start-specific resource validation, project-config refresh, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. 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, restores the original session-backed `base-path` for every matched worktree-backed completion by reusing persisted replacement-session command contexts when event contexts omit `switchSession()`,
|
|
1036
|
+
* @details Applies session-start-specific resource validation, project-config refresh, startup-tool enablement, and selected debug-tool logging before forwarding the originating hook name and payload into the shared `updateExtensionStatus(...)` pipeline. 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, restores the original session-backed `base-path` for every matched worktree-backed completion by reusing persisted replacement-session command contexts when event contexts omit `switchSession()`, executes the stash-assisted merge-and-delete finalization path for every matched successful worktree-backed completion even when a later busy-command rejection already moved workflow state to `error`, 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 `agent_end` 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.
|
|
952
1037
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
953
1038
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
954
1039
|
* @param[in] hookName {PiUsereqStatusHookName} Intercepted hook name.
|
|
955
1040
|
* @param[in] event {unknown} Hook payload forwarded by pi.
|
|
956
1041
|
* @param[in] ctx {ExtensionContext} Active extension context.
|
|
957
1042
|
* @return {Promise<void>} Promise resolved when hook processing completes.
|
|
958
|
-
* @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
|
|
1043
|
+
* @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
|
|
959
1044
|
*/
|
|
960
1045
|
async function handleExtensionStatusEvent(
|
|
961
1046
|
pi: ExtensionAPI,
|
|
@@ -1026,7 +1111,10 @@ async function handleExtensionStatusEvent(
|
|
|
1026
1111
|
if (hookName === "agent_end") {
|
|
1027
1112
|
if (statusController.config) {
|
|
1028
1113
|
runPiNotifyEffects(
|
|
1029
|
-
|
|
1114
|
+
{
|
|
1115
|
+
...statusController.config,
|
|
1116
|
+
"notify-sound": getPiUsereqRuntimeSoundLevel(statusController),
|
|
1117
|
+
},
|
|
1030
1118
|
event as { messages: AgentEndEvent["messages"] },
|
|
1031
1119
|
notifyRequest,
|
|
1032
1120
|
);
|
|
@@ -1042,7 +1130,6 @@ async function handleExtensionStatusEvent(
|
|
|
1042
1130
|
? `ERROR: Prompt closure retained worktree ${activePromptRequest.worktreeDir} after ${outcome} outcome.`
|
|
1043
1131
|
: undefined;
|
|
1044
1132
|
const shouldFinalizeMatchedSuccess = outcome === "completed"
|
|
1045
|
-
&& statusController.state.workflowState === "running"
|
|
1046
1133
|
&& activePromptRequest.worktreeDir !== undefined;
|
|
1047
1134
|
if (debugConfig) {
|
|
1048
1135
|
logPromptWorkflowEvent(
|
|
@@ -1081,6 +1168,7 @@ async function handleExtensionStatusEvent(
|
|
|
1081
1168
|
mergeSucceeded: boolean;
|
|
1082
1169
|
cleanupSucceeded: boolean;
|
|
1083
1170
|
errorMessage?: string;
|
|
1171
|
+
warningMessage?: string;
|
|
1084
1172
|
activeContext?: unknown;
|
|
1085
1173
|
}
|
|
1086
1174
|
| undefined;
|
|
@@ -1135,6 +1223,14 @@ async function handleExtensionStatusEvent(
|
|
|
1135
1223
|
}
|
|
1136
1224
|
notifyContextSafely(promptContext, finalization.errorMessage, "error");
|
|
1137
1225
|
}
|
|
1226
|
+
if (
|
|
1227
|
+
finalization.warningMessage
|
|
1228
|
+
&& finalization.cleanupSucceeded
|
|
1229
|
+
&& finalization.mergeSucceeded
|
|
1230
|
+
&& !finalization.errorMessage
|
|
1231
|
+
) {
|
|
1232
|
+
notifyContextSafely(promptContext, finalization.warningMessage, "info");
|
|
1233
|
+
}
|
|
1138
1234
|
} else {
|
|
1139
1235
|
try {
|
|
1140
1236
|
promptContext = (await restorePromptCommandExecution(
|
|
@@ -1356,7 +1452,6 @@ async function selectDebugLogOnStatus(
|
|
|
1356
1452
|
description: `Write matching debug entries only while workflow state is ${workflowState}.`,
|
|
1357
1453
|
})),
|
|
1358
1454
|
...buildTerminalSettingsMenuChoices({
|
|
1359
|
-
resetDefaultsValue: DEFAULT_DEBUG_LOG_ON_STATUS,
|
|
1360
1455
|
resetDefaultsDescription: "Restore the documented default workflow-state filter.",
|
|
1361
1456
|
}),
|
|
1362
1457
|
], { initialSelectedId: currentValue });
|
|
@@ -1385,6 +1480,7 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
|
|
|
1385
1480
|
id: "debug-enabled",
|
|
1386
1481
|
label: "Debug",
|
|
1387
1482
|
value: config.DEBUG_ENABLED,
|
|
1483
|
+
values: ["enable", "disable"],
|
|
1388
1484
|
description: "Enable or disable all debug logging behavior and unlock the remaining Debug rows.",
|
|
1389
1485
|
},
|
|
1390
1486
|
buildDebugMenuChoice(
|
|
@@ -1410,6 +1506,7 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
|
|
|
1410
1506
|
id: "debug-status-changes",
|
|
1411
1507
|
label: "Status changes",
|
|
1412
1508
|
value: normalizeDebugStatusChanges(config.DEBUG_STATUS_CHANGES),
|
|
1509
|
+
values: ["enable", "disable"],
|
|
1413
1510
|
description: "Enable or disable `workflow_state` debug entries for prompt-orchestration transitions.",
|
|
1414
1511
|
},
|
|
1415
1512
|
debugEnabled,
|
|
@@ -1419,6 +1516,7 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
|
|
|
1419
1516
|
id: "debug-workflow-events",
|
|
1420
1517
|
label: "Workflow events",
|
|
1421
1518
|
value: normalizeDebugWorkflowEvents(config.DEBUG_WORKFLOW_EVENTS),
|
|
1519
|
+
values: ["enable", "disable"],
|
|
1422
1520
|
description: "Enable or disable dedicated workflow debug entries for activation, restoration, closure, and session-shutdown diagnostics.",
|
|
1423
1521
|
},
|
|
1424
1522
|
debugEnabled,
|
|
@@ -1428,6 +1526,7 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
|
|
|
1428
1526
|
id: `debug-tool:${toolName}`,
|
|
1429
1527
|
label: toolName,
|
|
1430
1528
|
value: enabledTools.has(toolName) ? "enable" : "disable",
|
|
1529
|
+
values: ["enable", "disable"],
|
|
1431
1530
|
description: PI_USEREQ_CUSTOM_TOOL_NAMES.includes(toolName as never)
|
|
1432
1531
|
? `Toggle debug logging for custom tool ${toolName}.`
|
|
1433
1532
|
: `Toggle debug logging for embedded tool ${toolName}.`,
|
|
@@ -1439,12 +1538,12 @@ function buildDebugMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice
|
|
|
1439
1538
|
id: `debug-prompt:${promptName}`,
|
|
1440
1539
|
label: promptName,
|
|
1441
1540
|
value: enabledPrompts.has(promptName) ? "enable" : "disable",
|
|
1541
|
+
values: ["enable", "disable"],
|
|
1442
1542
|
description: `Toggle prompt-orchestration debug logging for /${promptName}.`,
|
|
1443
1543
|
},
|
|
1444
1544
|
debugEnabled,
|
|
1445
1545
|
)),
|
|
1446
1546
|
...buildTerminalSettingsMenuChoices({
|
|
1447
|
-
resetDefaultsValue: DEFAULT_DEBUG_LOG_ON_STATUS,
|
|
1448
1547
|
resetDefaultsDescription: "Restore the documented default Debug configuration.",
|
|
1449
1548
|
}),
|
|
1450
1549
|
];
|
|
@@ -1467,6 +1566,58 @@ async function configureDebugMenu(
|
|
|
1467
1566
|
while (true) {
|
|
1468
1567
|
const choice = await showPiUsereqSettingsMenu(ctx, "Debug", buildDebugMenuChoices(config), {
|
|
1469
1568
|
initialSelectedId: focusedChoiceId,
|
|
1569
|
+
getChoices: () => buildDebugMenuChoices(config),
|
|
1570
|
+
onChange: (choiceId, newValue) => {
|
|
1571
|
+
if (choiceId === "debug-enabled") {
|
|
1572
|
+
config.DEBUG_ENABLED = newValue === "enable" ? "enable" : "disable";
|
|
1573
|
+
onConfigChange();
|
|
1574
|
+
ctx.ui.notify(`Debug ${config.DEBUG_ENABLED}`, "info");
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
if (choiceId === "debug-status-changes") {
|
|
1578
|
+
config.DEBUG_STATUS_CHANGES = normalizeDebugStatusChanges(newValue);
|
|
1579
|
+
onConfigChange();
|
|
1580
|
+
ctx.ui.notify(`Debug status-change logging ${config.DEBUG_STATUS_CHANGES}`, "info");
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
if (choiceId === "debug-workflow-events") {
|
|
1584
|
+
config.DEBUG_WORKFLOW_EVENTS = normalizeDebugWorkflowEvents(newValue);
|
|
1585
|
+
onConfigChange();
|
|
1586
|
+
ctx.ui.notify(`Debug workflow-event logging ${config.DEBUG_WORKFLOW_EVENTS}`, "info");
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
if (choiceId.startsWith("debug-tool:")) {
|
|
1590
|
+
const toolName = choiceId.slice("debug-tool:".length) as PiUsereqStartupToolName;
|
|
1591
|
+
const enabledTools = new Set(normalizeDebugEnabledTools(config.DEBUG_ENABLED_TOOLS));
|
|
1592
|
+
if (newValue === "enable") {
|
|
1593
|
+
enabledTools.add(toolName);
|
|
1594
|
+
} else {
|
|
1595
|
+
enabledTools.delete(toolName);
|
|
1596
|
+
}
|
|
1597
|
+
config.DEBUG_ENABLED_TOOLS = getDebugToolToggleNames().filter((name) => enabledTools.has(name));
|
|
1598
|
+
onConfigChange();
|
|
1599
|
+
ctx.ui.notify(
|
|
1600
|
+
`${newValue === "enable" ? "Enabled" : "Disabled"} debug logging for ${toolName}`,
|
|
1601
|
+
"info",
|
|
1602
|
+
);
|
|
1603
|
+
return;
|
|
1604
|
+
}
|
|
1605
|
+
if (choiceId.startsWith("debug-prompt:")) {
|
|
1606
|
+
const promptName = choiceId.slice("debug-prompt:".length) as (typeof DEBUG_PROMPT_NAMES)[number];
|
|
1607
|
+
const enabledPrompts = new Set(normalizeDebugEnabledPrompts(config.DEBUG_ENABLED_PROMPTS));
|
|
1608
|
+
if (newValue === "enable") {
|
|
1609
|
+
enabledPrompts.add(promptName);
|
|
1610
|
+
} else {
|
|
1611
|
+
enabledPrompts.delete(promptName);
|
|
1612
|
+
}
|
|
1613
|
+
config.DEBUG_ENABLED_PROMPTS = DEBUG_PROMPT_NAMES.filter((name) => enabledPrompts.has(name));
|
|
1614
|
+
onConfigChange();
|
|
1615
|
+
ctx.ui.notify(
|
|
1616
|
+
`${newValue === "enable" ? "Enabled" : "Disabled"} debug logging for ${promptName}`,
|
|
1617
|
+
"info",
|
|
1618
|
+
);
|
|
1619
|
+
}
|
|
1620
|
+
},
|
|
1470
1621
|
});
|
|
1471
1622
|
if (!choice) {
|
|
1472
1623
|
return;
|
|
@@ -1754,6 +1905,13 @@ const PI_NOTIFY_EVENT_MENU_DEFINITIONS: Record<
|
|
|
1754
1905
|
},
|
|
1755
1906
|
};
|
|
1756
1907
|
|
|
1908
|
+
/**
|
|
1909
|
+
* @brief Defines the canonical label used for persisted boot-sound menu rows.
|
|
1910
|
+
* @details Reuses one shared string literal across notification menu rows, selectors, reset previews, and tests so the persisted boot-sound terminology remains stable. Access complexity is O(1).
|
|
1911
|
+
* @satisfies REQ-149, REQ-179
|
|
1912
|
+
*/
|
|
1913
|
+
const PI_NOTIFY_BOOT_SOUND_LABEL = "Enable sound (boot value)";
|
|
1914
|
+
|
|
1757
1915
|
/**
|
|
1758
1916
|
* @brief Formats the top-level summary value for one notification event submenu.
|
|
1759
1917
|
* @details Counts enabled completed/interrupted/failed toggles for the selected transport and renders the result as `n/3 on` for right-aligned menu display. Runtime is O(1). No external state is mutated.
|
|
@@ -1794,7 +1952,7 @@ function buildPiNotifyEventLauncherChoice(
|
|
|
1794
1952
|
|
|
1795
1953
|
/**
|
|
1796
1954
|
* @brief Builds the shared settings-menu choices for one notification event submenu.
|
|
1797
|
-
* @details Serializes completed/interrupted/failed rows with right-aligned `on|off` values, then appends `Reset defaults`
|
|
1955
|
+
* @details Serializes completed/interrupted/failed rows with right-aligned `on|off` values, then appends a value-less `Reset defaults` row for submenu-scoped mutation control. Runtime is O(1). No external state is mutated.
|
|
1798
1956
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
1799
1957
|
* @param[in] eventMenu {PiNotifyEventMenuDefinition} Notification-system event submenu contract.
|
|
1800
1958
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered event-submenu choice vector.
|
|
@@ -1809,6 +1967,7 @@ function buildPiNotifyEventMenuChoices(
|
|
|
1809
1967
|
id: eventMenu.keys[row.eventId],
|
|
1810
1968
|
label: row.label,
|
|
1811
1969
|
value: config[eventMenu.keys[row.eventId]] ? "on" : "off",
|
|
1970
|
+
values: ["on", "off"],
|
|
1812
1971
|
description: `${eventMenu.systemLabel}: ${row.description}`,
|
|
1813
1972
|
})),
|
|
1814
1973
|
...buildTerminalSettingsMenuChoices({
|
|
@@ -1873,7 +2032,23 @@ async function configurePiNotifyEventMenu(
|
|
|
1873
2032
|
ctx,
|
|
1874
2033
|
eventMenu.submenuTitle,
|
|
1875
2034
|
buildPiNotifyEventMenuChoices(config, eventMenu),
|
|
1876
|
-
{
|
|
2035
|
+
{
|
|
2036
|
+
initialSelectedId: focusedChoiceId,
|
|
2037
|
+
getChoices: () => buildPiNotifyEventMenuChoices(config, eventMenu),
|
|
2038
|
+
onChange: (choiceId, newValue) => {
|
|
2039
|
+
const enabled = newValue === "on";
|
|
2040
|
+
config[choiceId as PiNotifyEventBooleanConfigKey] = enabled;
|
|
2041
|
+
onConfigChange();
|
|
2042
|
+
const eventLabel = resolvePiNotifyEventLabel(
|
|
2043
|
+
choiceId as PiNotifyEventBooleanConfigKey,
|
|
2044
|
+
eventMenu,
|
|
2045
|
+
);
|
|
2046
|
+
ctx.ui.notify(
|
|
2047
|
+
`${eventMenu.systemLabel} ${eventLabel} ${enabled ? "enabled" : "disabled"}`,
|
|
2048
|
+
"info",
|
|
2049
|
+
);
|
|
2050
|
+
},
|
|
2051
|
+
},
|
|
1877
2052
|
);
|
|
1878
2053
|
if (!choice) {
|
|
1879
2054
|
return;
|
|
@@ -1925,7 +2100,7 @@ async function configurePiNotifyEventMenu(
|
|
|
1925
2100
|
|
|
1926
2101
|
/**
|
|
1927
2102
|
* @brief Builds the direct Pushover rows rendered inside `Notifications`.
|
|
1928
|
-
* @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, 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.
|
|
2103
|
+
* @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.
|
|
1929
2104
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
1930
2105
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered direct Pushover rows.
|
|
1931
2106
|
* @satisfies REQ-163, REQ-165, REQ-172, REQ-184, REQ-185, REQ-198, REQ-234, REQ-235
|
|
@@ -1937,8 +2112,9 @@ function buildPiNotifyPushoverRows(config: UseReqConfig): PiUsereqSettingsMenuCh
|
|
|
1937
2112
|
id: "notify-pushover-enabled",
|
|
1938
2113
|
label: "Enable pushover",
|
|
1939
2114
|
labelTone: pushoverCredentialsReady ? undefined : "dim",
|
|
1940
|
-
value: pushoverCredentialsReady ? formatPiNotifyPushoverStatus(config) : "
|
|
2115
|
+
value: pushoverCredentialsReady ? formatPiNotifyPushoverStatus(config) : "configure user/token keys first",
|
|
1941
2116
|
valueTone: pushoverCredentialsReady ? undefined : "dim",
|
|
2117
|
+
values: ["on", "off"],
|
|
1942
2118
|
disabled: !pushoverCredentialsReady,
|
|
1943
2119
|
description: pushoverCredentialsReady
|
|
1944
2120
|
? "Enable or disable all Pushover delivery globally."
|
|
@@ -1983,7 +2159,7 @@ function buildPiNotifyPushoverRows(config: UseReqConfig): PiUsereqSettingsMenuCh
|
|
|
1983
2159
|
|
|
1984
2160
|
/**
|
|
1985
2161
|
* @brief Opens the shared settings-menu selector for Pushover priority.
|
|
1986
|
-
* @details Reuses the pi-usereq settings-menu renderer so Pushover priority selection remains stylistically aligned with the notification menus and appends subtree-local `Reset defaults`
|
|
2162
|
+
* @details Reuses the pi-usereq settings-menu renderer so Pushover priority selection remains stylistically aligned with the notification menus and appends a value-less subtree-local `Reset defaults` row. Runtime depends on user interaction count. Side effects are limited to transient custom-UI rendering.
|
|
1987
2163
|
* @param[in] ctx {ExtensionCommandContext} Active command context.
|
|
1988
2164
|
* @param[in] currentPriority {PiNotifyPushoverPriority} Persisted priority value.
|
|
1989
2165
|
* @return {Promise<PiNotifyPushoverPriority | "reset-defaults" | undefined>} Selected priority, reset action, or `undefined` when cancelled.
|
|
@@ -2007,7 +2183,6 @@ async function selectPiNotifyPushoverPriority(
|
|
|
2007
2183
|
description: "Send outbound Pushover messages with high priority `1`.",
|
|
2008
2184
|
},
|
|
2009
2185
|
...buildTerminalSettingsMenuChoices({
|
|
2010
|
-
resetDefaultsValue: formatPiNotifyPushoverPriority(getDefaultConfig("")["notify-pushover-priority"]),
|
|
2011
2186
|
resetDefaultsDescription: "Restore the documented default Pushover priority.",
|
|
2012
2187
|
}),
|
|
2013
2188
|
], { initialSelectedId: String(currentPriority) });
|
|
@@ -2022,10 +2197,10 @@ async function selectPiNotifyPushoverPriority(
|
|
|
2022
2197
|
|
|
2023
2198
|
/**
|
|
2024
2199
|
* @brief Builds the shared settings-menu choices for notification configuration.
|
|
2025
|
-
* @details Serializes command-notify, sound, and Pushover blocks with dedicated shared-event submenu launchers so the settings-menu renderer can expose one unified but modular configuration surface, including locked Pushover enablement and escaped single-line rendering for `Pushover text`. Runtime is O(n) in the longest rendered command or text field. No external state is mutated.
|
|
2200
|
+
* @details Serializes command-notify, sound, and Pushover blocks with dedicated shared-event submenu launchers so the settings-menu renderer can expose one unified but modular configuration surface, including locked Pushover enablement, persisted boot-sound rows that stay decoupled from the active runtime sound level, and escaped single-line rendering for `Pushover text`. Runtime is O(n) in the longest rendered command or text field. No external state is mutated.
|
|
2026
2201
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
2027
2202
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered notification-menu choice vector.
|
|
2028
|
-
* @satisfies REQ-137, REQ-149, REQ-150, REQ-151, REQ-152, REQ-163, REQ-164, REQ-165, REQ-172, REQ-179, REQ-181, REQ-183, REQ-188, REQ-193, REQ-198, REQ-234, REQ-235
|
|
2203
|
+
* @satisfies REQ-137, REQ-149, REQ-150, REQ-151, REQ-152, REQ-163, REQ-164, REQ-165, REQ-172, REQ-179, REQ-181, REQ-183, REQ-188, REQ-193, REQ-198, REQ-234, REQ-235, REQ-289
|
|
2029
2204
|
*/
|
|
2030
2205
|
function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoice[] {
|
|
2031
2206
|
return [
|
|
@@ -2033,6 +2208,7 @@ function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuCho
|
|
|
2033
2208
|
id: "notify-enabled",
|
|
2034
2209
|
label: "Enable notification",
|
|
2035
2210
|
value: formatPiNotifyStatus(config),
|
|
2211
|
+
values: ["on", "off"],
|
|
2036
2212
|
description: "Enable or disable command-notify delivery globally.",
|
|
2037
2213
|
},
|
|
2038
2214
|
buildPiNotifyEventLauncherChoice(
|
|
@@ -2047,9 +2223,9 @@ function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuCho
|
|
|
2047
2223
|
},
|
|
2048
2224
|
{
|
|
2049
2225
|
id: "selected-sound-command",
|
|
2050
|
-
label:
|
|
2226
|
+
label: PI_NOTIFY_BOOT_SOUND_LABEL,
|
|
2051
2227
|
value: config["notify-sound"],
|
|
2052
|
-
description: "
|
|
2228
|
+
description: "Edit the persisted boot sound level without changing the active runtime sound level.",
|
|
2053
2229
|
},
|
|
2054
2230
|
buildPiNotifyEventLauncherChoice(
|
|
2055
2231
|
config,
|
|
@@ -2059,25 +2235,25 @@ function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuCho
|
|
|
2059
2235
|
id: "sound-toggle-hotkey-bind",
|
|
2060
2236
|
label: "Sound toggle hotkey bind",
|
|
2061
2237
|
value: config["notify-sound-toggle-shortcut"],
|
|
2062
|
-
description: "Edit the keyboard shortcut that cycles the
|
|
2238
|
+
description: "Edit the keyboard shortcut that cycles the active runtime sound level.",
|
|
2063
2239
|
},
|
|
2064
2240
|
{
|
|
2065
2241
|
id: "sound-command-low",
|
|
2066
2242
|
label: "Sound command (low vol.)",
|
|
2067
2243
|
value: config.PI_NOTIFY_SOUND_LOW_CMD,
|
|
2068
|
-
description: "Edit the shell command used when the
|
|
2244
|
+
description: "Edit the shell command used when the active runtime sound level is `low`.",
|
|
2069
2245
|
},
|
|
2070
2246
|
{
|
|
2071
2247
|
id: "sound-command-mid",
|
|
2072
2248
|
label: "Sound command (mid vol.)",
|
|
2073
2249
|
value: config.PI_NOTIFY_SOUND_MID_CMD,
|
|
2074
|
-
description: "Edit the shell command used when the
|
|
2250
|
+
description: "Edit the shell command used when the active runtime sound level is `mid`.",
|
|
2075
2251
|
},
|
|
2076
2252
|
{
|
|
2077
2253
|
id: "sound-command-high",
|
|
2078
2254
|
label: "Sound command (high vol.)",
|
|
2079
2255
|
value: config.PI_NOTIFY_SOUND_HIGH_CMD,
|
|
2080
|
-
description: "Edit the shell command used when the
|
|
2256
|
+
description: "Edit the shell command used when the active runtime sound level is `high`.",
|
|
2081
2257
|
},
|
|
2082
2258
|
...buildPiNotifyPushoverRows(config),
|
|
2083
2259
|
...buildTerminalSettingsMenuChoices({
|
|
@@ -2087,45 +2263,44 @@ function buildPiNotifyMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuCho
|
|
|
2087
2263
|
}
|
|
2088
2264
|
|
|
2089
2265
|
/**
|
|
2090
|
-
* @brief Opens the shared settings-menu selector for the
|
|
2091
|
-
* @details Reuses the pi-usereq settings-menu renderer so sound
|
|
2266
|
+
* @brief Opens the shared settings-menu selector for the persisted boot sound level.
|
|
2267
|
+
* @details Reuses the pi-usereq settings-menu renderer so boot-sound selection remains stylistically aligned with the notification menu, keeps the active runtime sound level unchanged, and appends a value-less subtree-local `Reset defaults` row. Runtime depends on user interaction count. Side effects are limited to transient custom-UI rendering.
|
|
2092
2268
|
* @param[in] ctx {ExtensionCommandContext} Active command context.
|
|
2093
|
-
* @param[in] currentLevel {PiNotifySoundLevel}
|
|
2094
|
-
* @return {Promise<PiNotifySoundLevel | "reset-defaults" | undefined>} Selected sound level, reset action, or `undefined` when cancelled.
|
|
2095
|
-
* @satisfies REQ-131, REQ-179, REQ-192
|
|
2269
|
+
* @param[in] currentLevel {PiNotifySoundLevel} Persisted boot sound level.
|
|
2270
|
+
* @return {Promise<PiNotifySoundLevel | "reset-defaults" | undefined>} Selected boot sound level, reset action, or `undefined` when cancelled.
|
|
2271
|
+
* @satisfies REQ-131, REQ-179, REQ-192, REQ-289
|
|
2096
2272
|
*/
|
|
2097
2273
|
async function selectPiNotifySoundLevel(
|
|
2098
2274
|
ctx: ExtensionCommandContext,
|
|
2099
2275
|
currentLevel: PiNotifySoundLevel,
|
|
2100
2276
|
): Promise<PiNotifySoundLevel | "reset-defaults" | undefined> {
|
|
2101
|
-
const choice = await showPiUsereqSettingsMenu(ctx,
|
|
2277
|
+
const choice = await showPiUsereqSettingsMenu(ctx, PI_NOTIFY_BOOT_SOUND_LABEL, [
|
|
2102
2278
|
{
|
|
2103
2279
|
id: "none",
|
|
2104
2280
|
label: "none",
|
|
2105
2281
|
value: currentLevel === "none" ? "selected" : "",
|
|
2106
|
-
description: "
|
|
2282
|
+
description: "Persist `none` as the boot sound level loaded during the next session start.",
|
|
2107
2283
|
},
|
|
2108
2284
|
{
|
|
2109
2285
|
id: "low",
|
|
2110
2286
|
label: "low",
|
|
2111
2287
|
value: currentLevel === "low" ? "selected" : "",
|
|
2112
|
-
description: "
|
|
2288
|
+
description: "Persist `low` as the boot sound level loaded during the next session start.",
|
|
2113
2289
|
},
|
|
2114
2290
|
{
|
|
2115
2291
|
id: "mid",
|
|
2116
2292
|
label: "mid",
|
|
2117
2293
|
value: currentLevel === "mid" ? "selected" : "",
|
|
2118
|
-
description: "
|
|
2294
|
+
description: "Persist `mid` as the boot sound level loaded during the next session start.",
|
|
2119
2295
|
},
|
|
2120
2296
|
{
|
|
2121
2297
|
id: "high",
|
|
2122
2298
|
label: "high",
|
|
2123
2299
|
value: currentLevel === "high" ? "selected" : "",
|
|
2124
|
-
description: "
|
|
2300
|
+
description: "Persist `high` as the boot sound level loaded during the next session start.",
|
|
2125
2301
|
},
|
|
2126
2302
|
...buildTerminalSettingsMenuChoices({
|
|
2127
|
-
|
|
2128
|
-
resetDefaultsDescription: "Restore the documented default sound level.",
|
|
2303
|
+
resetDefaultsDescription: "Restore the documented default boot sound level.",
|
|
2129
2304
|
}),
|
|
2130
2305
|
], { initialSelectedId: currentLevel });
|
|
2131
2306
|
if (!choice) {
|
|
@@ -2139,11 +2314,11 @@ async function selectPiNotifySoundLevel(
|
|
|
2139
2314
|
|
|
2140
2315
|
/**
|
|
2141
2316
|
* @brief Runs the interactive notification-configuration menu.
|
|
2142
|
-
* @details Exposes command-notify, sound, and Pushover controls through the shared settings-menu renderer, delegates completed/interrupted/failed toggles to dedicated event submenus, keeps `Enable pushover` locked until both credentials are populated, decodes escaped control-sequence input for `Pushover text`, and preserves row focus across menu re-renders. Runtime depends on user interaction count. Side effects include UI updates and config mutation.
|
|
2317
|
+
* @details Exposes command-notify, sound, and Pushover controls through the shared settings-menu renderer, delegates completed/interrupted/failed toggles to dedicated event submenus, persists boot-sound changes without altering the active runtime sound level, keeps `Enable pushover` locked until both credentials are populated, decodes escaped control-sequence input for `Pushover text`, and preserves row focus across menu re-renders. Runtime depends on user interaction count. Side effects include UI updates and config mutation.
|
|
2143
2318
|
* @param[in] ctx {ExtensionCommandContext} Active command context.
|
|
2144
2319
|
* @param[in,out] config {UseReqConfig} Mutable configuration object.
|
|
2145
2320
|
* @return {Promise<boolean>} `true` when the sound-toggle shortcut changed.
|
|
2146
|
-
* @satisfies REQ-131, REQ-133, REQ-134, REQ-137, REQ-163, REQ-164, REQ-165, REQ-172, REQ-179, REQ-181, REQ-183, REQ-184, REQ-188, REQ-192, REQ-193, REQ-195, REQ-196, REQ-198, REQ-234, REQ-235
|
|
2321
|
+
* @satisfies REQ-131, REQ-133, REQ-134, REQ-137, REQ-163, REQ-164, REQ-165, REQ-172, REQ-179, REQ-181, REQ-183, REQ-184, REQ-188, REQ-192, REQ-193, REQ-195, REQ-196, REQ-198, REQ-234, REQ-235, REQ-288, REQ-289
|
|
2147
2322
|
*/
|
|
2148
2323
|
async function configurePiNotifyMenu(
|
|
2149
2324
|
ctx: ExtensionCommandContext,
|
|
@@ -2157,7 +2332,27 @@ async function configurePiNotifyMenu(
|
|
|
2157
2332
|
ctx,
|
|
2158
2333
|
"Notifications",
|
|
2159
2334
|
buildPiNotifyMenuChoices(config),
|
|
2160
|
-
{
|
|
2335
|
+
{
|
|
2336
|
+
initialSelectedId: focusedChoiceId,
|
|
2337
|
+
getChoices: () => buildPiNotifyMenuChoices(config),
|
|
2338
|
+
onChange: (choiceId, newValue) => {
|
|
2339
|
+
if (choiceId === "notify-enabled" || choiceId === "notify-pushover-enabled") {
|
|
2340
|
+
if (choiceId === "notify-pushover-enabled" && !hasPiNotifyPushoverCredentials(config)) {
|
|
2341
|
+
config["notify-pushover-enabled"] = false;
|
|
2342
|
+
ctx.ui.notify("Populate both Pushover credential fields before enabling Pushover", "info");
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
const enabled = newValue === "on";
|
|
2346
|
+
config[choiceId as PiNotifyBooleanConfigKey] = enabled;
|
|
2347
|
+
onConfigChange();
|
|
2348
|
+
const labelMap: Record<string, string> = {
|
|
2349
|
+
"notify-enabled": "Notification",
|
|
2350
|
+
"notify-pushover-enabled": "Pushover",
|
|
2351
|
+
};
|
|
2352
|
+
ctx.ui.notify(`${labelMap[choiceId]} ${enabled ? "enabled" : "disabled"}`, "info");
|
|
2353
|
+
}
|
|
2354
|
+
},
|
|
2355
|
+
},
|
|
2161
2356
|
);
|
|
2162
2357
|
if (!choice) {
|
|
2163
2358
|
return config["notify-sound-toggle-shortcut"] !== originalShortcut;
|
|
@@ -2221,22 +2416,22 @@ async function configurePiNotifyMenu(
|
|
|
2221
2416
|
const approved = await confirmResetChanges(
|
|
2222
2417
|
ctx,
|
|
2223
2418
|
"Confirm sound reset",
|
|
2224
|
-
[{ label:
|
|
2419
|
+
[{ label: PI_NOTIFY_BOOT_SOUND_LABEL, previousValue: config["notify-sound"], nextValue: defaultSoundLevel }]
|
|
2225
2420
|
.filter((change) => change.previousValue !== change.nextValue),
|
|
2226
|
-
"Approve restoring the documented default sound level.",
|
|
2227
|
-
"Abort the sound reset and keep the current value.",
|
|
2421
|
+
"Approve restoring the documented default boot sound level.",
|
|
2422
|
+
"Abort the boot sound reset and keep the current value.",
|
|
2228
2423
|
);
|
|
2229
2424
|
if (!approved) {
|
|
2230
|
-
ctx.ui.notify("Aborted sound reset", "info");
|
|
2425
|
+
ctx.ui.notify("Aborted boot sound reset", "info");
|
|
2231
2426
|
} else {
|
|
2232
2427
|
config["notify-sound"] = defaultSoundLevel;
|
|
2233
2428
|
onConfigChange();
|
|
2234
|
-
ctx.ui.notify("Restored default sound level", "info");
|
|
2429
|
+
ctx.ui.notify("Restored default boot sound level; active runtime sound is unchanged", "info");
|
|
2235
2430
|
}
|
|
2236
2431
|
} else if (nextLevel !== undefined) {
|
|
2237
2432
|
config["notify-sound"] = nextLevel;
|
|
2238
2433
|
onConfigChange();
|
|
2239
|
-
ctx.ui.notify(`
|
|
2434
|
+
ctx.ui.notify(`Stored ${PI_NOTIFY_BOOT_SOUND_LABEL.toLowerCase()} as ${nextLevel}; active runtime sound is unchanged`, "info");
|
|
2240
2435
|
}
|
|
2241
2436
|
continue;
|
|
2242
2437
|
}
|
|
@@ -2381,7 +2576,7 @@ async function configurePiNotifyMenu(
|
|
|
2381
2576
|
const defaults = getDefaultConfig("");
|
|
2382
2577
|
const resetPreview: ResetConfirmationChange[] = [
|
|
2383
2578
|
{ label: "Enable notification", previousValue: formatPiNotifyStatus(config), nextValue: formatPiNotifyStatus(defaults) },
|
|
2384
|
-
{ label:
|
|
2579
|
+
{ label: PI_NOTIFY_BOOT_SOUND_LABEL, previousValue: config["notify-sound"], nextValue: defaults["notify-sound"] },
|
|
2385
2580
|
{ label: "Sound toggle hotkey bind", previousValue: config["notify-sound-toggle-shortcut"], nextValue: defaults["notify-sound-toggle-shortcut"] },
|
|
2386
2581
|
{ label: "Notify command", previousValue: config.PI_NOTIFY_CMD, nextValue: defaults.PI_NOTIFY_CMD },
|
|
2387
2582
|
{ label: "Sound command (low vol.)", previousValue: config.PI_NOTIFY_SOUND_LOW_CMD, nextValue: defaults.PI_NOTIFY_SOUND_LOW_CMD },
|
|
@@ -2416,15 +2611,15 @@ async function configurePiNotifyMenu(
|
|
|
2416
2611
|
/**
|
|
2417
2612
|
* @brief Registers the configurable notification-sound shortcut when supported.
|
|
2418
2613
|
* @details Loads the current project config, registers one raw pi shortcut when
|
|
2419
|
-
* the runtime exposes `registerShortcut(...)`, cycles
|
|
2420
|
-
* invocation,
|
|
2421
|
-
* notification. Runtime is O(1) for registration
|
|
2422
|
-
* use. Side effects include shortcut
|
|
2423
|
-
* updates.
|
|
2614
|
+
* the runtime exposes `registerShortcut(...)`, cycles only the active runtime
|
|
2615
|
+
* sound level on invocation, leaves `.pi-usereq.json` unchanged, refreshes the
|
|
2616
|
+
* status bar, and emits one info notification. Runtime is O(1) for registration
|
|
2617
|
+
* plus one status update per shortcut use. Side effects include shortcut
|
|
2618
|
+
* registration and status updates.
|
|
2424
2619
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2425
2620
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
2426
2621
|
* @return {void} No return value.
|
|
2427
|
-
* @satisfies REQ-
|
|
2622
|
+
* @satisfies REQ-134, REQ-180, REQ-286, REQ-287
|
|
2428
2623
|
*/
|
|
2429
2624
|
function registerPiNotifyShortcut(
|
|
2430
2625
|
pi: ExtensionAPI,
|
|
@@ -2438,19 +2633,170 @@ function registerPiNotifyShortcut(
|
|
|
2438
2633
|
shortcutRegistrar.registerShortcut(config["notify-sound-toggle-shortcut"], {
|
|
2439
2634
|
description: "Cycle pi-usereq notification sound level",
|
|
2440
2635
|
handler: async (ctx) => {
|
|
2441
|
-
const
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2636
|
+
const nextRuntimeSoundLevel = cyclePiNotifySoundLevel(
|
|
2637
|
+
getPiUsereqRuntimeSoundLevel(statusController),
|
|
2638
|
+
);
|
|
2639
|
+
setPiUsereqRuntimeSoundLevel(
|
|
2640
|
+
statusController,
|
|
2641
|
+
nextRuntimeSoundLevel,
|
|
2642
|
+
ctx,
|
|
2643
|
+
);
|
|
2644
|
+
ctx.ui.notify(`pi-usereq sound:${nextRuntimeSoundLevel}`, "info");
|
|
2447
2645
|
},
|
|
2448
2646
|
});
|
|
2449
2647
|
}
|
|
2450
2648
|
|
|
2451
2649
|
/**
|
|
2452
|
-
* @brief
|
|
2453
|
-
* @details
|
|
2650
|
+
* @brief Resolves the prompt execution plan targeted by `req-reset` recovery.
|
|
2651
|
+
* @details Prefers the current in-memory active request, then the current in-memory pending request, then the process-scoped persisted prompt runtime state so the dedicated reset command can recover from same-host unclean prompt termination after session replacement. Runtime is O(1). No external state is mutated.
|
|
2652
|
+
* @param[in] statusController {PiUsereqStatusController} Mutable status controller.
|
|
2653
|
+
* @return {PromptCommandExecutionPlan | undefined} Recoverable prompt execution plan when one remains available.
|
|
2654
|
+
*/
|
|
2655
|
+
function resolveReqResetPromptRequest(
|
|
2656
|
+
statusController: PiUsereqStatusController,
|
|
2657
|
+
): PromptCommandExecutionPlan | undefined {
|
|
2658
|
+
const isWorktreeBacked = (request: PromptCommandExecutionPlan | undefined): request is PromptCommandExecutionPlan =>
|
|
2659
|
+
request?.worktreeDir !== undefined
|
|
2660
|
+
&& request.worktreeRootPath !== undefined
|
|
2661
|
+
&& request.worktreePath !== undefined;
|
|
2662
|
+
const inMemoryActiveRequest = statusController.state.activePromptRequest;
|
|
2663
|
+
if (isWorktreeBacked(inMemoryActiveRequest)) {
|
|
2664
|
+
return inMemoryActiveRequest;
|
|
2665
|
+
}
|
|
2666
|
+
const inMemoryPendingRequest = statusController.state.pendingPromptRequest;
|
|
2667
|
+
if (isWorktreeBacked(inMemoryPendingRequest)) {
|
|
2668
|
+
return inMemoryPendingRequest;
|
|
2669
|
+
}
|
|
2670
|
+
const persistedRuntimeState = readPersistedPromptCommandRuntimeState();
|
|
2671
|
+
if (isWorktreeBacked(persistedRuntimeState.activePromptRequest)) {
|
|
2672
|
+
return persistedRuntimeState.activePromptRequest;
|
|
2673
|
+
}
|
|
2674
|
+
if (isWorktreeBacked(persistedRuntimeState.pendingPromptRequest)) {
|
|
2675
|
+
return persistedRuntimeState.pendingPromptRequest;
|
|
2676
|
+
}
|
|
2677
|
+
return inMemoryActiveRequest
|
|
2678
|
+
?? inMemoryPendingRequest
|
|
2679
|
+
?? persistedRuntimeState.activePromptRequest
|
|
2680
|
+
?? persistedRuntimeState.pendingPromptRequest;
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
/**
|
|
2684
|
+
* @brief Registers the specialized `req-reset` slash command.
|
|
2685
|
+
* @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, and notifies pi without starting an LLM session or creating a worktree. Runtime is dominated by session restoration plus git cleanup. Side effects include command registration, status-controller mutation, active-session replacement, worktree deletion, branch deletion, and user notifications.
|
|
2686
|
+
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2687
|
+
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
2688
|
+
* @return {void} No return value.
|
|
2689
|
+
* @satisfies REQ-304, REQ-305, REQ-306, REQ-307, REQ-308, REQ-309, REQ-310, REQ-311, REQ-312, REQ-313
|
|
2690
|
+
*/
|
|
2691
|
+
function registerReqResetCommand(
|
|
2692
|
+
pi: ExtensionAPI,
|
|
2693
|
+
statusController: PiUsereqStatusController,
|
|
2694
|
+
): void {
|
|
2695
|
+
pi.registerCommand("req-reset", {
|
|
2696
|
+
description: REQ_RESET_COMMAND_DESCRIPTION,
|
|
2697
|
+
handler: async (_args, ctx) => {
|
|
2698
|
+
const promptRequest = resolveReqResetPromptRequest(statusController);
|
|
2699
|
+
const commandCwd = resolveLiveBootstrapCwd(ctx.cwd);
|
|
2700
|
+
syncContextCwdMirror(ctx, commandCwd);
|
|
2701
|
+
const projectBase = path.resolve(promptRequest?.basePath ?? getProjectBase(commandCwd));
|
|
2702
|
+
bootstrapRuntimePathState(projectBase, {
|
|
2703
|
+
gitPath: resolveRuntimeGitPath(projectBase),
|
|
2704
|
+
});
|
|
2705
|
+
const config = loadProjectConfig(projectBase);
|
|
2706
|
+
let executionPlan: ReqResetCommandPlan;
|
|
2707
|
+
let executionResult: ReqResetCommandExecutionResult;
|
|
2708
|
+
let resetContext = ctx;
|
|
2709
|
+
|
|
2710
|
+
setPiUsereqStatusConfig(statusController, config);
|
|
2711
|
+
setPiUsereqWorkflowState(statusController, "running", ctx);
|
|
2712
|
+
|
|
2713
|
+
try {
|
|
2714
|
+
executionPlan = prepareReqResetCommandExecution(projectBase, config, promptRequest);
|
|
2715
|
+
executionResult = await executeReqResetCommandExecution(executionPlan, ctx);
|
|
2716
|
+
resetContext = (executionResult.activeContext ?? resetContext) as typeof ctx;
|
|
2717
|
+
} catch (error) {
|
|
2718
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2719
|
+
setPiUsereqWorkflowState(statusController, "error", resetContext);
|
|
2720
|
+
notifyContextSafely(resetContext, message, "error");
|
|
2721
|
+
throw error;
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
const shouldClearPromptState = executionResult.restoredBasePath
|
|
2725
|
+
|| executionPlan.promptRequest === undefined;
|
|
2726
|
+
if (shouldClearPromptState) {
|
|
2727
|
+
statusController.state.pendingPromptRequest = undefined;
|
|
2728
|
+
statusController.state.activePromptRequest = undefined;
|
|
2729
|
+
clearPersistedPromptCommandRuntimeState();
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
if (executionResult.errorMessage) {
|
|
2733
|
+
setPiUsereqWorkflowState(statusController, "error", resetContext);
|
|
2734
|
+
notifyContextSafely(resetContext, executionResult.errorMessage, "error");
|
|
2735
|
+
throw new ReqError(executionResult.errorMessage, 1);
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2738
|
+
setPiUsereqWorkflowState(statusController, "idle", resetContext);
|
|
2739
|
+
const successMessage = executionPlan.promptRequest !== undefined
|
|
2740
|
+
? `SUCCESS: req-reset restored base-path and removed ${executionResult.removedWorktreeDirs.length} worktree(s) plus ${executionResult.removedBranchNames.length} branch(es).`
|
|
2741
|
+
: `SUCCESS: req-reset removed ${executionResult.removedWorktreeDirs.length} worktree(s) plus ${executionResult.removedBranchNames.length} branch(es) and restored idle state.`;
|
|
2742
|
+
notifyContextSafely(resetContext, successMessage, "info");
|
|
2743
|
+
},
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
/**
|
|
2748
|
+
* @brief Registers the specialized `req-references` slash command.
|
|
2749
|
+
* @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, and notifies pi 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, and user notifications.
|
|
2750
|
+
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2751
|
+
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
2752
|
+
* @return {void} No return value.
|
|
2753
|
+
* @satisfies REQ-200, REQ-221, REQ-224, REQ-298, REQ-299, REQ-300, REQ-301, REQ-302, REQ-303
|
|
2754
|
+
*/
|
|
2755
|
+
function registerReqReferencesCommand(
|
|
2756
|
+
pi: ExtensionAPI,
|
|
2757
|
+
statusController: PiUsereqStatusController,
|
|
2758
|
+
): void {
|
|
2759
|
+
pi.registerCommand("req-references", {
|
|
2760
|
+
description: REQ_REFERENCES_COMMAND_DESCRIPTION,
|
|
2761
|
+
handler: async (_args, ctx) => {
|
|
2762
|
+
if (statusController.state.workflowState !== "idle") {
|
|
2763
|
+
rejectNonIdleReqCommand(statusController, ctx);
|
|
2764
|
+
}
|
|
2765
|
+
const commandCwd = resolveLiveBootstrapCwd(ctx.cwd);
|
|
2766
|
+
syncContextCwdMirror(ctx, commandCwd);
|
|
2767
|
+
bootstrapRuntimePathState(commandCwd, {
|
|
2768
|
+
gitPath: resolveRuntimeGitPath(commandCwd),
|
|
2769
|
+
});
|
|
2770
|
+
const projectBase = getProjectBase(commandCwd);
|
|
2771
|
+
const config = loadProjectConfig(commandCwd);
|
|
2772
|
+
setPiUsereqStatusConfig(statusController, config);
|
|
2773
|
+
statusController.state.pendingPromptRequest = undefined;
|
|
2774
|
+
statusController.state.activePromptRequest = undefined;
|
|
2775
|
+
setPiUsereqWorkflowState(statusController, "checking", ctx);
|
|
2776
|
+
try {
|
|
2777
|
+
const executionPlan = prepareReqReferencesCommandExecution(projectBase, config);
|
|
2778
|
+
setPiUsereqWorkflowState(statusController, "running", ctx);
|
|
2779
|
+
executeReqReferencesCommandExecution(executionPlan, config);
|
|
2780
|
+
setPiUsereqWorkflowState(statusController, "idle", ctx);
|
|
2781
|
+
ctx.ui.notify(
|
|
2782
|
+
`SUCCESS: Updated ${formatRuntimePathForDisplay(executionPlan.referencesPath)} and committed changes.`,
|
|
2783
|
+
"info",
|
|
2784
|
+
);
|
|
2785
|
+
} catch (error) {
|
|
2786
|
+
statusController.state.pendingPromptRequest = undefined;
|
|
2787
|
+
statusController.state.activePromptRequest = undefined;
|
|
2788
|
+
setPiUsereqWorkflowState(statusController, "error", ctx);
|
|
2789
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2790
|
+
ctx.ui.notify(message, "error");
|
|
2791
|
+
throw error;
|
|
2792
|
+
}
|
|
2793
|
+
},
|
|
2794
|
+
});
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
/**
|
|
2798
|
+
* @brief Registers bundled prompt-backed commands with the extension.
|
|
2799
|
+
* @details Creates one prompt-template-backed `req-<prompt>` command per bundled prompt name. Each handler rejects non-`idle` workflow state by transitioning the shared workflow state to `error` before command-side preflight, otherwise transitions the shared workflow state through `checking`, `error`, and `running`, runs dedicated prompt-command git and required-doc preflight checks, optionally prepares a dedicated worktree execution plan using the active session directory, persists the prompt metadata needed for switch-triggered rebinding, switches the active session to the verified execution cwd before prompt handoff, logs dedicated workflow-activation diagnostics, renders the prompt, starts prompt delivery into the forked active session, records `running` immediately after delivery handoff begins, and then awaits the wrapped prompt-delivery promise whose stale post-restore rejections are suppressed. Runtime is O(p) for registration; handler cost depends on prompt preflight, worktree preparation, session switching, prompt rendering, prompt dispatch, and optional debug logging. Side effects include command registration, status-controller mutation, worktree creation, active-session replacement, optional worktree rollback, user-message delivery during execution, and optional debug-log writes.
|
|
2454
2800
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2455
2801
|
* @param[in,out] statusController {PiUsereqStatusController} Mutable status controller.
|
|
2456
2802
|
* @return {void} No return value.
|
|
@@ -2465,9 +2811,7 @@ function registerPromptCommands(
|
|
|
2465
2811
|
description: resolvePromptCommandDescription(promptName),
|
|
2466
2812
|
handler: async (args, ctx) => {
|
|
2467
2813
|
if (statusController.state.workflowState !== "idle") {
|
|
2468
|
-
|
|
2469
|
-
ctx.ui.notify(message, "error");
|
|
2470
|
-
throw new ReqError(message, 1);
|
|
2814
|
+
rejectNonIdleReqCommand(statusController, ctx, promptName);
|
|
2471
2815
|
}
|
|
2472
2816
|
const commandCwd = resolveLiveBootstrapCwd(ctx.cwd);
|
|
2473
2817
|
syncContextCwdMirror(ctx, commandCwd);
|
|
@@ -2582,10 +2926,10 @@ function registerPromptCommands(
|
|
|
2582
2926
|
* @details Defines the tool schemas, prompt metadata, and execution handlers that bridge extension tool calls into tool-runner operations without registering duplicate custom slash commands for the same capabilities. Runtime is O(t) for registration; execution cost depends on the selected tool. Side effects include tool registration.
|
|
2583
2927
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2584
2928
|
* @return {void} No return value.
|
|
2585
|
-
* @satisfies REQ-005, REQ-010, REQ-011, REQ-014, REQ-017, REQ-044, REQ-069, REQ-070, REQ-071, REQ-072, REQ-073, REQ-074, REQ-075, REQ-076, REQ-077, REQ-078, REQ-079, REQ-080, REQ-089, REQ-090, REQ-091, REQ-092, REQ-093, REQ-094, REQ-095, REQ-096, REQ-097, REQ-098, REQ-099, REQ-100, REQ-101, REQ-102
|
|
2929
|
+
* @satisfies REQ-005, REQ-010, REQ-011, REQ-014, REQ-017, REQ-044, REQ-069, REQ-070, REQ-071, REQ-072, REQ-073, REQ-074, REQ-075, REQ-076, REQ-077, REQ-078, REQ-079, REQ-080, REQ-089, REQ-090, REQ-091, REQ-092, REQ-093, REQ-094, REQ-095, REQ-096, REQ-097, REQ-098, REQ-099, REQ-100, REQ-101, REQ-102, REQ-293, REQ-294, REQ-295, REQ-296, REQ-297
|
|
2586
2930
|
*/
|
|
2587
2931
|
function registerAgentTools(pi: ExtensionAPI): void {
|
|
2588
|
-
const
|
|
2932
|
+
const filesSummarizeSchema = Type.Object(
|
|
2589
2933
|
{
|
|
2590
2934
|
files: Type.Array(
|
|
2591
2935
|
Type.String({ description: "Project-relative or absolute source file path resolved from the current working directory when not already absolute" }),
|
|
@@ -2637,21 +2981,21 @@ function registerAgentTools(pi: ExtensionAPI): void {
|
|
|
2637
2981
|
});
|
|
2638
2982
|
|
|
2639
2983
|
pi.registerTool({
|
|
2640
|
-
name: "files-
|
|
2641
|
-
label: "files-
|
|
2642
|
-
description: "Scope: explicit source files. Return the monolithic
|
|
2643
|
-
promptSnippet: "Return the monolithic
|
|
2984
|
+
name: "files-summarize",
|
|
2985
|
+
label: "files-summarize",
|
|
2986
|
+
description: "Scope: explicit source files. Return the monolithic summary markdown report in content[0].text and keep only execution metadata in details.execution.",
|
|
2987
|
+
promptSnippet: "Return the monolithic summary markdown report for caller-selected source files.",
|
|
2644
2988
|
promptGuidelines: [
|
|
2645
2989
|
"Scope: explicit source files selected by files[]; caller order is preserved; each item may be project-relative or absolute.",
|
|
2646
2990
|
"Output contract: monolithic markdown in content[0].text; details.execution preserves only exit code and residual diagnostics.",
|
|
2647
|
-
"Formatting contract: content matches the Python
|
|
2991
|
+
"Formatting contract: content matches the Python summary renderer used by `generate_markdown.py`.",
|
|
2648
2992
|
"Behavior contract: missing inputs, non-file inputs, unsupported extensions, and analysis failures surface through details.execution diagnostics.",
|
|
2649
2993
|
],
|
|
2650
|
-
renderResult: buildStructuredToolRenderResult("files-
|
|
2651
|
-
parameters:
|
|
2994
|
+
renderResult: buildStructuredToolRenderResult("files-summarize"),
|
|
2995
|
+
parameters: filesSummarizeSchema,
|
|
2652
2996
|
async execute(_toolCallId, params) {
|
|
2653
2997
|
const contextPath = getRuntimeContextPath(process.cwd());
|
|
2654
|
-
return executeMonolithicTool(() =>
|
|
2998
|
+
return executeMonolithicTool(() => runFilesSummarize(params.files, contextPath));
|
|
2655
2999
|
},
|
|
2656
3000
|
});
|
|
2657
3001
|
|
|
@@ -2722,12 +3066,18 @@ function registerAgentTools(pi: ExtensionAPI): void {
|
|
|
2722
3066
|
},
|
|
2723
3067
|
});
|
|
2724
3068
|
|
|
2725
|
-
const
|
|
3069
|
+
const summarizeSchema = Type.Object(
|
|
2726
3070
|
{},
|
|
2727
3071
|
{
|
|
2728
3072
|
description: "Input contract: no params. Scope is the configured src-dir list resolved from the current project configuration. Output contract: monolithic markdown in content[0].text plus details.execution diagnostics.",
|
|
2729
3073
|
},
|
|
2730
3074
|
);
|
|
3075
|
+
const referencesSchema = Type.Object(
|
|
3076
|
+
{},
|
|
3077
|
+
{
|
|
3078
|
+
description: "Input contract: no params. Scope is the configured src-dir list plus configured docs-dir resolved from the current project configuration. Output contract: content[0].text returns only `success` or `error: <diagnostic>`; the tool overwrites `<docs-dir>/REFERENCES.md` and keeps details.execution diagnostics.",
|
|
3079
|
+
},
|
|
3080
|
+
);
|
|
2731
3081
|
const tokensSchema = Type.Object(
|
|
2732
3082
|
{},
|
|
2733
3083
|
{
|
|
@@ -2736,23 +3086,44 @@ function registerAgentTools(pi: ExtensionAPI): void {
|
|
|
2736
3086
|
);
|
|
2737
3087
|
|
|
2738
3088
|
pi.registerTool({
|
|
2739
|
-
name: "
|
|
2740
|
-
label: "
|
|
2741
|
-
description: "Scope: configured project source directories. Return the monolithic
|
|
2742
|
-
promptSnippet: "Return the monolithic project
|
|
3089
|
+
name: "summarize",
|
|
3090
|
+
label: "summarize",
|
|
3091
|
+
description: "Scope: configured project source directories. Return the monolithic summary markdown report in content[0].text and keep only execution metadata in details.execution.",
|
|
3092
|
+
promptSnippet: "Return the monolithic project summary markdown report from the configured source directories.",
|
|
2743
3093
|
promptGuidelines: [
|
|
2744
3094
|
"Scope: no params; resolve src-dir from the current project configuration and scan the configured source surface from the current working directory.",
|
|
2745
3095
|
"Output contract: monolithic markdown in content[0].text; details.execution preserves only exit code and residual diagnostics.",
|
|
2746
3096
|
"Formatting contract: content prepends the file-structure markdown block before the per-file markdown produced by `generate_markdown.py`.",
|
|
2747
3097
|
"Configuration contract: output changes with cwd-derived project config and src-dir values; the tool does not accept explicit file overrides.",
|
|
2748
3098
|
],
|
|
3099
|
+
renderResult: buildStructuredToolRenderResult("summarize"),
|
|
3100
|
+
parameters: summarizeSchema,
|
|
3101
|
+
async execute() {
|
|
3102
|
+
const contextPath = getRuntimeContextPath(process.cwd());
|
|
3103
|
+
const projectBase = getProjectBase(contextPath);
|
|
3104
|
+
const config = loadProjectConfig(projectBase);
|
|
3105
|
+
return executeMonolithicTool(() => runSummarize(contextPath, config));
|
|
3106
|
+
},
|
|
3107
|
+
});
|
|
3108
|
+
|
|
3109
|
+
pi.registerTool({
|
|
3110
|
+
name: "references",
|
|
3111
|
+
label: "references",
|
|
3112
|
+
description: "Scope: configured project source directories and configured docs-dir. Overwrite REFERENCES.md and return only success or error in content[0].text while keeping execution metadata in details.execution.",
|
|
3113
|
+
promptSnippet: "Generate REFERENCES.md from the configured source directories without returning the generated markdown.",
|
|
3114
|
+
promptGuidelines: [
|
|
3115
|
+
"Scope: no params; resolve src-dir and docs-dir from the current project configuration and current working directory.",
|
|
3116
|
+
"Behavior contract: generate the same file-structure-plus-summary markdown as `summarize` and overwrite `<docs-dir>/REFERENCES.md`.",
|
|
3117
|
+
"Output contract: `content[0].text` is `success` on success or `error: <diagnostic>` on failure; generated markdown is never returned to the LLM.",
|
|
3118
|
+
"Failure contract: source discovery, markdown generation, and file-write errors surface through the status text plus details.execution diagnostics.",
|
|
3119
|
+
],
|
|
2749
3120
|
renderResult: buildStructuredToolRenderResult("references"),
|
|
2750
3121
|
parameters: referencesSchema,
|
|
2751
3122
|
async execute() {
|
|
2752
3123
|
const contextPath = getRuntimeContextPath(process.cwd());
|
|
2753
3124
|
const projectBase = getProjectBase(contextPath);
|
|
2754
3125
|
const config = loadProjectConfig(projectBase);
|
|
2755
|
-
return
|
|
3126
|
+
return executeStatusTool(() => runReferences(contextPath, config));
|
|
2756
3127
|
},
|
|
2757
3128
|
});
|
|
2758
3129
|
|
|
@@ -2923,7 +3294,6 @@ function buildPiUsereqToolsMenuChoices(pi: ExtensionAPI, config: UseReqConfig):
|
|
|
2923
3294
|
description: "Disable every configurable startup tool for future session starts.",
|
|
2924
3295
|
},
|
|
2925
3296
|
...buildTerminalSettingsMenuChoices({
|
|
2926
|
-
resetDefaultsValue: `${normalizeEnabledPiUsereqTools(undefined).length} defaults`,
|
|
2927
3297
|
resetDefaultsDescription: "Restore the documented default startup-tool selection.",
|
|
2928
3298
|
}),
|
|
2929
3299
|
];
|
|
@@ -2931,7 +3301,7 @@ function buildPiUsereqToolsMenuChoices(pi: ExtensionAPI, config: UseReqConfig):
|
|
|
2931
3301
|
|
|
2932
3302
|
/**
|
|
2933
3303
|
* @brief Builds the shared settings-menu choices for per-tool startup toggles.
|
|
2934
|
-
* @details Exposes every configurable startup tool as one row whose right-side value reports the current enabled state, preserves the documented custom/files/embedded/default-disabled ordering, and appends subtree-local `Reset defaults`
|
|
3304
|
+
* @details Exposes every configurable startup tool as one row whose right-side value reports the current enabled state, preserves the documented custom/files/embedded/default-disabled ordering, and appends a value-less subtree-local `Reset defaults` row. Runtime is O(t) in configurable-tool count. No external state is mutated.
|
|
2935
3305
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
2936
3306
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
2937
3307
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered per-tool toggle choices.
|
|
@@ -2944,10 +3314,10 @@ function buildPiUsereqToolToggleChoices(pi: ExtensionAPI, config: UseReqConfig):
|
|
|
2944
3314
|
id: tool.name,
|
|
2945
3315
|
label: tool.name,
|
|
2946
3316
|
value: enabledTools.has(tool.name) ? "on" : "off",
|
|
3317
|
+
values: ["on", "off"],
|
|
2947
3318
|
description: tool.description ?? `Toggle startup activation for ${tool.name}.`,
|
|
2948
3319
|
})),
|
|
2949
3320
|
...buildTerminalSettingsMenuChoices({
|
|
2950
|
-
resetDefaultsValue: `${normalizeEnabledPiUsereqTools(undefined).length} defaults`,
|
|
2951
3321
|
resetDefaultsDescription: "Restore the documented default startup-tool selection.",
|
|
2952
3322
|
}),
|
|
2953
3323
|
];
|
|
@@ -3019,7 +3389,29 @@ async function configurePiUsereqToolsMenu(
|
|
|
3019
3389
|
}
|
|
3020
3390
|
|
|
3021
3391
|
if (choice === "enable-tools") {
|
|
3022
|
-
const selectedToolName = await showPiUsereqSettingsMenu(ctx, "Enable tools", buildPiUsereqToolToggleChoices(pi, config)
|
|
3392
|
+
const selectedToolName = await showPiUsereqSettingsMenu(ctx, "Enable tools", buildPiUsereqToolToggleChoices(pi, config), {
|
|
3393
|
+
getChoices: () => buildPiUsereqToolToggleChoices(pi, config),
|
|
3394
|
+
onChange: (toolName, newValue) => {
|
|
3395
|
+
const enabledTools = new Set(getConfiguredEnabledPiUsereqTools(config));
|
|
3396
|
+
if (newValue === "on") {
|
|
3397
|
+
enabledTools.add(toolName as PiUsereqStartupToolName);
|
|
3398
|
+
} else {
|
|
3399
|
+
enabledTools.delete(toolName as PiUsereqStartupToolName);
|
|
3400
|
+
}
|
|
3401
|
+
setConfiguredPiUsereqTools(
|
|
3402
|
+
pi,
|
|
3403
|
+
config,
|
|
3404
|
+
getPiUsereqStartupTools(pi)
|
|
3405
|
+
.map((tool) => tool.name)
|
|
3406
|
+
.filter((currentToolName) => enabledTools.has(currentToolName)),
|
|
3407
|
+
);
|
|
3408
|
+
onConfigChange();
|
|
3409
|
+
ctx.ui.notify(
|
|
3410
|
+
`${newValue === "on" ? "Enabled" : "Disabled"} ${toolName}`,
|
|
3411
|
+
"info",
|
|
3412
|
+
);
|
|
3413
|
+
},
|
|
3414
|
+
});
|
|
3023
3415
|
if (!selectedToolName) {
|
|
3024
3416
|
continue;
|
|
3025
3417
|
}
|
|
@@ -3145,11 +3537,11 @@ function buildStaticCheckMenuChoices(config: UseReqConfig): PiUsereqSettingsMenu
|
|
|
3145
3537
|
id: `toggle-static-check-language:${language}`,
|
|
3146
3538
|
label: language,
|
|
3147
3539
|
value: languageConfig.enabled === "enable" ? "on" : "off",
|
|
3540
|
+
values: ["on", "off"],
|
|
3148
3541
|
description: `Toggle static-check execution for ${language}. Configured ${configuredCount} ${suffix}. Supported extensions: ${extensions.join(", ")}.`,
|
|
3149
3542
|
};
|
|
3150
3543
|
}),
|
|
3151
3544
|
...buildTerminalSettingsMenuChoices({
|
|
3152
|
-
resetDefaultsValue: formatStaticCheckLanguagesSummary(config),
|
|
3153
3545
|
resetDefaultsDescription: "Restore the documented per-language static-check defaults.",
|
|
3154
3546
|
}),
|
|
3155
3547
|
];
|
|
@@ -3175,7 +3567,6 @@ function buildSupportedStaticCheckLanguageChoices(config: UseReqConfig): PiUsere
|
|
|
3175
3567
|
};
|
|
3176
3568
|
}),
|
|
3177
3569
|
...buildTerminalSettingsMenuChoices({
|
|
3178
|
-
resetDefaultsValue: formatStaticCheckLanguagesSummary(config),
|
|
3179
3570
|
resetDefaultsDescription: "Restore the documented per-language static-check defaults.",
|
|
3180
3571
|
}),
|
|
3181
3572
|
];
|
|
@@ -3201,7 +3592,6 @@ function buildConfiguredStaticCheckLanguageChoices(config: UseReqConfig): PiUser
|
|
|
3201
3592
|
};
|
|
3202
3593
|
}),
|
|
3203
3594
|
...buildTerminalSettingsMenuChoices({
|
|
3204
|
-
resetDefaultsValue: formatStaticCheckLanguagesSummary(config),
|
|
3205
3595
|
resetDefaultsDescription: "Restore the documented per-language static-check defaults.",
|
|
3206
3596
|
}),
|
|
3207
3597
|
];
|
|
@@ -3224,6 +3614,19 @@ async function configureStaticCheckMenu(
|
|
|
3224
3614
|
while (true) {
|
|
3225
3615
|
const staticChoice = await showPiUsereqSettingsMenu(ctx, "Language static code checkers", buildStaticCheckMenuChoices(config), {
|
|
3226
3616
|
initialSelectedId: focusedChoiceId,
|
|
3617
|
+
getChoices: () => buildStaticCheckMenuChoices(config),
|
|
3618
|
+
onChange: (choiceId, newValue) => {
|
|
3619
|
+
if (choiceId.startsWith("toggle-static-check-language:")) {
|
|
3620
|
+
const language = choiceId.slice("toggle-static-check-language:".length);
|
|
3621
|
+
config["static-check"][language] ??= createStaticCheckLanguageConfig([]);
|
|
3622
|
+
config["static-check"][language]!.enabled = newValue === "on" ? "enable" : "disable";
|
|
3623
|
+
onConfigChange();
|
|
3624
|
+
ctx.ui.notify(
|
|
3625
|
+
`${newValue === "on" ? "Enabled" : "Disabled"} static-check for ${language}`,
|
|
3626
|
+
"info",
|
|
3627
|
+
);
|
|
3628
|
+
}
|
|
3629
|
+
},
|
|
3227
3630
|
});
|
|
3228
3631
|
|
|
3229
3632
|
if (!staticChoice) {
|
|
@@ -3390,6 +3793,7 @@ function buildPiUsereqMenuChoices(
|
|
|
3390
3793
|
id: "auto-git-commit",
|
|
3391
3794
|
label: "Auto git commit",
|
|
3392
3795
|
value: config.AUTO_GIT_COMMIT,
|
|
3796
|
+
values: ["enable", "disable"],
|
|
3393
3797
|
description: "Select bundled `git_commit.md` or `git_read-only.md` for `%%COMMIT%%`; disabling also forces prompt-command worktrees off.",
|
|
3394
3798
|
},
|
|
3395
3799
|
{
|
|
@@ -3398,6 +3802,8 @@ function buildPiUsereqMenuChoices(
|
|
|
3398
3802
|
labelTone: autoGitCommitDisabled ? "dim" : undefined,
|
|
3399
3803
|
value: effectiveGitWorktreeEnabled,
|
|
3400
3804
|
valueTone: autoGitCommitDisabled ? "dim" : undefined,
|
|
3805
|
+
values: ["enable", "disable"],
|
|
3806
|
+
disabled: autoGitCommitDisabled,
|
|
3401
3807
|
description: autoGitCommitDisabled
|
|
3402
3808
|
? "Forced to `disable` while `Auto git commit` is disabled."
|
|
3403
3809
|
: "Enable or disable prompt-command worktree orchestration.",
|
|
@@ -3471,7 +3877,6 @@ function buildSrcDirMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoic
|
|
|
3471
3877
|
description: "Select one configured source directory to remove from the current configuration.",
|
|
3472
3878
|
},
|
|
3473
3879
|
...buildTerminalSettingsMenuChoices({
|
|
3474
|
-
resetDefaultsValue: `${DEFAULT_SRC_DIRS.join(", ")}`,
|
|
3475
3880
|
resetDefaultsDescription: "Restore the documented default source-directory configuration.",
|
|
3476
3881
|
}),
|
|
3477
3882
|
];
|
|
@@ -3479,7 +3884,7 @@ function buildSrcDirMenuChoices(config: UseReqConfig): PiUsereqSettingsMenuChoic
|
|
|
3479
3884
|
|
|
3480
3885
|
/**
|
|
3481
3886
|
* @brief Builds the shared settings-menu choices for removing one source-directory entry.
|
|
3482
|
-
* @details Exposes every configured `src-dir` entry as one removable row and appends subtree-local `Reset defaults`
|
|
3887
|
+
* @details Exposes every configured `src-dir` entry as one removable row and appends a value-less subtree-local `Reset defaults` row. Runtime is O(s) in source-directory count. No external state is mutated.
|
|
3483
3888
|
* @param[in] config {UseReqConfig} Effective project configuration.
|
|
3484
3889
|
* @return {PiUsereqSettingsMenuChoice[]} Ordered removable source-directory choices.
|
|
3485
3890
|
* @satisfies REQ-006, REQ-151, REQ-152, REQ-153, REQ-154
|
|
@@ -3493,7 +3898,6 @@ function buildSrcDirRemovalChoices(config: UseReqConfig): PiUsereqSettingsMenuCh
|
|
|
3493
3898
|
description: `Remove the source-directory entry ${entry} from the current configuration.`,
|
|
3494
3899
|
})),
|
|
3495
3900
|
...buildTerminalSettingsMenuChoices({
|
|
3496
|
-
resetDefaultsValue: `${DEFAULT_SRC_DIRS.join(", ")}`,
|
|
3497
3901
|
resetDefaultsDescription: "Restore the documented default source-directory configuration.",
|
|
3498
3902
|
}),
|
|
3499
3903
|
];
|
|
@@ -3532,7 +3936,36 @@ async function configurePiUsereq(
|
|
|
3532
3936
|
ctx,
|
|
3533
3937
|
"pi-usereq",
|
|
3534
3938
|
buildPiUsereqMenuChoices(ctx.cwd, config),
|
|
3535
|
-
{
|
|
3939
|
+
{
|
|
3940
|
+
initialSelectedId: focusedChoiceId,
|
|
3941
|
+
getChoices: () => buildPiUsereqMenuChoices(ctx.cwd, config),
|
|
3942
|
+
onChange: (choiceId, newValue) => {
|
|
3943
|
+
if (choiceId === "auto-git-commit") {
|
|
3944
|
+
config.AUTO_GIT_COMMIT = newValue === "enable" ? "enable" : "disable";
|
|
3945
|
+
if (config.AUTO_GIT_COMMIT === "disable") {
|
|
3946
|
+
config.GIT_WORKTREE_ENABLED = "disable";
|
|
3947
|
+
persistConfigChange();
|
|
3948
|
+
ctx.ui.notify("Auto git commit disabled; Git worktree forced off", "info");
|
|
3949
|
+
} else {
|
|
3950
|
+
persistConfigChange();
|
|
3951
|
+
ctx.ui.notify("Auto git commit enabled", "info");
|
|
3952
|
+
}
|
|
3953
|
+
return;
|
|
3954
|
+
}
|
|
3955
|
+
if (choiceId === "git-worktree-enabled") {
|
|
3956
|
+
if (config.AUTO_GIT_COMMIT === "disable") {
|
|
3957
|
+
ctx.ui.notify("Git worktree is locked while Auto git commit is disabled", "info");
|
|
3958
|
+
return;
|
|
3959
|
+
}
|
|
3960
|
+
config.GIT_WORKTREE_ENABLED = newValue === "enable" ? "enable" : "disable";
|
|
3961
|
+
persistConfigChange();
|
|
3962
|
+
ctx.ui.notify(
|
|
3963
|
+
`Git worktree ${resolveEffectiveGitWorktreeEnabled(config.AUTO_GIT_COMMIT, config.GIT_WORKTREE_ENABLED) === "enable" ? "enabled" : "disabled"}`,
|
|
3964
|
+
"info",
|
|
3965
|
+
);
|
|
3966
|
+
}
|
|
3967
|
+
},
|
|
3968
|
+
},
|
|
3536
3969
|
);
|
|
3537
3970
|
if (!choice) {
|
|
3538
3971
|
if (config["notify-sound-toggle-shortcut"] !== initialShortcut) {
|
|
@@ -3752,23 +4185,16 @@ function registerConfigCommands(
|
|
|
3752
4185
|
|
|
3753
4186
|
/**
|
|
3754
4187
|
* @brief Registers the complete pi-usereq extension.
|
|
3755
|
-
* @details Validates installation-owned bundled resources, registers prompt and
|
|
3756
|
-
* configuration commands plus agent tools, registers the configurable
|
|
3757
|
-
* notification-sound shortcut when the runtime supports shortcuts, and
|
|
3758
|
-
* installs shared wrappers for all supported pi lifecycle hooks so status
|
|
3759
|
-
* telemetry, context usage, prompt timing, cumulative runtime, prompt-specific
|
|
3760
|
-
* Pushover metadata, tool-result debug logging, and prompt-orchestration debug
|
|
3761
|
-
* effects remain synchronized with runtime events. Runtime is O(h) in hook
|
|
3762
|
-
* count during registration. Side effects include filesystem reads,
|
|
3763
|
-
* command/tool/shortcut registration, UI updates, active-tool changes,
|
|
3764
|
-
* optional debug-log writes, and timer scheduling.
|
|
4188
|
+
* @details Validates installation-owned bundled resources, registers the specialized `req-reset` and `req-references` commands plus bundled prompt-backed commands and agent tools, 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.
|
|
3765
4189
|
* @param[in] pi {ExtensionAPI} Active extension API instance.
|
|
3766
4190
|
* @return {void} No return value.
|
|
3767
|
-
* @satisfies DES-002, 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-
|
|
4191
|
+
* @satisfies DES-002, 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
|
|
3768
4192
|
*/
|
|
3769
4193
|
export default function piUsereqExtension(pi: ExtensionAPI): void {
|
|
3770
4194
|
const statusController = createPiUsereqStatusController();
|
|
3771
4195
|
ensureBundledResourcesAccessible();
|
|
4196
|
+
registerReqResetCommand(pi, statusController);
|
|
4197
|
+
registerReqReferencesCommand(pi, statusController);
|
|
3772
4198
|
registerPromptCommands(pi, statusController);
|
|
3773
4199
|
registerAgentTools(pi);
|
|
3774
4200
|
registerConfigCommands(pi, statusController);
|