@hachej/boring-workspace 0.1.13 → 0.1.14
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 +270 -42
- package/dist/CommandPalette-NOEOVkN2.js +5714 -0
- package/dist/{FileTree-BVfqs3rR.js → FileTree-Dl-qUAB0.js} +9 -9
- package/dist/MarkdownEditor-yc6mFsnI.js +533 -0
- package/dist/{WorkspaceLoadingState-BjZGQLS_.js → WorkspaceLoadingState-CSZfENWe.js} +145 -124
- package/dist/agent-tool-DEtfQPVB.d.ts +100 -0
- package/dist/app-front.d.ts +79 -67
- package/dist/app-front.js +253 -241
- package/dist/app-server.d.ts +17 -12
- package/dist/app-server.js +80 -10
- package/dist/{bootstrapServer-BRUqUpVW.d.ts → bootstrapServer-BreQ9QBc.d.ts} +8 -2
- package/dist/server.d.ts +10 -32
- package/dist/server.js +22 -127
- package/dist/shared.d.ts +1 -2
- package/dist/testing.d.ts +0 -63
- package/dist/testing.js +2248 -2401
- package/dist/workspace.css +1616 -974
- package/dist/workspace.d.ts +111 -450
- package/dist/workspace.js +417 -1635
- package/docs/INTERFACES.md +2 -2
- package/docs/PLUGIN_STRUCTURE.md +1 -1
- package/docs/plans/ASK_USER_QUESTIONS_PLUGIN_SPEC.md +131 -263
- package/docs/plans/GENERIC_EXPLORER_PLUGIN_PLAN.md +29 -27
- package/docs/plans/MACRO_PLUGIN_GENERIC_HELPERS_AUDIT.md +12 -12
- package/docs/plans/PANE_TO_AGENT_CHAT_ACTIONS_SPEC.md +366 -0
- package/docs/plans/README.md +2 -0
- package/docs/plans/archive/PLUGIN_MODEL.md +14 -14
- package/docs/plans/archive/SRC_FOLDER_REORG_PLAN.md +2 -3
- package/docs/plans/archive/WORKSPACE_V2_PLAN.md +1 -1
- package/package.json +3 -6
- package/dist/CommandPalette-Dme9em28.js +0 -5506
- package/dist/MarkdownEditor-CcCDF65H.js +0 -502
- package/dist/agent-tool-NvxKfist.d.ts +0 -28
- package/dist/explorer-DtLUnuah.d.ts +0 -129
package/docs/INTERFACES.md
CHANGED
|
@@ -35,8 +35,8 @@ commands, and default workspace plugins.
|
|
|
35
35
|
- Filesystem data: `src/plugins/filesystemPlugin/front/data`
|
|
36
36
|
- Filesystem client, hooks, event stream, and cache invalidation are plugin
|
|
37
37
|
owned.
|
|
38
|
-
- Data catalog:
|
|
39
|
-
|
|
38
|
+
- Data catalog package: `@hachej/boring-data-catalog/front` and
|
|
39
|
+
`@hachej/boring-data-catalog/server`
|
|
40
40
|
- Catalog rows are opened through `openSurface`; row-to-panel mapping belongs
|
|
41
41
|
to the plugin resolver.
|
|
42
42
|
- Server plugins: `src/server/plugins`
|
package/docs/PLUGIN_STRUCTURE.md
CHANGED
|
@@ -133,7 +133,7 @@ slash commands.
|
|
|
133
133
|
## Current Plugins
|
|
134
134
|
|
|
135
135
|
- `packages/workspace/src/plugins/filesystemPlugin`
|
|
136
|
-
- `
|
|
136
|
+
- Data catalog package: `@hachej/boring-data-catalog` (`plugins/data-catalog/src`)
|
|
137
137
|
- `apps/workspace-playground/src/plugins/playgroundDataCatalog`
|
|
138
138
|
- Macro plugin example: `hachej/boring-macro` (`src/plugins/macro`)
|
|
139
139
|
|
|
@@ -1,322 +1,190 @@
|
|
|
1
1
|
# Ask User Questions Plugin Spec
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Summary
|
|
6
|
-
|
|
7
|
-
Add a blocking `ask_user` capability for agent sessions that opens a Workspace
|
|
8
|
-
page named **Questions**, renders an agent-generated form, lets the user submit
|
|
9
|
-
answers, and returns those answers to the waiting agent tool call.
|
|
10
|
-
|
|
11
|
-
The Workspace implementation owns the page/plugin UI, form primitives, and UI
|
|
12
|
-
bridge command handling. The Agent implementation owns the blocking tool runtime
|
|
13
|
-
and session-level waiter. The browser must submit answers through the Workspace
|
|
14
|
-
UI bridge command path, not through ad-hoc form POST semantics.
|
|
15
|
-
|
|
16
|
-
## Goals
|
|
17
|
-
|
|
18
|
-
- Provide an agent tool that asks the user for structured input and blocks until
|
|
19
|
-
the user answers or cancels.
|
|
20
|
-
- Open or focus a Workspace page/panel named `Questions` whenever a question is
|
|
21
|
-
pending.
|
|
22
|
-
- Render forms from a portable, JSON-serializable schema generated by the agent.
|
|
23
|
-
- Provide primitive React UI components and hooks so app shells can render these
|
|
24
|
-
forms in a standard way.
|
|
25
|
-
- Persist the single pending question per agent session across browser reloads.
|
|
26
|
-
- Send submitted answers back to the waiting agent through `UiBridge.postCommand`
|
|
27
|
-
as the single user-dispatch source.
|
|
28
|
-
- Keep Workspace base front/shared code package-neutral; no value imports from
|
|
29
|
-
`@boring/agent` outside allowed app composition boundaries.
|
|
3
|
+
Status: implemented in `plugins/askUserPlugin`.
|
|
30
4
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
- Multiple simultaneous pending questions per agent session.
|
|
34
|
-
- File upload fields in the first version.
|
|
35
|
-
- Full process-crash restoration of an already-blocked in-memory tool call,
|
|
36
|
-
unless the current agent session runtime already supports rehydrating waiters.
|
|
37
|
-
- Using chat-stream `data-ui-command` parts as the source of truth for answers.
|
|
38
|
-
- Making `pi-ask-user` the Workspace UX implementation dependency.
|
|
39
|
-
|
|
40
|
-
## User flow
|
|
41
|
-
|
|
42
|
-
1. Agent calls `ask_user` with title, optional context, and form schema.
|
|
43
|
-
2. Server creates a pending question record for the current agent session.
|
|
44
|
-
3. Agent tool blocks on an `AskUserCoordinator` waiter.
|
|
45
|
-
4. Workspace receives/loads the pending question and opens or focuses the
|
|
46
|
-
`Questions` page.
|
|
47
|
-
5. User fills the form and clicks Submit.
|
|
48
|
-
6. Questions page calls `uiBridge.postCommand({ type: "questions.submit", ... })`.
|
|
49
|
-
7. Workspace bridge server handler validates the command and records the answer.
|
|
50
|
-
8. `AskUserCoordinator` resolves the waiter.
|
|
51
|
-
9. Tool returns the structured answer to the agent and the agent continues.
|
|
52
|
-
|
|
53
|
-
Cancel follows the same path with `type: "questions.cancel"` and returns a
|
|
54
|
-
stable cancelled result to the tool caller.
|
|
5
|
+
## Goal
|
|
55
6
|
|
|
56
|
-
|
|
7
|
+
Provide a Workspace-owned `ask_user` agent tool that asks the user a blocking,
|
|
8
|
+
structured question in a **Questions** workbench pane and returns the browser
|
|
9
|
+
answer to the waiting agent tool call.
|
|
57
10
|
|
|
58
|
-
|
|
11
|
+
The ask-user domain stays inside the plugin:
|
|
59
12
|
|
|
60
|
-
|
|
13
|
+
- shared constants, types, schemas, and error codes
|
|
14
|
+
- server runtime, store, routes, state publisher, and tool wrapper
|
|
15
|
+
- front provider, Questions pane, client, form primitives, and surface resolver
|
|
61
16
|
|
|
62
|
-
|
|
63
|
-
- `AskUserFormSchema`
|
|
64
|
-
- `AskUserField`
|
|
65
|
-
- `AskUserAnswer`
|
|
66
|
-
- `QuestionsSubmitCommand`
|
|
67
|
-
- `QuestionsCancelCommand`
|
|
68
|
-
- stable error codes imported from the canonical error-code enum
|
|
17
|
+
Generic Workspace and Agent layers know only generic concepts:
|
|
69
18
|
|
|
70
|
-
|
|
19
|
+
- Workspace attention blockers
|
|
20
|
+
- generic blocker labels/actions
|
|
21
|
+
- generic `openSurface` dispatch from Workspace chrome
|
|
22
|
+
- generic tool execution context with the active agent `sessionId`
|
|
71
23
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
New default Workspace plugin that owns:
|
|
75
|
-
|
|
76
|
-
- `front/QuestionsPage.tsx`
|
|
77
|
-
- `front/QuestionsPanel.tsx`
|
|
78
|
-
- `front/usePendingQuestion.ts`
|
|
79
|
-
- `front/primitives/QuestionForm.tsx`
|
|
80
|
-
- `front/primitives/QuestionField.tsx`
|
|
81
|
-
- field primitive components
|
|
82
|
-
- `server/questionsBridge.ts`
|
|
83
|
-
- `shared/types.ts`
|
|
84
|
-
|
|
85
|
-
Plugin outputs should include at minimum:
|
|
24
|
+
## Non-goals
|
|
86
25
|
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
26
|
+
- No progressive/draft form streaming in this PR.
|
|
27
|
+
- No JSON-Schema `properties` compatibility layer.
|
|
28
|
+
- No heuristic A/B fallback when schema is omitted.
|
|
29
|
+
- No chat-inline form UI; chat only shows generic blocker/status affordances.
|
|
30
|
+
- No ask-user-specific strings or events in `@hachej/boring-agent`.
|
|
91
31
|
|
|
92
|
-
|
|
32
|
+
Agents must provide the final form schema up front.
|
|
93
33
|
|
|
94
|
-
|
|
95
|
-
registration APIs. This is the allowed boundary for Workspace + Agent product
|
|
96
|
-
composition.
|
|
34
|
+
## Tool contract
|
|
97
35
|
|
|
98
|
-
|
|
36
|
+
Tool name: `ask_user`
|
|
99
37
|
|
|
100
|
-
|
|
101
|
-
interface that Workspace can satisfy:
|
|
38
|
+
Input:
|
|
102
39
|
|
|
103
40
|
```ts
|
|
104
|
-
|
|
105
|
-
|
|
41
|
+
type AskUserToolInput = {
|
|
42
|
+
title: string
|
|
43
|
+
context?: string
|
|
44
|
+
schema: AskUserFormSchema
|
|
45
|
+
timeoutMs?: number
|
|
106
46
|
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Workspace app/server composition injects a runtime that stores the pending
|
|
110
|
-
question and resolves through UI bridge answers.
|
|
111
|
-
|
|
112
|
-
## Form schema
|
|
113
47
|
|
|
114
|
-
Use a small JSON-schema-lite contract. It is serializable, easy to render in
|
|
115
|
-
React, and avoids forcing Zod or another runtime validator across the shared
|
|
116
|
-
browser/server boundary. A later helper may compile from Zod or JSON Schema into
|
|
117
|
-
this format.
|
|
118
|
-
|
|
119
|
-
```ts
|
|
120
48
|
type AskUserFormSchema = {
|
|
49
|
+
wireVersion: 1
|
|
121
50
|
fields: AskUserField[]
|
|
122
51
|
submitLabel?: string
|
|
123
52
|
}
|
|
124
|
-
|
|
125
|
-
type AskUserField =
|
|
126
|
-
| {
|
|
127
|
-
type: "text"
|
|
128
|
-
name: string
|
|
129
|
-
label: string
|
|
130
|
-
required?: boolean
|
|
131
|
-
placeholder?: string
|
|
132
|
-
defaultValue?: string
|
|
133
|
-
helpText?: string
|
|
134
|
-
}
|
|
135
|
-
| {
|
|
136
|
-
type: "textarea"
|
|
137
|
-
name: string
|
|
138
|
-
label: string
|
|
139
|
-
required?: boolean
|
|
140
|
-
placeholder?: string
|
|
141
|
-
defaultValue?: string
|
|
142
|
-
helpText?: string
|
|
143
|
-
}
|
|
144
|
-
| {
|
|
145
|
-
type: "select"
|
|
146
|
-
name: string
|
|
147
|
-
label: string
|
|
148
|
-
required?: boolean
|
|
149
|
-
options: AskUserOption[]
|
|
150
|
-
defaultValue?: string
|
|
151
|
-
helpText?: string
|
|
152
|
-
}
|
|
153
|
-
| {
|
|
154
|
-
type: "multiselect"
|
|
155
|
-
name: string
|
|
156
|
-
label: string
|
|
157
|
-
required?: boolean
|
|
158
|
-
options: AskUserOption[]
|
|
159
|
-
defaultValue?: string[]
|
|
160
|
-
helpText?: string
|
|
161
|
-
}
|
|
162
|
-
| {
|
|
163
|
-
type: "checkbox"
|
|
164
|
-
name: string
|
|
165
|
-
label: string
|
|
166
|
-
defaultValue?: boolean
|
|
167
|
-
helpText?: string
|
|
168
|
-
}
|
|
169
|
-
| {
|
|
170
|
-
type: "radio"
|
|
171
|
-
name: string
|
|
172
|
-
label: string
|
|
173
|
-
required?: boolean
|
|
174
|
-
options: AskUserOption[]
|
|
175
|
-
defaultValue?: string
|
|
176
|
-
helpText?: string
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
type AskUserOption = {
|
|
180
|
-
value: string
|
|
181
|
-
label: string
|
|
182
|
-
description?: string
|
|
183
|
-
}
|
|
184
53
|
```
|
|
185
54
|
|
|
186
|
-
|
|
55
|
+
Supported field types:
|
|
187
56
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
57
|
+
- `text`
|
|
58
|
+
- `textarea`
|
|
59
|
+
- `select`
|
|
60
|
+
- `radio`
|
|
61
|
+
- `multiselect`
|
|
62
|
+
- `checkbox`
|
|
63
|
+
- `number`
|
|
64
|
+
|
|
65
|
+
The tool prompt explicitly instructs the model to emit this schema shape and not
|
|
66
|
+
JSON Schema `properties`.
|
|
196
67
|
|
|
197
|
-
|
|
68
|
+
Output:
|
|
198
69
|
|
|
199
70
|
```ts
|
|
200
71
|
type AskUserToolResult =
|
|
201
72
|
| { status: "answered"; answer: AskUserAnswer }
|
|
202
|
-
| { status: "cancelled"; questionId: string; sessionId: string }
|
|
73
|
+
| { status: "cancelled"; questionId: string; sessionId: string; reason: AskUserCancelReason }
|
|
203
74
|
```
|
|
204
75
|
|
|
205
|
-
|
|
76
|
+
Tool errors are returned as normal tool errors when input validation fails,
|
|
77
|
+
runtime limits reject the request, timeout/abort occurs, or the user cancels.
|
|
206
78
|
|
|
207
|
-
|
|
208
|
-
question for a session that already has one should fail with a stable error code
|
|
209
|
-
or replace only if an explicit future `replacePending` option is added.
|
|
79
|
+
## Runtime flow
|
|
210
80
|
|
|
211
|
-
|
|
81
|
+
1. Agent calls `ask_user` with complete schema.
|
|
82
|
+
2. Tool execution context provides active chat/session id when available.
|
|
83
|
+
3. `AskUserRuntime.ask()` validates schema and creates one ready pending question.
|
|
84
|
+
4. Store persists the question and transcript events.
|
|
85
|
+
5. State publisher writes `questions.pending` into Workspace UI state.
|
|
86
|
+
6. Runtime best-effort posts `openSurface { kind: "questions" }`.
|
|
87
|
+
7. Questions pane renders the form from command metadata or persisted UI state.
|
|
88
|
+
8. User submits/cancels through `/api/v1/questions/commands`.
|
|
89
|
+
9. Server validates session/principal/token/schema and resolves the in-process waiter.
|
|
90
|
+
10. Agent receives answered/cancelled result.
|
|
212
91
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
getPending(sessionId: string): Promise<AskUserQuestion | null>
|
|
216
|
-
createPending(question: AskUserQuestion): Promise<void>
|
|
217
|
-
answer(questionId: string, answer: AskUserAnswer): Promise<void>
|
|
218
|
-
cancel(questionId: string): Promise<void>
|
|
219
|
-
clearPending(sessionId: string): Promise<void>
|
|
220
|
-
}
|
|
221
|
-
```
|
|
92
|
+
Missed UI open acks or failed `openSurface` dispatch do not cancel the pending
|
|
93
|
+
question. The persisted state lets browser refresh/reconnect recover.
|
|
222
94
|
|
|
223
|
-
|
|
224
|
-
adapter. Core/cloud can later inject a DB-backed implementation.
|
|
95
|
+
## Store contract
|
|
225
96
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
agent session runtime.
|
|
97
|
+
`AskUserStore` owns persisted pending questions, answers, and transcript events.
|
|
98
|
+
The file-backed default store is suitable for standalone/dev use and can be
|
|
99
|
+
replaced by app/core/cloud storage later.
|
|
230
100
|
|
|
231
|
-
|
|
101
|
+
Important invariants:
|
|
232
102
|
|
|
233
|
-
|
|
103
|
+
- one pending ready question per session
|
|
104
|
+
- terminal states are guarded (`answered`, `cancelled`, `abandoned`)
|
|
105
|
+
- writes are serialized
|
|
106
|
+
- listener failures do not roll back mutations
|
|
107
|
+
- transcript events never contain browser-supplied schema
|
|
234
108
|
|
|
235
|
-
|
|
236
|
-
uiBridge.postCommand({
|
|
237
|
-
type: "questions.submit",
|
|
238
|
-
questionId,
|
|
239
|
-
sessionId,
|
|
240
|
-
values,
|
|
241
|
-
})
|
|
242
|
-
```
|
|
109
|
+
## Browser command security
|
|
243
110
|
|
|
244
|
-
|
|
111
|
+
Browser commands include the question id, session id, and answer token. The
|
|
112
|
+
bridge validates:
|
|
245
113
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
```
|
|
114
|
+
- command payload shape
|
|
115
|
+
- stored question exists
|
|
116
|
+
- session id matches
|
|
117
|
+
- auth context/principal matches when configured
|
|
118
|
+
- answer token matches using constant-time comparison
|
|
119
|
+
- answer values match the server-stored schema
|
|
253
120
|
|
|
254
|
-
|
|
121
|
+
Duplicate submit after answered is idempotent. Submit after cancel is rejected.
|
|
122
|
+
If the runtime waiter is gone, submit abandons and returns conflict instead of
|
|
123
|
+
falsely reporting answered.
|
|
255
124
|
|
|
256
|
-
|
|
257
|
-
- validate submitted values against the form schema
|
|
258
|
-
- persist answer/cancel state
|
|
259
|
-
- resolve the matching `AskUserCoordinator` waiter
|
|
260
|
-
- emit/update Workspace state so the Questions page leaves pending mode
|
|
125
|
+
## UI state and recovery
|
|
261
126
|
|
|
262
|
-
|
|
263
|
-
|
|
127
|
+
The plugin owns `ASK_USER_UI_STATE_SLOTS.PENDING` (`questions.pending`). Server
|
|
128
|
+
plugins declare preserved UI state keys so generic Workspace routes do not import
|
|
129
|
+
ask-user constants.
|
|
264
130
|
|
|
265
|
-
|
|
131
|
+
Pending state shape:
|
|
266
132
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
133
|
+
```ts
|
|
134
|
+
type AskUserPendingState = {
|
|
135
|
+
question: AskUserQuestion | null
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The front provider refreshes pending state on mount, window focus, visibility
|
|
140
|
+
restore, and UI-command events. It does not poll continuously.
|
|
141
|
+
|
|
142
|
+
## Composer blocking
|
|
274
143
|
|
|
275
|
-
|
|
144
|
+
Pending ready questions add a `WorkspaceAttentionBlocker` with generic actions:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
{
|
|
148
|
+
reason: "waiting_for_user_input",
|
|
149
|
+
label: "Answer the question in Questions to continue",
|
|
150
|
+
actions: [{ id: "open", label: "Open Questions" }]
|
|
151
|
+
}
|
|
152
|
+
```
|
|
276
153
|
|
|
277
|
-
|
|
278
|
-
|
|
154
|
+
`@hachej/boring-agent` receives only generic blocker shape/actions. Workspace
|
|
155
|
+
chrome handles action ids against its richer workspace blocker metadata.
|
|
279
156
|
|
|
280
|
-
|
|
281
|
-
- `<QuestionField field value onChange error />`
|
|
282
|
-
- `<QuestionSubmitButton />`
|
|
283
|
-
- `<QuestionCancelButton />`
|
|
284
|
-
- `useQuestionForm(schema, initialValues?)`
|
|
285
|
-
- `validateQuestionValues(schema, values)`
|
|
157
|
+
Policy:
|
|
286
158
|
|
|
287
|
-
|
|
288
|
-
|
|
159
|
+
- normal busy chat blocks send unless native follow-up is supported
|
|
160
|
+
- pending ask-user always blocks composer, even with native follow-up support
|
|
161
|
+
- Stop remains clickable while blocked
|
|
162
|
+
- Stop cancels the pending question for that session and closes Questions pane
|
|
289
163
|
|
|
290
|
-
##
|
|
164
|
+
## App wiring
|
|
291
165
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
skill. It is good prior art and may be useful as a standalone CLI fallback.
|
|
166
|
+
The ask-user plugin is not hard-wired into `createWorkspaceAgentServer()` or
|
|
167
|
+
`WorkspaceAgentFront()`. Host apps install both halves explicitly:
|
|
295
168
|
|
|
296
|
-
|
|
169
|
+
- front: pass `askUserPlugin` through the workspace `plugins` prop
|
|
170
|
+
- server: pass a plugin factory that creates `createAskUserPluginBundle({ workspaceRoot, bridge })`
|
|
297
171
|
|
|
298
|
-
-
|
|
299
|
-
- generated rich React form rendering
|
|
300
|
-
- Workspace persistence semantics
|
|
301
|
-
- answer dispatch through `UiBridge.postCommand`
|
|
302
|
-
- app-shell primitive components
|
|
172
|
+
Ask-user server plugin contributes:
|
|
303
173
|
|
|
304
|
-
|
|
174
|
+
- `ask_user` agent tool
|
|
175
|
+
- Questions routes
|
|
176
|
+
- system prompt snippet
|
|
177
|
+
- preserved UI state key
|
|
305
178
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
- Keep Workspace Questions plugin implementation first-party.
|
|
179
|
+
The state publisher is started only when the host app installs the server plugin
|
|
180
|
+
and is disposed on Fastify close.
|
|
309
181
|
|
|
310
|
-
##
|
|
182
|
+
## Tests to keep
|
|
311
183
|
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
-
|
|
315
|
-
-
|
|
316
|
-
-
|
|
317
|
-
-
|
|
318
|
-
-
|
|
319
|
-
- Cancel resolves the tool call with `status: "cancelled"`.
|
|
320
|
-
- Primitive form components/hooks are exported for app-shell reuse.
|
|
321
|
-
- Unit tests cover schema validation and one-pending-question enforcement.
|
|
322
|
-
- Integration test or harness test covers ask -> render -> submit -> tool result.
|
|
184
|
+
- schema validation limits and command payloads
|
|
185
|
+
- store persistence and terminal guards
|
|
186
|
+
- runtime answer/cancel/timeout/abort/orphan behavior
|
|
187
|
+
- bridge auth/session/token/answer validation
|
|
188
|
+
- front Questions pane submit/cancel/stop behavior
|
|
189
|
+
- generic ChatPanelHost blocker action behavior
|
|
190
|
+
- host app front/server plugin installation symmetry
|
|
@@ -7,9 +7,9 @@ Status: draft plan. No code has moved yet.
|
|
|
7
7
|
## Problem
|
|
8
8
|
|
|
9
9
|
Workspace currently has a good generic `DataExplorer` primitive under
|
|
10
|
-
|
|
10
|
+
`@hachej/boring-data-explorer/front`. The data-catalog-specific legacy wrappers
|
|
11
11
|
under `src/front/components/data-catalog` have been removed; data catalog behavior
|
|
12
|
-
now lives only in `
|
|
12
|
+
now lives only in the `@hachej/boring-data-catalog` package. Feret v2 shows the next requirement: not
|
|
13
13
|
just flat/faceted database rows, but mixed project trees with
|
|
14
14
|
filesystem rows, virtual DB rows, section filters, friendly labels, and domain
|
|
15
15
|
open routing.
|
|
@@ -28,7 +28,7 @@ We need a cleaner ownership model:
|
|
|
28
28
|
Create a dedicated generic explorer plugin/family:
|
|
29
29
|
|
|
30
30
|
```txt
|
|
31
|
-
|
|
31
|
+
plugins/data-explorer/src/
|
|
32
32
|
index.tsx
|
|
33
33
|
constants.ts
|
|
34
34
|
types.ts
|
|
@@ -47,13 +47,13 @@ emit panes/outputs and own a feature contract, but they do not encode an app
|
|
|
47
47
|
domain like files, data catalog, or Feret. Domain plugins compose it:
|
|
48
48
|
|
|
49
49
|
```txt
|
|
50
|
-
|
|
51
|
-
filesystemPlugin -> may use
|
|
52
|
-
Feret app plugin -> uses
|
|
53
|
-
future domain plugin -> uses
|
|
50
|
+
data catalog package -> uses data explorer package for generic explorer rendering
|
|
51
|
+
filesystemPlugin -> may use data explorer package for project/friendly trees later
|
|
52
|
+
Feret app plugin -> uses data explorer package directly for Project Tree and Data/Feret
|
|
53
|
+
future domain plugin -> uses data explorer package for symbols/docs/jobs/issues/etc.
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
Do **not** put generic explorer under `
|
|
56
|
+
Do **not** put generic explorer under the `@hachej/boring-data-catalog` package. That would make other
|
|
57
57
|
domains depend on a data-catalog name and blur ownership.
|
|
58
58
|
|
|
59
59
|
## Target Package Shape
|
|
@@ -83,9 +83,11 @@ src/front/
|
|
|
83
83
|
toast/
|
|
84
84
|
|
|
85
85
|
src/plugins/
|
|
86
|
-
explorerPlugin/ # generic explorer feature family
|
|
87
|
-
dataCatalogPlugin/ # data catalog specialization
|
|
88
86
|
filesystemPlugin/ # files/editors/tree specialization
|
|
87
|
+
|
|
88
|
+
root plugins/
|
|
89
|
+
data-explorer/ # @hachej/boring-data-explorer
|
|
90
|
+
data-catalog/ # @hachej/boring-data-catalog
|
|
89
91
|
```
|
|
90
92
|
|
|
91
93
|
## Explorer Plugin API Shape
|
|
@@ -282,10 +284,10 @@ Implementation must validate adapter/mode combinations at runtime too:
|
|
|
282
284
|
|
|
283
285
|
## Data Catalog After Refactor
|
|
284
286
|
|
|
285
|
-
`
|
|
287
|
+
the `@hachej/boring-data-catalog` package becomes a specialization that composes explorer outputs:
|
|
286
288
|
|
|
287
289
|
```txt
|
|
288
|
-
|
|
290
|
+
@hachej/boring-data-catalog/
|
|
289
291
|
index.tsx # createDataCatalogPlugin, appendDataCatalogOutputs
|
|
290
292
|
constants.ts
|
|
291
293
|
types.ts
|
|
@@ -312,7 +314,7 @@ Non-responsibilities:
|
|
|
312
314
|
|
|
313
315
|
Legacy `src/front/components/data-catalog` is removed. Consumers should use
|
|
314
316
|
`createDataCatalogPlugin()` / `appendDataCatalogOutputs()` or compose
|
|
315
|
-
`DataExplorer` directly until it moves to `
|
|
317
|
+
`DataExplorer` directly until it moves to the `@hachej/boring-data-explorer` package.
|
|
316
318
|
|
|
317
319
|
## Feret v2 Requirements Driving Explorer Plugin
|
|
318
320
|
|
|
@@ -356,7 +358,7 @@ filters.
|
|
|
356
358
|
|
|
357
359
|
| Current location | Decision | Rationale |
|
|
358
360
|
| --------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
359
|
-
|
|
|
361
|
+
| `@hachej/boring-data-explorer/front` | Extracted to `plugins/data-explorer/src/front/*` | Generic feature family, but pane-capable and adapter-owned; multiple plugins depend on it. |
|
|
360
362
|
| `front/components/data-catalog/*` | Removed | Data-catalog naming is domain-ish; real data catalog behavior is plugin-owned already. |
|
|
361
363
|
| `front/components/CommandPalette.tsx` | Keep in `front/components` | Generic workspace chrome over command/catalog registries, not a domain plugin. |
|
|
362
364
|
| `front/components/recent/*` | Keep in `front/components` for now | Generic command/catalog recent state used by CommandPalette. Could become `commandPalette` subfolder later. |
|
|
@@ -374,39 +376,39 @@ filters.
|
|
|
374
376
|
| `plugins/filesystemPlugin/front/code-editor/*` | Keep in filesystem plugin | File editor domain and file data hooks. |
|
|
375
377
|
| `plugins/filesystemPlugin/front/markdown-editor/*` | Keep in filesystem plugin | File editor domain and file data hooks. |
|
|
376
378
|
| `plugins/filesystemPlugin/front/empty-file-panel/*` | Keep in filesystem plugin | File-specific empty panel. |
|
|
377
|
-
|
|
|
379
|
+
| `@hachej/boring-data-catalog/front` | Extracted to `plugins/data-catalog/src/front/*`; imports explorer from `@hachej/boring-data-explorer` | Domain specialization. |
|
|
378
380
|
|
|
379
381
|
## Public API Migration
|
|
380
382
|
|
|
381
383
|
Avoid breaking current consumers in the first pass.
|
|
382
384
|
|
|
383
|
-
1. Add `plugins/
|
|
385
|
+
1. Add `plugins/data-explorer` and re-export explorer APIs from old package
|
|
384
386
|
root names:
|
|
385
387
|
- `DataExplorer` stays exported, but source moves.
|
|
386
388
|
- `ExplorerRow`, `ExplorerAdapter`, `FacetConfig`, etc. stay exported with
|
|
387
389
|
compatibility aliases.
|
|
388
|
-
2. Keep
|
|
389
|
-
|
|
390
|
+
2. Keep any workspace compatibility re-export thin and temporary if internal
|
|
391
|
+
import churn requires it; the canonical API is `@hachej/boring-data-explorer/front`.
|
|
390
392
|
3. `DataCatalog` and `DataCatalogPane` root exports are removed now; use data catalog plugin helpers instead.
|
|
391
|
-
4. Move app/plugin imports to `plugins/
|
|
393
|
+
4. Move app/plugin imports to `plugins/data-explorer` or package-root exports.
|
|
392
394
|
|
|
393
395
|
## Implementation Beads
|
|
394
396
|
|
|
395
397
|
### Bead 1 — Explorer plugin skeleton
|
|
396
398
|
|
|
397
|
-
- Add `
|
|
399
|
+
- Add `plugins/data-explorer/src` with current `DataExplorer` code moved mostly
|
|
398
400
|
intact.
|
|
399
401
|
- Export compatibility aliases.
|
|
400
|
-
- Update internal imports from
|
|
401
|
-
`plugins/
|
|
402
|
+
- Update internal imports from `@hachej/boring-data-explorer/front` to
|
|
403
|
+
`plugins/data-explorer`.
|
|
402
404
|
- Tests: current DataExplorer tests pass unchanged after path update.
|
|
403
405
|
|
|
404
406
|
### Bead 2 — Data catalog plugin composition
|
|
405
407
|
|
|
406
|
-
- Change `
|
|
408
|
+
- Change the `@hachej/boring-data-catalog` package to import explorer APIs from `@hachej/boring-data-explorer`.
|
|
407
409
|
- Split data catalog helpers into `catalogs.ts` if useful.
|
|
408
410
|
- Keep `front/components/data-catalog` removed; do not add compatibility wrappers back.
|
|
409
|
-
- Tests:
|
|
411
|
+
- Tests: data catalog package tests and public API tests.
|
|
410
412
|
|
|
411
413
|
### Bead 3 — Tree adapter design
|
|
412
414
|
|
|
@@ -441,9 +443,9 @@ filesystem tree to explorer tree` before the legacy data-catalog removal bead.
|
|
|
441
443
|
- Do not force filesystem to depend on data catalog.
|
|
442
444
|
- Do not rewrite file tree in the first bead.
|
|
443
445
|
- Do not remove public exports without an explicit breaking cleanup bead.
|
|
444
|
-
- Do not allow reverse imports from `
|
|
445
|
-
extend invariant lint so allowed direction is domain plugin ->
|
|
446
|
-
never
|
|
446
|
+
- Do not allow reverse imports from `@hachej/boring-data-explorer` into domain plugins. Add or
|
|
447
|
+
extend invariant lint so allowed direction is domain plugin -> data explorer package,
|
|
448
|
+
never data explorer package -> data catalog package, filesystemPlugin, or app plugins.
|
|
447
449
|
|
|
448
450
|
## Acceptance Criteria
|
|
449
451
|
|