@vitos-pizza/vitos-pizza 0.3.1 → 0.4.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.
Files changed (37) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +42 -11
  3. package/README.md +31 -4
  4. package/assets/architecture.png +0 -0
  5. package/assets/architecture.svg +97 -0
  6. package/package.json +22 -12
  7. package/packages/agent-mode/package.json +3 -3
  8. package/packages/agent-mode/src/plan-instructions.ts +19 -7
  9. package/packages/hypa/extensions/index.ts +16 -0
  10. package/packages/hypa/package.json +23 -0
  11. package/packages/hypa/scripts/smoke.mjs +50 -0
  12. package/packages/hypa/src/config.ts +37 -0
  13. package/packages/hypa/src/seed.ts +22 -0
  14. package/packages/hypa/tsconfig.json +13 -0
  15. package/packages/keybindings/package.json +1 -1
  16. package/packages/permission-system/package.json +2 -2
  17. package/packages/permission-system/presets/default.json +8 -0
  18. package/packages/permission-system/presets/plan.json +6 -0
  19. package/packages/permission-system/presets/yolo.json +1 -0
  20. package/packages/question/extensions/index.ts +54 -21
  21. package/packages/question/package.json +1 -1
  22. package/packages/question/src/forwarding/file-watcher.ts +41 -11
  23. package/packages/question/src/forwarding/forwarder.ts +61 -27
  24. package/packages/question/src/question-ui.ts +773 -78
  25. package/packages/question/src/register-tool.ts +351 -40
  26. package/packages/question/src/types.ts +79 -7
  27. package/packages/session-title/package.json +3 -3
  28. package/packages/settings-preset/package.json +1 -1
  29. package/packages/subagents/agents/planner.md +3 -2
  30. package/packages/subagents/agents/scout.md +2 -1
  31. package/packages/subagents/agents/worker.md +3 -2
  32. package/packages/subagents/package.json +1 -1
  33. package/packages/todoist/package.json +1 -1
  34. package/packages/ui-enhancements/package.json +1 -1
  35. package/packages/ui-enhancements/src/chrome/resize-recovery.ts +71 -14
  36. package/packages/websearch/package.json +1 -1
  37. package/scripts/sync-pi-manifest.mjs +18 -12
@@ -7,8 +7,25 @@ import { Text } from "@earendil-works/pi-tui";
7
7
  import { Type } from "typebox";
8
8
  import { forwardQuestionPrompt } from "./forwarding/forwarder.ts";
9
9
  import { isSubagentChild, resolveParentSessionId } from "./parent-session.ts";
10
- import { runQuestionUi } from "./question-ui.ts";
11
- import type { QuestionDetails, QuestionParams } from "./types.ts";
10
+ import { runMultiQuestionUi, runQuestionUi } from "./question-ui.ts";
11
+ import type {
12
+ MultiQuestionDetails,
13
+ MultiQuestionParams,
14
+ MultiTabAnswer,
15
+ QuestionDetails,
16
+ QuestionParams,
17
+ QuestionUiResult,
18
+ QuestionsParams,
19
+ SelectType,
20
+ SingleTabAnswer,
21
+ TabAnswer,
22
+ } from "./types.ts";
23
+
24
+ const SelectTypeSchema = Type.Optional(
25
+ Type.Union([Type.Literal("single"), Type.Literal("multi")], {
26
+ description: '"single" (default) or "multi" — allows multiple selections',
27
+ }),
28
+ );
12
29
 
13
30
  const OptionSchema = Type.Object({
14
31
  label: Type.String({ description: "Display label for the option" }),
@@ -17,11 +34,44 @@ const OptionSchema = Type.Object({
17
34
  ),
18
35
  });
19
36
 
20
- const QuestionParamsSchema = Type.Object({
37
+ const QuestionTabSchema = Type.Object({
38
+ id: Type.Optional(
39
+ Type.String({
40
+ description:
41
+ "Optional stable identifier used as result key (defaults to q0, q1, …)",
42
+ }),
43
+ ),
44
+ title: Type.Optional(
45
+ Type.String({
46
+ description: "Optional tab bar label (defaults to Q1, Q2, …)",
47
+ }),
48
+ ),
21
49
  question: Type.String({ description: "The question to ask the user" }),
22
50
  options: Type.Array(OptionSchema, {
23
51
  description: "Options for the user to choose from",
24
52
  }),
53
+ selectType: SelectTypeSchema,
54
+ });
55
+
56
+ const QuestionParamsSchema = Type.Object({
57
+ question: Type.Optional(
58
+ Type.String({
59
+ description: "The question to ask the user (single‑question mode)",
60
+ }),
61
+ ),
62
+ options: Type.Optional(
63
+ Type.Array(OptionSchema, {
64
+ description: "Options for the user to choose from (single‑question mode)",
65
+ }),
66
+ ),
67
+ selectType: SelectTypeSchema,
68
+ questions: Type.Optional(
69
+ Type.Array(QuestionTabSchema, {
70
+ description:
71
+ "Multiple questions displayed as tabs (multi‑question mode). Overrides question/options when present.",
72
+ minItems: 1,
73
+ }),
74
+ ),
25
75
  });
26
76
 
27
77
  export interface QuestionToolDeps {
@@ -32,6 +82,8 @@ export interface QuestionToolDeps {
32
82
  };
33
83
  }
34
84
 
85
+ // ── result builders (single) ──
86
+
35
87
  function buildCancelledResult(
36
88
  params: QuestionParams,
37
89
  ): AgentToolResult<QuestionDetails> {
@@ -48,34 +100,72 @@ function buildCancelledResult(
48
100
 
49
101
  function buildAnswerResult(
50
102
  params: QuestionParams,
51
- answer: string,
52
- wasCustom: boolean,
53
- index?: number,
103
+ answerData: string | SingleTabAnswer | MultiTabAnswer | QuestionUiResult,
54
104
  ): AgentToolResult<QuestionDetails> {
55
105
  const simpleOptions = params.options.map((o) => o.label);
56
- if (wasCustom) {
106
+
107
+ // Check for multi-select (from MultiTabAnswer or QuestionUiResult)
108
+ if (typeof answerData === "object" && ("answers" in answerData || "multiAnswers" in answerData)) {
109
+ const multiAnswers = "answers" in answerData
110
+ ? (answerData as MultiTabAnswer).answers
111
+ : (answerData as QuestionUiResult).multiAnswers ?? [];
112
+ const multiIndices = "indices" in answerData
113
+ ? (answerData as MultiTabAnswer).indices
114
+ : (answerData as QuestionUiResult).multiIndices ?? [];
115
+
116
+ const lines = multiAnswers.map((a: string, i: number) => {
117
+ const idx = multiIndices[i];
118
+ return idx === -1 ? ` (custom) ${a}` : ` ${idx}. ${a}`;
119
+ });
57
120
  return {
58
- content: [{ type: "text", text: `User wrote: ${answer}` }],
121
+ content: [{ type: "text", text: `User selected:\n${lines.join("\n")}` }],
59
122
  details: {
60
123
  question: params.question,
61
124
  options: simpleOptions,
62
- answer,
63
- wasCustom: true,
125
+ answer: multiAnswers.join(", "),
126
+ multiAnswers,
127
+ multiIndices,
64
128
  },
65
129
  };
66
130
  }
67
- return {
68
- content: [
69
- {
70
- type: "text",
71
- text: `User selected: ${index ?? simpleOptions.indexOf(answer) + 1}. ${answer}`,
131
+
132
+ if (typeof answerData === "object") {
133
+ // Single select
134
+ const single = answerData as SingleTabAnswer;
135
+ if (single.wasCustom) {
136
+ return {
137
+ content: [{ type: "text", text: `User wrote: ${single.answer}` }],
138
+ details: {
139
+ question: params.question,
140
+ options: simpleOptions,
141
+ answer: single.answer,
142
+ wasCustom: true,
143
+ },
144
+ };
145
+ }
146
+ return {
147
+ content: [
148
+ {
149
+ type: "text",
150
+ text: `User selected: ${single.index ?? simpleOptions.indexOf(single.answer) + 1}. ${single.answer}`,
151
+ },
152
+ ],
153
+ details: {
154
+ question: params.question,
155
+ options: simpleOptions,
156
+ answer: single.answer,
157
+ wasCustom: false,
72
158
  },
73
- ],
159
+ };
160
+ }
161
+
162
+ // Legacy string
163
+ return {
164
+ content: [{ type: "text", text: `User selected: ${answerData}` }],
74
165
  details: {
75
166
  question: params.question,
76
167
  options: simpleOptions,
77
- answer,
78
- wasCustom: false,
168
+ answer: answerData,
79
169
  },
80
170
  };
81
171
  }
@@ -94,7 +184,75 @@ function buildUnavailableResult(
94
184
  };
95
185
  }
96
186
 
97
- async function executeQuestion(
187
+ // ── result builders (multi) ──
188
+
189
+ function buildMultiCancelledResult(
190
+ params: MultiQuestionParams,
191
+ ): AgentToolResult<MultiQuestionDetails> {
192
+ return {
193
+ content: [
194
+ { type: "text", text: "User cancelled the multi‑question selection" },
195
+ ],
196
+ details: {
197
+ answers: {},
198
+ },
199
+ };
200
+ }
201
+
202
+ function buildMultiAnswerResult(
203
+ params: MultiQuestionParams,
204
+ answers: Record<string, TabAnswer>,
205
+ ): AgentToolResult<MultiQuestionDetails> {
206
+ const lines: string[] = ["User answered:"];
207
+ for (const [key, ans] of Object.entries(answers)) {
208
+ const tab = params.questions.find(
209
+ (q) => (q.id ?? `q${params.questions.indexOf(q)}`) === key,
210
+ );
211
+ const label = tab?.title ?? key;
212
+ if ("answers" in ans) {
213
+ const multi = ans as MultiTabAnswer;
214
+ const parts = multi.answers.map((a, i) => {
215
+ const idx = multi.indices[i];
216
+ return idx === -1 ? `${a}(custom)` : `${idx}. ${a}`;
217
+ });
218
+ lines.push(` ${label}: ${parts.join(", ")}`);
219
+ } else {
220
+ const single = ans as SingleTabAnswer;
221
+ if (single.wasCustom) {
222
+ lines.push(` ${label}: ${single.answer} (custom)`);
223
+ } else {
224
+ lines.push(` ${label}: ${single.index}. ${single.answer}`);
225
+ }
226
+ }
227
+ }
228
+ return {
229
+ content: [{ type: "text", text: lines.join("\n") }],
230
+ details: { answers },
231
+ };
232
+ }
233
+
234
+ function buildMultiUnavailableResult(
235
+ params: MultiQuestionParams,
236
+ reason: string,
237
+ ): AgentToolResult<MultiQuestionDetails> {
238
+ return {
239
+ content: [{ type: "text", text: reason }],
240
+ details: { answers: {} },
241
+ };
242
+ }
243
+
244
+ // ── execution ──
245
+
246
+ function isMultiParams(
247
+ params: QuestionsParams,
248
+ ): params is MultiQuestionParams {
249
+ return (
250
+ "questions" in params &&
251
+ Array.isArray((params as MultiQuestionParams).questions)
252
+ );
253
+ }
254
+
255
+ async function executeSingleQuestion(
98
256
  params: QuestionParams,
99
257
  ctx: ExtensionContext,
100
258
  deps: QuestionToolDeps,
@@ -110,12 +268,13 @@ async function executeQuestion(
110
268
  if (!child && ctx.hasUI) {
111
269
  const result = await runQuestionUi(ctx.ui, params);
112
270
  if (!result) return buildCancelledResult(params);
113
- return buildAnswerResult(
114
- params,
115
- result.answer,
116
- result.wasCustom,
117
- result.index,
118
- );
271
+ if (result.multiAnswers && result.multiIndices) {
272
+ return buildAnswerResult(params, {
273
+ answers: result.multiAnswers,
274
+ indices: result.multiIndices,
275
+ } as MultiTabAnswer);
276
+ }
277
+ return buildAnswerResult(params, result as SingleTabAnswer);
119
278
  }
120
279
 
121
280
  if (!parentSessionId) {
@@ -140,17 +299,83 @@ async function executeQuestion(
140
299
  );
141
300
  }
142
301
 
143
- if (forwarded.cancelled || forwarded.answer === null) {
302
+ if (forwarded.cancelled) {
144
303
  return buildCancelledResult(params);
145
304
  }
146
305
 
147
- return buildAnswerResult(
306
+ // Multi-select via forwarding
307
+ if (forwarded.multiAnswers && forwarded.multiIndices) {
308
+ return buildAnswerResult(params, {
309
+ answers: forwarded.multiAnswers,
310
+ indices: forwarded.multiIndices,
311
+ } as MultiTabAnswer);
312
+ }
313
+
314
+ // Single-select via forwarding
315
+ if (forwarded.answer !== null && forwarded.answer !== undefined) {
316
+ return buildAnswerResult(params, {
317
+ answer: forwarded.answer,
318
+ wasCustom: forwarded.wasCustom ?? false,
319
+ } as SingleTabAnswer);
320
+ }
321
+
322
+ return buildCancelledResult(params);
323
+ }
324
+
325
+ async function executeMultiQuestion(
326
+ params: MultiQuestionParams,
327
+ ctx: ExtensionContext,
328
+ deps: QuestionToolDeps,
329
+ ): Promise<AgentToolResult<MultiQuestionDetails>> {
330
+ if (params.questions.length === 0) {
331
+ return buildMultiUnavailableResult(params, "Error: No questions provided");
332
+ }
333
+
334
+ const child = isSubagentChild();
335
+ const parentSessionId = resolveParentSessionId();
336
+ const currentSessionId = ctx.sessionManager.getSessionId?.() ?? null;
337
+
338
+ if (!child && ctx.hasUI) {
339
+ const result = await runMultiQuestionUi(ctx.ui, params);
340
+ if (!result) return buildMultiCancelledResult(params);
341
+ return buildMultiAnswerResult(params, result.answers);
342
+ }
343
+
344
+ if (!parentSessionId) {
345
+ return buildMultiUnavailableResult(
346
+ params,
347
+ "Error: UI not available (running in non-interactive mode)",
348
+ );
349
+ }
350
+
351
+ const forwarded = await forwardQuestionPrompt({
352
+ events: deps.events,
353
+ agentDir: deps.getAgentDir(),
354
+ targetSessionId: parentSessionId,
355
+ requesterSessionId: currentSessionId ?? "unknown",
148
356
  params,
149
- forwarded.answer,
150
- forwarded.wasCustom ?? false,
151
- );
357
+ });
358
+
359
+ if (!forwarded) {
360
+ return buildMultiUnavailableResult(
361
+ params,
362
+ "Error: Question prompt timed out or parent session unavailable",
363
+ );
364
+ }
365
+
366
+ if (forwarded.cancelled) {
367
+ return buildMultiCancelledResult(params);
368
+ }
369
+
370
+ if (forwarded.answers) {
371
+ return buildMultiAnswerResult(params, forwarded.answers);
372
+ }
373
+
374
+ return buildMultiUnavailableResult(params, "Error: No answers returned");
152
375
  }
153
376
 
377
+ // ── tool registration ──
378
+
154
379
  export function registerQuestionTool(
155
380
  pi: ExtensionAPI,
156
381
  deps: QuestionToolDeps,
@@ -159,12 +384,26 @@ export function registerQuestionTool(
159
384
  name: "question",
160
385
  label: "Question",
161
386
  description:
162
- "Ask the user a question and let them pick from options. Use when you need user input to proceed.",
387
+ "Ask the user a question and let them pick from options. Supports single questions (question+options) or multiple tabbed questions (questions[]). Use when you need user input to proceed.",
163
388
  parameters: QuestionParamsSchema,
164
389
  executionMode: "sequential",
165
390
 
166
391
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
167
- return executeQuestion(params, ctx, deps);
392
+ const p = params as QuestionsParams;
393
+ if (isMultiParams(p)) {
394
+ return executeMultiQuestion(p, ctx, deps);
395
+ }
396
+ const single = p as QuestionParams;
397
+ if (!single.question || !single.options) {
398
+ return buildUnavailableResult(
399
+ {
400
+ question: single.question ?? "",
401
+ options: single.options ?? [],
402
+ },
403
+ "Error: Provide either question+options or questions[]",
404
+ );
405
+ }
406
+ return executeSingleQuestion(single, ctx, deps);
168
407
  },
169
408
 
170
409
  renderCall(_args, theme, _context) {
@@ -172,19 +411,56 @@ export function registerQuestionTool(
172
411
  },
173
412
 
174
413
  renderResult(result, _options, theme, _context) {
175
- const details = result.details as QuestionDetails | undefined;
414
+ const details = result.details as
415
+ | QuestionDetails
416
+ | MultiQuestionDetails
417
+ | undefined;
176
418
  if (!details) {
177
419
  const text = result.content[0];
178
420
  const fallback = text?.type === "text" ? text.text : "";
179
421
  return new Text(fallback, 0, 0);
180
422
  }
181
423
 
182
- if (details.answer === null) {
183
- return new Text(theme.fg("warning", "Cancelled"), 0, 0);
424
+ // Multi-question (tabbed) result
425
+ if ("answers" in details && details.answers) {
426
+ const ans = details.answers;
427
+ const keys = Object.keys(ans);
428
+ if (keys.length === 0) {
429
+ return new Text(theme.fg("warning", "Cancelled"), 0, 0);
430
+ }
431
+ const first = ans[keys[0]!];
432
+ if (keys.length === 1 && first) {
433
+ const display = "answers" in first
434
+ ? (first as MultiTabAnswer).answers.join(", ")
435
+ : (first as SingleTabAnswer).answer;
436
+ return new Text(
437
+ theme.fg("success", "✓ ") + theme.fg("accent", display),
438
+ 0,
439
+ 0,
440
+ );
441
+ }
442
+ return new Text(
443
+ theme.fg("success", `✓ ${keys.length} answered`),
444
+ 0,
445
+ 0,
446
+ );
184
447
  }
185
448
 
449
+ // Single-question result
450
+ const sq = details as QuestionDetails;
451
+ if (sq.multiAnswers && sq.multiAnswers.length > 0) {
452
+ return new Text(
453
+ theme.fg("success", "✓ ") +
454
+ theme.fg("accent", sq.multiAnswers.join(", ")),
455
+ 0,
456
+ 0,
457
+ );
458
+ }
459
+ if (sq.answer === null || sq.answer === undefined) {
460
+ return new Text(theme.fg("warning", "Cancelled"), 0, 0);
461
+ }
186
462
  return new Text(
187
- theme.fg("success", "✓ ") + theme.fg("accent", details.answer),
463
+ theme.fg("success", "✓ ") + theme.fg("accent", sq.answer),
188
464
  0,
189
465
  0,
190
466
  );
@@ -192,26 +468,61 @@ export function registerQuestionTool(
192
468
  });
193
469
  }
194
470
 
471
+ // ── local prompt helper ──
472
+
195
473
  export async function promptQuestionLocally(
196
474
  ui: ExtensionContext["ui"],
197
- params: QuestionParams,
475
+ params: QuestionParams | MultiQuestionParams,
198
476
  responderSessionId: string,
199
477
  ) {
200
- const simpleOptions = params.options.map((o) => o.label);
478
+ if (isMultiParams(params)) {
479
+ const result = await runMultiQuestionUi(ui, params);
480
+ if (!result) {
481
+ return {
482
+ answers: {},
483
+ cancelled: true,
484
+ responderSessionId,
485
+ respondedAt: Date.now(),
486
+ };
487
+ }
488
+ return {
489
+ answers: result.answers,
490
+ cancelled: false,
491
+ responderSessionId,
492
+ respondedAt: Date.now(),
493
+ };
494
+ }
495
+
201
496
  const result = await runQuestionUi(ui, params);
202
497
  if (!result) {
203
498
  return {
204
499
  question: params.question,
205
- options: simpleOptions,
500
+ options: params.options.map((o) => o.label),
206
501
  answer: null,
207
502
  cancelled: true,
208
503
  responderSessionId,
209
504
  respondedAt: Date.now(),
210
505
  };
211
506
  }
507
+
508
+ // Multi-select result
509
+ if (result.multiAnswers && result.multiIndices) {
510
+ return {
511
+ question: params.question,
512
+ options: params.options.map((o) => o.label),
513
+ answer: result.multiAnswers.join(", "),
514
+ multiAnswers: result.multiAnswers,
515
+ multiIndices: result.multiIndices,
516
+ cancelled: false,
517
+ responderSessionId,
518
+ respondedAt: Date.now(),
519
+ };
520
+ }
521
+
522
+ // Single-select result
212
523
  return {
213
524
  question: params.question,
214
- options: simpleOptions,
525
+ options: params.options.map((o) => o.label),
215
526
  answer: result.answer,
216
527
  wasCustom: result.wasCustom,
217
528
  cancelled: false,
@@ -1,3 +1,5 @@
1
+ export type SelectType = "single" | "multi";
2
+
1
3
  export interface QuestionOption {
2
4
  label: string;
3
5
  description?: string;
@@ -6,35 +8,105 @@ export interface QuestionOption {
6
8
  export interface QuestionParams {
7
9
  question: string;
8
10
  options: QuestionOption[];
11
+ selectType?: SelectType;
9
12
  }
10
13
 
11
- export interface QuestionDetails {
14
+ // --- Multi-question (tabs) types ---
15
+
16
+ export interface QuestionTab {
17
+ /** Optional stable identifier used as result key; defaults to "q0", "q1", … */
18
+ id?: string;
19
+ /** Tab bar label; defaults to "Q1", "Q2", … */
20
+ title?: string;
21
+ /** The question text shown inside the tab */
12
22
  question: string;
13
- options: string[];
23
+ options: QuestionOption[];
24
+ /** "single" (default) or "multi" */
25
+ selectType?: SelectType;
26
+ }
27
+
28
+ export interface MultiQuestionParams {
29
+ questions: QuestionTab[];
30
+ }
31
+
32
+ // --- Answer types ---
33
+
34
+ /** Single-select answer (one pick) */
35
+ export interface SingleTabAnswer {
36
+ answer: string;
37
+ wasCustom: boolean;
38
+ index?: number;
39
+ }
40
+
41
+ /** Multi-select answer (multiple picks) */
42
+ export interface MultiTabAnswer {
43
+ answers: string[];
44
+ indices: number[];
45
+ }
46
+
47
+ export type TabAnswer = SingleTabAnswer | MultiTabAnswer;
48
+
49
+ export type QuestionsParams = QuestionParams | MultiQuestionParams;
50
+
51
+ /** Returns true if the answer is a multi-select answer */
52
+ export function isMultiAnswer(ans: TabAnswer): ans is MultiTabAnswer {
53
+ return "answers" in ans;
54
+ }
55
+
56
+ // --- Result types ---
57
+
58
+ export interface QuestionDetails {
59
+ question?: string;
60
+ options?: string[];
14
61
  answer: string | null;
15
62
  wasCustom?: boolean;
63
+ /** Multi-select answers (present when selectType="multi") */
64
+ multiAnswers?: string[];
65
+ multiIndices?: number[];
66
+ }
67
+
68
+ export interface MultiQuestionDetails {
69
+ answers: Record<string, TabAnswer>;
16
70
  }
17
71
 
18
72
  export interface QuestionUiResult {
19
73
  answer: string;
20
74
  wasCustom: boolean;
21
75
  index?: number;
76
+ /** Multi-select answers (present when selectType="multi") */
77
+ multiAnswers?: string[];
78
+ multiIndices?: number[];
22
79
  }
23
80
 
81
+ export interface MultiQuestionUiResult {
82
+ answers: Record<string, TabAnswer>;
83
+ }
84
+
85
+ // --- Forwarding types ---
86
+
24
87
  export interface ForwardedQuestionRequest {
25
88
  id: string;
26
89
  createdAt: number;
27
90
  requesterSessionId: string;
28
91
  targetSessionId: string;
29
- question: string;
30
- options: QuestionOption[];
92
+ /** Single question (legacy) */
93
+ question?: string;
94
+ options?: QuestionOption[];
95
+ selectType?: SelectType;
96
+ /** Multi-question (new) */
97
+ questions?: QuestionTab[];
31
98
  }
32
99
 
33
100
  export interface ForwardedQuestionResponse {
34
- question: string;
35
- options: string[];
36
- answer: string | null;
101
+ question?: string;
102
+ options?: string[];
103
+ answer?: string | null;
37
104
  wasCustom?: boolean;
105
+ /** Multi-select answers */
106
+ multiAnswers?: string[];
107
+ multiIndices?: number[];
108
+ /** Multi-question answers (each value can be single or multi answer) */
109
+ answers?: Record<string, TabAnswer>;
38
110
  cancelled?: boolean;
39
111
  responderSessionId: string;
40
112
  respondedAt: number;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitos-pizza/session-title",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Async session auto-naming for Vito's Pizzeria Pi distribution",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -11,7 +11,7 @@
11
11
  ]
12
12
  },
13
13
  "dependencies": {
14
- "@vitos-pizza/subagents": "0.3.1"
14
+ "@vitos-pizza/subagents": "0.4.1"
15
15
  },
16
16
  "scripts": {
17
17
  "test": "vitest run",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@earendil-works/pi-ai": "*",
32
32
  "@earendil-works/pi-coding-agent": "*",
33
- "@vitos-pizza/subagents": "0.3.1",
33
+ "@vitos-pizza/subagents": "0.4.1",
34
34
  "typebox": "*",
35
35
  "vitest": "^3.2.4"
36
36
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitos-pizza/settings-preset",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "Default Pi settings for Vito's Pizzeria distribution — written on first session start",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: planner
3
3
  description: Creates implementation plans from context and requirements
4
- tools: read, grep, find, ls, write, question, web_search, web_read
4
+ tools: hypa_read, hypa_grep, hypa_find, hypa_ls, write, question, web_search, web_read
5
5
  thinking: high
6
6
  systemPromptMode: replace
7
7
  ---
@@ -10,6 +10,7 @@ You are planner: turn requirements and code context into a concrete implementati
10
10
 
11
11
  Rules:
12
12
  - Read provided context (and more code as needed) before planning.
13
+ - Use `hypa_read` / `hypa_grep` / `hypa_find` / `hypa_ls` for codebase exploration.
13
14
  - Name exact files; prefer small, ordered, actionable tasks; call out risks and dependencies.
14
15
  - Underspecified or mutually exclusive choices → use `question` before guessing.
15
16
  - Web tools only for current external facts outside the repo.
@@ -39,4 +40,4 @@ Anything likely to go wrong or need careful verification.
39
40
  ## 功能验收
40
41
  3–6 checkboxes of observable outcomes (yes/no verifiable).
41
42
 
42
- Keep the plan concrete enough for another agent to execute without guessing. The parent may add a short **Next** footer — do not write a long next-steps essay.
43
+ Keep the plan concrete enough for another agent to execute without guessing. The parent may add a short **Worth considering** footer for gaps or adjacent capabilities — do not write a long next-steps essay.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: scout
3
3
  description: Fast codebase recon that returns compressed context for handoff
4
- tools: read, grep, find, ls, question, web_search, web_read
4
+ tools: hypa_read, hypa_grep, hypa_find, hypa_ls, question, web_search, web_read
5
5
  thinking: low
6
6
  systemPromptMode: replace
7
7
  ---
@@ -11,6 +11,7 @@ You are scout: fast codebase recon for handoff. Do not guess. Prefer targeted se
11
11
  Return the minimum context another agent needs: entry points, key types/APIs, data flow, files likely to change, risks and open questions.
12
12
 
13
13
  Rules:
14
+ - Use `hypa_read` / `hypa_grep` / `hypa_find` / `hypa_ls` for codebase exploration.
14
15
  - Cite exact file paths and line ranges.
15
16
  - Use `question` only when ambiguity blocks recon; prefer structured options over free-text choices.
16
17
  - Web tools only for current external facts outside the repo.