@mrclrchtr/supi-ask-user 1.7.0 → 1.8.1
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 +8 -6
- package/node_modules/@mrclrchtr/supi-core/README.md +3 -13
- package/node_modules/@mrclrchtr/supi-core/package.json +13 -8
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +26 -92
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/context.ts +16 -0
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +26 -92
- package/node_modules/@mrclrchtr/supi-core/src/path.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/project.ts +15 -0
- package/node_modules/@mrclrchtr/supi-core/src/session.ts +4 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings-ui.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/settings.ts +9 -0
- package/node_modules/@mrclrchtr/supi-core/src/substrate-types.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/types.ts +2 -0
- package/package.json +5 -5
- package/src/ask-user.ts +1 -1
- package/src/schema.ts +24 -33
- package/src/tool/guidance.ts +4 -6
- package/src/ui/overlay-render.ts +15 -7
- package/src/ui/overlay-view.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/extension.ts +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# @mrclrchtr/supi-ask-user
|
|
2
4
|
|
|
3
5
|
Adds a redesigned `ask_user` tool to the [pi coding agent](https://github.com/earendil-works/pi). It lets the model pause and request a small decision form when explicit human input is required.
|
|
@@ -14,7 +16,9 @@ For local development:
|
|
|
14
16
|
pi install ./packages/supi-ask-user
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+

|
|
18
22
|
|
|
19
23
|
## What you get
|
|
20
24
|
|
|
@@ -114,12 +118,10 @@ A completed form returns a result with `details.status` set to one of:
|
|
|
114
118
|
|
|
115
119
|
The tool registers the following prompt guidance that the model sees:
|
|
116
120
|
|
|
117
|
-
- Use ask_user only
|
|
121
|
+
- Use ask_user only for blocking user input, not open-ended interviews or repo facts.
|
|
118
122
|
- Use ask_user with 1-4 related questions; prefer one when possible.
|
|
119
|
-
- Use ask_user `choice` for fixed options and ask_user `text` for freeform input;
|
|
120
|
-
-
|
|
121
|
-
- Use ask_user `allowDiscuss` or `allowPartialSubmit` only when that outcome is actionable.
|
|
122
|
-
- Do not call ask_user while another ask_user form is already in flight.
|
|
123
|
+
- Use ask_user `choice` for fixed options and ask_user `text` for freeform input; yes/no should be a `choice`.
|
|
124
|
+
- Keep one ask_user form active at a time; use `allowOther` only for single-select choice and `allowDiscuss`/`allowPartialSubmit` only when actionable.
|
|
123
125
|
|
|
124
126
|
## UI controls
|
|
125
127
|
|
|
@@ -1,29 +1,20 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# @mrclrchtr/supi-core
|
|
2
4
|
|
|
3
5
|
Shared infrastructure for SuPi extensions.
|
|
4
6
|
|
|
5
|
-
This
|
|
7
|
+
This is a **pure library** — it does not register any pi commands or tools. The `/supi-settings` command is now available through `@mrclrchtr/supi-settings`.
|
|
6
8
|
|
|
7
9
|
## Install
|
|
8
10
|
|
|
9
|
-
### As a dependency for another extension
|
|
10
|
-
|
|
11
11
|
```bash
|
|
12
12
|
pnpm add @mrclrchtr/supi-core
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
### As a pi package
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
pi install npm:@mrclrchtr/supi-core
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Installing it as a pi package adds the minimal `/supi-settings` extension surface.
|
|
22
|
-
|
|
23
15
|
## Package surfaces
|
|
24
16
|
|
|
25
17
|
- `@mrclrchtr/supi-core/api` — reusable helpers for other packages and extensions
|
|
26
|
-
- `@mrclrchtr/supi-core/extension` — minimal pi extension that registers `/supi-settings`
|
|
27
18
|
|
|
28
19
|
## What you get from the API
|
|
29
20
|
|
|
@@ -101,7 +92,6 @@ const message = wrapExtensionContext("my-extension", "hello", {
|
|
|
101
92
|
## Source
|
|
102
93
|
|
|
103
94
|
- `src/api.ts` — exported library surface
|
|
104
|
-
- `src/extension.ts` — minimal `/supi-settings` entrypoint
|
|
105
95
|
- `src/config.ts` — shared config loading and writing
|
|
106
96
|
- `src/config-settings.ts` — config-backed settings registration helper
|
|
107
97
|
- `src/settings-ui.ts` — shared settings overlay
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "SuPi core — shared infrastructure for SuPi extensions (XML context tags, config system)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,12 +37,17 @@
|
|
|
37
37
|
"main": "src/api.ts",
|
|
38
38
|
"exports": {
|
|
39
39
|
"./api": "./src/api.ts",
|
|
40
|
-
"./
|
|
41
|
-
"./
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
"./config": "./src/config.ts",
|
|
41
|
+
"./context": "./src/context.ts",
|
|
42
|
+
"./debug": "./src/debug-registry.ts",
|
|
43
|
+
"./package.json": "./package.json",
|
|
44
|
+
"./path": "./src/path.ts",
|
|
45
|
+
"./project": "./src/project.ts",
|
|
46
|
+
"./session": "./src/session.ts",
|
|
47
|
+
"./settings": "./src/settings.ts",
|
|
48
|
+
"./settings-ui": "./src/settings-ui.ts",
|
|
49
|
+
"./terminal": "./src/terminal.ts",
|
|
50
|
+
"./tool-framework": "./src/tool-framework.ts",
|
|
51
|
+
"./types": "./src/types.ts"
|
|
47
52
|
}
|
|
48
53
|
}
|
|
@@ -1,96 +1,30 @@
|
|
|
1
1
|
// supi-core — shared infrastructure for SuPi extensions.
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
3
|
// settings registry for supi-wide TUI settings, and a shared tool-spec/registration framework.
|
|
4
|
+
//
|
|
5
|
+
// Convenience barrel — re-exports all domain entry points.
|
|
6
|
+
// For lighter imports, use one of the domain subpaths directly
|
|
7
|
+
// (e.g. @mrclrchtr/supi-core/config, @mrclrchtr/supi-core/context).
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
registerContextProvider,
|
|
28
|
-
} from "./context/context-provider-registry.ts";
|
|
29
|
-
export { wrapExtensionContext } from "./context/context-tag.ts";
|
|
30
|
-
export type {
|
|
31
|
-
DebugAgentAccess,
|
|
32
|
-
DebugEvent,
|
|
33
|
-
DebugEventInput,
|
|
34
|
-
DebugEventQuery,
|
|
35
|
-
DebugEventQueryResult,
|
|
36
|
-
DebugEventView,
|
|
37
|
-
DebugLevel,
|
|
38
|
-
DebugNotifyLevel,
|
|
39
|
-
DebugRegistryConfig,
|
|
40
|
-
DebugSummary,
|
|
41
|
-
} from "./debug-registry.ts";
|
|
42
|
-
export {
|
|
43
|
-
clearDebugEvents,
|
|
44
|
-
configureDebugRegistry,
|
|
45
|
-
DEBUG_REGISTRY_DEFAULTS,
|
|
46
|
-
getDebugEvents,
|
|
47
|
-
getDebugRegistryConfig,
|
|
48
|
-
getDebugSummary,
|
|
49
|
-
recordDebugEvent,
|
|
50
|
-
redactDebugData,
|
|
51
|
-
resetDebugRegistry,
|
|
52
|
-
} from "./debug-registry.ts";
|
|
53
|
-
export { fileToUri, resolveToolPath, stripToolPathPrefix, uriToFile } from "./path-utils.ts";
|
|
54
|
-
export type { KnownRootEntry } from "./project-roots.ts";
|
|
55
|
-
export {
|
|
56
|
-
buildKnownRootsMap,
|
|
57
|
-
byPathDepth,
|
|
58
|
-
dedupeTopmostRoots,
|
|
59
|
-
findProjectRoot,
|
|
60
|
-
isWithin,
|
|
61
|
-
isWithinOrEqual,
|
|
62
|
-
mergeKnownRoots,
|
|
63
|
-
resolveKnownRoot,
|
|
64
|
-
segmentCount,
|
|
65
|
-
sortRootsBySpecificity,
|
|
66
|
-
walkProject,
|
|
67
|
-
} from "./project-roots.ts";
|
|
68
|
-
export { createRegistry, createSessionStateRegistry } from "./registry-utils.ts";
|
|
69
|
-
export { getActiveBranchEntries } from "./session-utils.ts";
|
|
70
|
-
export { registerSettingsCommand } from "./settings/settings-command.ts";
|
|
71
|
-
export type { SettingsScope, SettingsSection } from "./settings/settings-registry.ts";
|
|
72
|
-
export {
|
|
73
|
-
clearRegisteredSettings,
|
|
74
|
-
getRegisteredSettings,
|
|
75
|
-
registerSettings,
|
|
76
|
-
} from "./settings/settings-registry.ts";
|
|
77
|
-
export { createInputSubmenu, openSettingsOverlay } from "./settings/settings-ui.ts";
|
|
78
|
-
export type { TitleTarget } from "./terminal.ts";
|
|
79
|
-
export {
|
|
80
|
-
DONE_SYMBOL,
|
|
81
|
-
formatTitle,
|
|
82
|
-
signalBell,
|
|
83
|
-
signalDone,
|
|
84
|
-
signalWaiting,
|
|
85
|
-
WAITING_SYMBOL,
|
|
86
|
-
} from "./terminal.ts";
|
|
87
|
-
export type { SuiPiToolPromptSurface, SuiPiToolSpec, ToolExecuteFn } from "./tool-framework.ts";
|
|
88
|
-
export {
|
|
89
|
-
CharacterParam,
|
|
90
|
-
derivePromptSurface,
|
|
91
|
-
FileParam,
|
|
92
|
-
LineParam,
|
|
93
|
-
MaxResultsParam,
|
|
94
|
-
registerSuiPiTools,
|
|
95
|
-
SymbolParam,
|
|
96
|
-
} from "./tool-framework.ts";
|
|
9
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
|
+
export * from "./config.ts";
|
|
11
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
12
|
+
export * from "./context.ts";
|
|
13
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
14
|
+
export * from "./debug-registry.ts";
|
|
15
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
16
|
+
export * from "./path.ts";
|
|
17
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
18
|
+
export * from "./project.ts";
|
|
19
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
20
|
+
export * from "./session.ts";
|
|
21
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
22
|
+
export * from "./settings.ts";
|
|
23
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
24
|
+
export * from "./settings-ui.ts";
|
|
25
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
26
|
+
export * from "./terminal.ts";
|
|
27
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
28
|
+
export * from "./tool-framework.ts";
|
|
29
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
30
|
+
export * from "./types.ts";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// supi-core config domain — config loading and config-settings helpers.
|
|
2
|
+
export type { SupiConfigLocation, SupiConfigOptions } from "./config/config.ts";
|
|
3
|
+
export {
|
|
4
|
+
loadSupiConfig,
|
|
5
|
+
loadSupiConfigForScope,
|
|
6
|
+
readJsonFile,
|
|
7
|
+
removeSupiConfigKey,
|
|
8
|
+
writeSupiConfig,
|
|
9
|
+
} from "./config/config.ts";
|
|
10
|
+
export type { ConfigSettingsHelpers, ConfigSettingsOptions } from "./config/config-settings.ts";
|
|
11
|
+
export { registerConfigSettings } from "./config/config-settings.ts";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// supi-core context domain — context messages, providers, and XML tags.
|
|
2
|
+
export type { ContextMessageLike } from "./context/context-messages.ts";
|
|
3
|
+
export {
|
|
4
|
+
findLastUserMessageIndex,
|
|
5
|
+
getContextToken,
|
|
6
|
+
getPromptContent,
|
|
7
|
+
pruneAndReorderContextMessages,
|
|
8
|
+
restorePromptContent,
|
|
9
|
+
} from "./context/context-messages.ts";
|
|
10
|
+
export type { ContextProvider } from "./context/context-provider-registry.ts";
|
|
11
|
+
export {
|
|
12
|
+
clearRegisteredContextProviders,
|
|
13
|
+
getRegisteredContextProviders,
|
|
14
|
+
registerContextProvider,
|
|
15
|
+
} from "./context/context-provider-registry.ts";
|
|
16
|
+
export { wrapExtensionContext } from "./context/context-tag.ts";
|
|
@@ -1,96 +1,30 @@
|
|
|
1
1
|
// supi-core — shared infrastructure for SuPi extensions.
|
|
2
2
|
// Provides XML context tag wrapping, unified config system, context-message utilities,
|
|
3
3
|
// settings registry for supi-wide TUI settings, and a shared tool-spec/registration framework.
|
|
4
|
+
//
|
|
5
|
+
// Convenience barrel — re-exports all domain entry points.
|
|
6
|
+
// For lighter imports, use one of the domain subpaths directly
|
|
7
|
+
// (e.g. @mrclrchtr/supi-core/config, @mrclrchtr/supi-core/context).
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
export
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
registerContextProvider,
|
|
28
|
-
} from "./context/context-provider-registry.ts";
|
|
29
|
-
export { wrapExtensionContext } from "./context/context-tag.ts";
|
|
30
|
-
export type {
|
|
31
|
-
DebugAgentAccess,
|
|
32
|
-
DebugEvent,
|
|
33
|
-
DebugEventInput,
|
|
34
|
-
DebugEventQuery,
|
|
35
|
-
DebugEventQueryResult,
|
|
36
|
-
DebugEventView,
|
|
37
|
-
DebugLevel,
|
|
38
|
-
DebugNotifyLevel,
|
|
39
|
-
DebugRegistryConfig,
|
|
40
|
-
DebugSummary,
|
|
41
|
-
} from "./debug-registry.ts";
|
|
42
|
-
export {
|
|
43
|
-
clearDebugEvents,
|
|
44
|
-
configureDebugRegistry,
|
|
45
|
-
DEBUG_REGISTRY_DEFAULTS,
|
|
46
|
-
getDebugEvents,
|
|
47
|
-
getDebugRegistryConfig,
|
|
48
|
-
getDebugSummary,
|
|
49
|
-
recordDebugEvent,
|
|
50
|
-
redactDebugData,
|
|
51
|
-
resetDebugRegistry,
|
|
52
|
-
} from "./debug-registry.ts";
|
|
53
|
-
export { fileToUri, resolveToolPath, stripToolPathPrefix, uriToFile } from "./path-utils.ts";
|
|
54
|
-
export type { KnownRootEntry } from "./project-roots.ts";
|
|
55
|
-
export {
|
|
56
|
-
buildKnownRootsMap,
|
|
57
|
-
byPathDepth,
|
|
58
|
-
dedupeTopmostRoots,
|
|
59
|
-
findProjectRoot,
|
|
60
|
-
isWithin,
|
|
61
|
-
isWithinOrEqual,
|
|
62
|
-
mergeKnownRoots,
|
|
63
|
-
resolveKnownRoot,
|
|
64
|
-
segmentCount,
|
|
65
|
-
sortRootsBySpecificity,
|
|
66
|
-
walkProject,
|
|
67
|
-
} from "./project-roots.ts";
|
|
68
|
-
export { createRegistry, createSessionStateRegistry } from "./registry-utils.ts";
|
|
69
|
-
export { getActiveBranchEntries } from "./session-utils.ts";
|
|
70
|
-
export { registerSettingsCommand } from "./settings/settings-command.ts";
|
|
71
|
-
export type { SettingsScope, SettingsSection } from "./settings/settings-registry.ts";
|
|
72
|
-
export {
|
|
73
|
-
clearRegisteredSettings,
|
|
74
|
-
getRegisteredSettings,
|
|
75
|
-
registerSettings,
|
|
76
|
-
} from "./settings/settings-registry.ts";
|
|
77
|
-
export { createInputSubmenu, openSettingsOverlay } from "./settings/settings-ui.ts";
|
|
78
|
-
export type { TitleTarget } from "./terminal.ts";
|
|
79
|
-
export {
|
|
80
|
-
DONE_SYMBOL,
|
|
81
|
-
formatTitle,
|
|
82
|
-
signalBell,
|
|
83
|
-
signalDone,
|
|
84
|
-
signalWaiting,
|
|
85
|
-
WAITING_SYMBOL,
|
|
86
|
-
} from "./terminal.ts";
|
|
87
|
-
export type { SuiPiToolPromptSurface, SuiPiToolSpec, ToolExecuteFn } from "./tool-framework.ts";
|
|
88
|
-
export {
|
|
89
|
-
CharacterParam,
|
|
90
|
-
derivePromptSurface,
|
|
91
|
-
FileParam,
|
|
92
|
-
LineParam,
|
|
93
|
-
MaxResultsParam,
|
|
94
|
-
registerSuiPiTools,
|
|
95
|
-
SymbolParam,
|
|
96
|
-
} from "./tool-framework.ts";
|
|
9
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
10
|
+
export * from "./config.ts";
|
|
11
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
12
|
+
export * from "./context.ts";
|
|
13
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
14
|
+
export * from "./debug-registry.ts";
|
|
15
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
16
|
+
export * from "./path.ts";
|
|
17
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
18
|
+
export * from "./project.ts";
|
|
19
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
20
|
+
export * from "./session.ts";
|
|
21
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
22
|
+
export * from "./settings.ts";
|
|
23
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
24
|
+
export * from "./settings-ui.ts";
|
|
25
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
26
|
+
export * from "./terminal.ts";
|
|
27
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
28
|
+
export * from "./tool-framework.ts";
|
|
29
|
+
// biome-ignore lint/performance/noReExportAll: intentional convenience barrel
|
|
30
|
+
export * from "./types.ts";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// supi-core project domain — project root discovery and traversal.
|
|
2
|
+
export type { KnownRootEntry } from "./project-roots.ts";
|
|
3
|
+
export {
|
|
4
|
+
buildKnownRootsMap,
|
|
5
|
+
byPathDepth,
|
|
6
|
+
dedupeTopmostRoots,
|
|
7
|
+
findProjectRoot,
|
|
8
|
+
isWithin,
|
|
9
|
+
isWithinOrEqual,
|
|
10
|
+
mergeKnownRoots,
|
|
11
|
+
resolveKnownRoot,
|
|
12
|
+
segmentCount,
|
|
13
|
+
sortRootsBySpecificity,
|
|
14
|
+
walkProject,
|
|
15
|
+
} from "./project-roots.ts";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// supi-core settings domain — settings registry (lightweight, type-only pi-tui import).
|
|
2
|
+
|
|
3
|
+
export { registerSettingsCommand } from "./settings/settings-command.ts";
|
|
4
|
+
export type { SettingsScope, SettingsSection } from "./settings/settings-registry.ts";
|
|
5
|
+
export {
|
|
6
|
+
clearRegisteredSettings,
|
|
7
|
+
getRegisteredSettings,
|
|
8
|
+
registerSettings,
|
|
9
|
+
} from "./settings/settings-registry.ts";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** 0-based position used by LSP and code-intelligence internally. */
|
|
2
|
+
export interface CodePosition {
|
|
3
|
+
line: number;
|
|
4
|
+
character: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/** Normalized location — flat replacement for LSP's nested Location/range shape. */
|
|
8
|
+
export interface CodeLocation {
|
|
9
|
+
uri: string;
|
|
10
|
+
range: { start: CodePosition; end: CodePosition };
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-ask-user",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "SuPi ask-user extension — rich questionnaire UI for structured agent-user decisions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"main": "src/api.ts",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@mrclrchtr/supi-core": "1.
|
|
24
|
+
"@mrclrchtr/supi-core": "1.8.1"
|
|
25
25
|
},
|
|
26
26
|
"bundledDependencies": [
|
|
27
27
|
"@mrclrchtr/supi-core"
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
},
|
|
45
45
|
"pi": {
|
|
46
46
|
"extensions": [
|
|
47
|
-
"./src/extension.ts"
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
"./src/extension.ts"
|
|
48
|
+
],
|
|
49
|
+
"image": "https://raw.githubusercontent.com/mrclrchtr/supi/main/packages/supi-ask-user/assets/logo.png"
|
|
50
50
|
},
|
|
51
51
|
"exports": {
|
|
52
52
|
"./api": "./src/api.ts",
|
package/src/ask-user.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { formatTitle, signalWaiting } from "@mrclrchtr/supi-core/
|
|
2
|
+
import { formatTitle, signalWaiting } from "@mrclrchtr/supi-core/terminal";
|
|
3
3
|
import { AskUserValidationError, normalizeQuestionnaire } from "./normalize.ts";
|
|
4
4
|
import { type AskUserToolResult, buildErrorResult, buildResult } from "./render/result.ts";
|
|
5
5
|
import { renderAskUserCall, renderAskUserResult } from "./render/transcript.ts";
|
package/src/schema.ts
CHANGED
|
@@ -3,101 +3,92 @@
|
|
|
3
3
|
import { type Static, Type } from "typebox";
|
|
4
4
|
|
|
5
5
|
const OptionSchema = Type.Object({
|
|
6
|
-
value: Type.String({ description: "
|
|
7
|
-
label: Type.String({ description: "
|
|
6
|
+
value: Type.String({ description: "Returned id" }),
|
|
7
|
+
label: Type.String({ description: "Displayed label" }),
|
|
8
8
|
description: Type.Optional(
|
|
9
9
|
Type.String({
|
|
10
|
-
description: "Optional
|
|
10
|
+
description: "Optional note",
|
|
11
11
|
}),
|
|
12
12
|
),
|
|
13
13
|
preview: Type.Optional(
|
|
14
14
|
Type.String({
|
|
15
|
-
description: "Optional preview
|
|
15
|
+
description: "Optional preview",
|
|
16
16
|
}),
|
|
17
17
|
),
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
const ChoiceQuestionSchema = Type.Object({
|
|
21
21
|
type: Type.Literal("choice"),
|
|
22
|
-
id: Type.String({ description: "
|
|
23
|
-
header: Type.String({ description: "Short label
|
|
24
|
-
prompt: Type.String({ description: "
|
|
22
|
+
id: Type.String({ description: "Question id" }),
|
|
23
|
+
header: Type.String({ description: "Short label" }),
|
|
24
|
+
prompt: Type.String({ description: "Question text" }),
|
|
25
25
|
options: Type.Array(OptionSchema, {
|
|
26
|
-
description: "Allowed
|
|
26
|
+
description: "Allowed options (2-12)",
|
|
27
27
|
}),
|
|
28
28
|
required: Type.Optional(
|
|
29
29
|
Type.Boolean({
|
|
30
30
|
default: true,
|
|
31
|
-
description: "
|
|
31
|
+
description: "Required for full submit",
|
|
32
32
|
}),
|
|
33
33
|
),
|
|
34
34
|
multi: Type.Optional(
|
|
35
35
|
Type.Boolean({
|
|
36
36
|
default: false,
|
|
37
|
-
description: "Allow
|
|
37
|
+
description: "Allow multiple selections",
|
|
38
38
|
}),
|
|
39
39
|
),
|
|
40
40
|
allowOther: Type.Optional(
|
|
41
41
|
Type.Boolean({
|
|
42
|
-
description:
|
|
43
|
-
"Allow a custom freeform answer instead of the listed options. Only valid for single-select choice questions.",
|
|
42
|
+
description: "Allow a custom option; single-select only",
|
|
44
43
|
}),
|
|
45
44
|
),
|
|
46
45
|
recommendation: Type.Optional(
|
|
47
46
|
Type.Union([Type.String(), Type.Array(Type.String())], {
|
|
48
|
-
description:
|
|
49
|
-
"Recommended option value or values. Use a string for single-select and an array for multi-select.",
|
|
47
|
+
description: "Recommended value(s)",
|
|
50
48
|
}),
|
|
51
49
|
),
|
|
52
50
|
initial: Type.Optional(
|
|
53
51
|
Type.Union([Type.String(), Type.Array(Type.String())], {
|
|
54
|
-
description:
|
|
55
|
-
"Initial selected option value or values. Use a string for single-select and an array for multi-select.",
|
|
52
|
+
description: "Initial value(s)",
|
|
56
53
|
}),
|
|
57
54
|
),
|
|
58
55
|
});
|
|
59
56
|
|
|
60
57
|
const TextQuestionSchema = Type.Object({
|
|
61
58
|
type: Type.Literal("text"),
|
|
62
|
-
id: Type.String({ description: "
|
|
63
|
-
header: Type.String({ description: "Short label
|
|
64
|
-
prompt: Type.String({ description: "
|
|
59
|
+
id: Type.String({ description: "Question id" }),
|
|
60
|
+
header: Type.String({ description: "Short label" }),
|
|
61
|
+
prompt: Type.String({ description: "Question text" }),
|
|
65
62
|
required: Type.Optional(
|
|
66
63
|
Type.Boolean({
|
|
67
64
|
default: true,
|
|
68
|
-
description: "
|
|
65
|
+
description: "Required for full submit",
|
|
69
66
|
}),
|
|
70
67
|
),
|
|
71
|
-
initial: Type.Optional(Type.String({ description: "Initial
|
|
72
|
-
placeholder: Type.Optional(
|
|
73
|
-
Type.String({ description: "Placeholder shown before the user types" }),
|
|
74
|
-
),
|
|
68
|
+
initial: Type.Optional(Type.String({ description: "Initial text" })),
|
|
69
|
+
placeholder: Type.Optional(Type.String({ description: "Editor placeholder" })),
|
|
75
70
|
});
|
|
76
71
|
|
|
77
72
|
const QuestionSchema = Type.Union([ChoiceQuestionSchema, TextQuestionSchema]);
|
|
78
73
|
|
|
79
74
|
export const AskUserParamsSchema = Type.Object({
|
|
80
|
-
title: Type.Optional(
|
|
81
|
-
Type.String({ description: "Optional short title explaining the overall decision" }),
|
|
82
|
-
),
|
|
75
|
+
title: Type.Optional(Type.String({ description: "Optional title" })),
|
|
83
76
|
intro: Type.Optional(
|
|
84
77
|
Type.String({
|
|
85
|
-
description: "Optional
|
|
78
|
+
description: "Optional intro for the decision",
|
|
86
79
|
}),
|
|
87
80
|
),
|
|
88
81
|
questions: Type.Array(QuestionSchema, {
|
|
89
|
-
description: "
|
|
82
|
+
description: "1-4 focused questions for one decision",
|
|
90
83
|
}),
|
|
91
84
|
allowPartialSubmit: Type.Optional(
|
|
92
85
|
Type.Boolean({
|
|
93
|
-
description:
|
|
94
|
-
"Allow the user to submit a partial form when some required questions remain unanswered",
|
|
86
|
+
description: "Allow partial submission",
|
|
95
87
|
}),
|
|
96
88
|
),
|
|
97
89
|
allowDiscuss: Type.Optional(
|
|
98
90
|
Type.Boolean({
|
|
99
|
-
description:
|
|
100
|
-
"Allow the user to switch back into discussion instead of committing to a final answer",
|
|
91
|
+
description: "Allow discussion handoff",
|
|
101
92
|
}),
|
|
102
93
|
),
|
|
103
94
|
});
|
package/src/tool/guidance.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
// Prompt guidance and tool description for the redesigned ask_user tool.
|
|
2
2
|
|
|
3
3
|
export const toolDescription =
|
|
4
|
-
"Ask the user for a focused blocking decision
|
|
4
|
+
"Ask the user for a focused blocking decision. Use 1-4 related `choice` or `text` questions, and keep only one ask_user form active at a time.";
|
|
5
5
|
|
|
6
6
|
export const promptSnippet = "ask_user — request a focused blocking user decision";
|
|
7
7
|
|
|
8
8
|
export const promptGuidelines = [
|
|
9
|
-
"Use ask_user only
|
|
9
|
+
"Use ask_user only for blocking user input, not open-ended interviews or repo facts.",
|
|
10
10
|
"Use ask_user with 1-4 related questions; prefer one when possible.",
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"Use ask_user `allowDiscuss` or `allowPartialSubmit` only when that outcome is actionable.",
|
|
14
|
-
"Do not call ask_user while another ask_user form is already in flight.",
|
|
11
|
+
"Use ask_user `choice` for fixed options and ask_user `text` for freeform input; yes/no should be a `choice`.",
|
|
12
|
+
"Keep one ask_user form active at a time; use `allowOther` only for single-select choice and `allowDiscuss`/`allowPartialSubmit` only when actionable.",
|
|
15
13
|
];
|
package/src/ui/overlay-render.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Markdown,
|
|
6
6
|
type SelectList,
|
|
7
7
|
type SelectListTheme,
|
|
8
|
+
wrapTextWithAnsi,
|
|
8
9
|
} from "@earendil-works/pi-tui";
|
|
9
10
|
import type { AskUserController } from "../session/controller.ts";
|
|
10
11
|
import type { NormalizedQuestionnaire } from "../types.ts";
|
|
@@ -100,11 +101,15 @@ export function clampIndex(index: number, length: number): number {
|
|
|
100
101
|
function renderHeader(args: RenderOverlayFrameArgs): string[] {
|
|
101
102
|
const lines: string[] = [];
|
|
102
103
|
const { title, intro } = args.controller.questionnaire;
|
|
103
|
-
if (title)
|
|
104
|
+
if (title)
|
|
105
|
+
lines.push(...wrapTextWithAnsi(args.theme.fg("accent", args.theme.bold(title)), args.width));
|
|
104
106
|
lines.push(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
...wrapTextWithAnsi(
|
|
108
|
+
args.theme.fg(
|
|
109
|
+
"muted",
|
|
110
|
+
`${args.controller.currentIndex + 1}/${args.controller.questions.length} · ${args.controller.currentQuestion.header}`,
|
|
111
|
+
),
|
|
112
|
+
args.width,
|
|
108
113
|
),
|
|
109
114
|
);
|
|
110
115
|
if (intro) {
|
|
@@ -197,14 +202,17 @@ function renderEditorLines(args: RenderOverlayFrameArgs, width: number): string[
|
|
|
197
202
|
: "Option note"
|
|
198
203
|
: "Your answer";
|
|
199
204
|
|
|
200
|
-
const
|
|
205
|
+
const labelLines = wrapTextWithAnsi(args.theme.fg("accent", label), width);
|
|
206
|
+
const lines = [...labelLines, ...args.editor.render(Math.max(20, width - 1))];
|
|
201
207
|
const question = args.controller.currentQuestion;
|
|
202
208
|
if (question.type !== "text" || args.editor.getText()) return lines;
|
|
203
209
|
|
|
204
210
|
if (question.initial) {
|
|
205
|
-
lines.push(args.theme.fg("dim", `Initial: ${question.initial}`));
|
|
211
|
+
lines.push(...wrapTextWithAnsi(args.theme.fg("dim", `Initial: ${question.initial}`), width));
|
|
206
212
|
} else if (question.placeholder) {
|
|
207
|
-
lines.push(
|
|
213
|
+
lines.push(
|
|
214
|
+
...wrapTextWithAnsi(args.theme.fg("dim", `Placeholder: ${question.placeholder}`), width),
|
|
215
|
+
);
|
|
208
216
|
}
|
|
209
217
|
return lines;
|
|
210
218
|
}
|
package/src/ui/overlay-view.ts
CHANGED
|
@@ -177,7 +177,7 @@ function renderOptionRow(args: {
|
|
|
177
177
|
: `${prefix}${labelText}`;
|
|
178
178
|
const noteSuffix = hasNote ? ` ${theme.fg("accent", "[note]")}` : "";
|
|
179
179
|
|
|
180
|
-
const lines: string[] =
|
|
180
|
+
const lines: string[] = wrapTextWithAnsi(`${baseText}${noteSuffix}`, width);
|
|
181
181
|
|
|
182
182
|
if (option.description) {
|
|
183
183
|
const descWidth = Math.max(10, width - 2);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { registerSettingsCommand as default } from "./settings/settings-command.ts";
|