@vitos-pizza/vitos-pizza 0.1.0 → 0.2.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.
Files changed (259) hide show
  1. package/AGENTS.md +158 -158
  2. package/CHANGELOG.md +42 -24
  3. package/LICENSE +21 -21
  4. package/README.md +237 -234
  5. package/assets/logo.svg +28 -28
  6. package/node_modules/@vitos-pizza/agent-mode/extensions/index.ts +138 -117
  7. package/node_modules/@vitos-pizza/agent-mode/package.json +3 -3
  8. package/node_modules/@vitos-pizza/agent-mode/src/apply-mode.ts +60 -60
  9. package/node_modules/@vitos-pizza/agent-mode/src/mode-events.ts +102 -102
  10. package/node_modules/@vitos-pizza/agent-mode/src/modes.ts +43 -43
  11. package/node_modules/@vitos-pizza/agent-mode/src/plan-instructions.ts +85 -44
  12. package/node_modules/@vitos-pizza/agent-mode/tests/apply-mode.test.ts +36 -36
  13. package/node_modules/@vitos-pizza/agent-mode/tests/mode-events.test.ts +22 -22
  14. package/node_modules/@vitos-pizza/agent-mode/tests/modes.test.ts +38 -38
  15. package/node_modules/@vitos-pizza/agent-mode/tests/plan-instructions.test.ts +68 -45
  16. package/node_modules/@vitos-pizza/agent-mode/tsconfig.json +13 -13
  17. package/node_modules/@vitos-pizza/agent-mode/vitest.config.ts +8 -8
  18. package/node_modules/@vitos-pizza/keybindings/extensions/index.ts +104 -104
  19. package/node_modules/@vitos-pizza/keybindings/package.json +1 -1
  20. package/node_modules/@vitos-pizza/keybindings/presets/shortcuts.json +3 -3
  21. package/node_modules/@vitos-pizza/keybindings/src/bind.ts +57 -57
  22. package/node_modules/@vitos-pizza/keybindings/src/config.ts +84 -84
  23. package/node_modules/@vitos-pizza/keybindings/src/registry.ts +43 -43
  24. package/node_modules/@vitos-pizza/keybindings/src/types.ts +54 -54
  25. package/node_modules/@vitos-pizza/keybindings/tests/config.test.ts +83 -83
  26. package/node_modules/@vitos-pizza/keybindings/tests/registry.test.ts +142 -142
  27. package/node_modules/@vitos-pizza/keybindings/tsconfig.json +13 -13
  28. package/node_modules/@vitos-pizza/keybindings/vitest.config.ts +8 -8
  29. package/node_modules/@vitos-pizza/permission-system/extensions/index.ts +162 -162
  30. package/node_modules/@vitos-pizza/permission-system/package.json +2 -2
  31. package/node_modules/@vitos-pizza/permission-system/src/bash/matcher.ts +54 -51
  32. package/node_modules/@vitos-pizza/permission-system/src/bash/parser.ts +40 -40
  33. package/node_modules/@vitos-pizza/permission-system/src/config-paths.ts +23 -23
  34. package/node_modules/@vitos-pizza/permission-system/src/detect-preset-mode.ts +61 -61
  35. package/node_modules/@vitos-pizza/permission-system/src/expand-home.ts +12 -12
  36. package/node_modules/@vitos-pizza/permission-system/src/forwarding/forwarder.ts +224 -224
  37. package/node_modules/@vitos-pizza/permission-system/src/forwarding/subagent-registry.ts +61 -61
  38. package/node_modules/@vitos-pizza/permission-system/src/gates/path-utils.ts +66 -66
  39. package/node_modules/@vitos-pizza/permission-system/src/gates/pipeline.ts +151 -155
  40. package/node_modules/@vitos-pizza/permission-system/src/handlers/before-agent-start.ts +86 -65
  41. package/node_modules/@vitos-pizza/permission-system/src/handlers/skill-input.ts +1 -1
  42. package/node_modules/@vitos-pizza/permission-system/src/handlers/tool-call-gate.ts +204 -199
  43. package/node_modules/@vitos-pizza/permission-system/src/mode-api.ts +44 -44
  44. package/node_modules/@vitos-pizza/permission-system/src/permission-evaluator.ts +233 -216
  45. package/node_modules/@vitos-pizza/permission-system/src/permission-session.ts +62 -62
  46. package/node_modules/@vitos-pizza/permission-system/src/policy-loader.ts +211 -211
  47. package/node_modules/@vitos-pizza/permission-system/src/sanitizers/skill-prompt.ts +99 -99
  48. package/node_modules/@vitos-pizza/permission-system/src/sanitizers/system-prompt.ts +221 -221
  49. package/node_modules/@vitos-pizza/permission-system/src/service.ts +66 -66
  50. package/node_modules/@vitos-pizza/permission-system/src/session-approvals.ts +4 -1
  51. package/node_modules/@vitos-pizza/permission-system/src/types.ts +80 -80
  52. package/node_modules/@vitos-pizza/permission-system/src/ui/approval-summary.ts +43 -43
  53. package/node_modules/@vitos-pizza/permission-system/src/ui/config-modal.ts +36 -36
  54. package/node_modules/@vitos-pizza/permission-system/src/ui/permission-dialog.ts +52 -52
  55. package/node_modules/@vitos-pizza/permission-system/src/wildcard-matcher.ts +81 -81
  56. package/node_modules/@vitos-pizza/permission-system/src/yaml-frontmatter.ts +84 -84
  57. package/node_modules/@vitos-pizza/permission-system/src/yolo/runtime-api.ts +49 -49
  58. package/node_modules/@vitos-pizza/permission-system/tests/bash-parser.test.ts +32 -32
  59. package/node_modules/@vitos-pizza/permission-system/tests/before-agent-start.test.ts +61 -0
  60. package/node_modules/@vitos-pizza/permission-system/tests/detect-preset-mode.test.ts +68 -68
  61. package/node_modules/@vitos-pizza/permission-system/tests/forwarder.test.ts +55 -55
  62. package/node_modules/@vitos-pizza/permission-system/tests/gates.test.ts +170 -61
  63. package/node_modules/@vitos-pizza/permission-system/tests/path-utils.test.ts +68 -68
  64. package/node_modules/@vitos-pizza/permission-system/tests/permission-evaluator.test.ts +82 -55
  65. package/node_modules/@vitos-pizza/permission-system/tests/policy-loader.test.ts +25 -25
  66. package/node_modules/@vitos-pizza/permission-system/tests/system-prompt-sanitizer.test.ts +22 -22
  67. package/node_modules/@vitos-pizza/permission-system/tests/wildcard-matcher.test.ts +27 -27
  68. package/node_modules/@vitos-pizza/permission-system/tsconfig.json +13 -13
  69. package/node_modules/@vitos-pizza/permission-system/vitest.config.ts +8 -8
  70. package/node_modules/@vitos-pizza/question/package.json +1 -1
  71. package/node_modules/@vitos-pizza/question/src/question-ui.ts +5 -1
  72. package/node_modules/@vitos-pizza/question/src/register-tool.ts +1 -4
  73. package/node_modules/@vitos-pizza/question/tests/question-ui-width-cache.test.ts +45 -0
  74. package/node_modules/@vitos-pizza/question/tests/register-tool-render.test.ts +48 -45
  75. package/node_modules/@vitos-pizza/session-title/extensions/index.ts +137 -137
  76. package/node_modules/@vitos-pizza/session-title/package.json +3 -3
  77. package/node_modules/@vitos-pizza/session-title/src/build-title-prompt.ts +16 -16
  78. package/node_modules/@vitos-pizza/session-title/src/extract-title-context.ts +55 -55
  79. package/node_modules/@vitos-pizza/session-title/src/fast-rules.ts +48 -48
  80. package/node_modules/@vitos-pizza/session-title/src/load-settings.ts +70 -70
  81. package/node_modules/@vitos-pizza/session-title/src/normalize-title.ts +20 -20
  82. package/node_modules/@vitos-pizza/session-title/src/parse-title-response.ts +6 -6
  83. package/node_modules/@vitos-pizza/session-title/src/resolve-title-model.ts +33 -33
  84. package/node_modules/@vitos-pizza/session-title/src/schedule-title-job.ts +53 -53
  85. package/node_modules/@vitos-pizza/session-title/src/should-schedule.ts +30 -30
  86. package/node_modules/@vitos-pizza/session-title/src/title-agent.ts +60 -60
  87. package/node_modules/@vitos-pizza/session-title/src/truncate-input.ts +10 -10
  88. package/node_modules/@vitos-pizza/session-title/src/types.ts +29 -29
  89. package/node_modules/@vitos-pizza/session-title/tests/build-title-prompt.test.ts +34 -34
  90. package/node_modules/@vitos-pizza/session-title/tests/extension.test.ts +198 -198
  91. package/node_modules/@vitos-pizza/session-title/tests/extract-title-context.test.ts +48 -48
  92. package/node_modules/@vitos-pizza/session-title/tests/fast-rules.test.ts +43 -43
  93. package/node_modules/@vitos-pizza/session-title/tests/parse-title-response.test.ts +34 -34
  94. package/node_modules/@vitos-pizza/session-title/tests/should-schedule.test.ts +30 -30
  95. package/node_modules/@vitos-pizza/session-title/tests/title-agent.test.ts +154 -154
  96. package/node_modules/@vitos-pizza/session-title/tests/truncate-input.test.ts +15 -15
  97. package/node_modules/@vitos-pizza/session-title/tsconfig.json +13 -13
  98. package/node_modules/@vitos-pizza/session-title/vitest.config.ts +8 -8
  99. package/node_modules/@vitos-pizza/subagents/agents/planner.md +46 -43
  100. package/node_modules/@vitos-pizza/subagents/agents/scout.md +40 -40
  101. package/node_modules/@vitos-pizza/subagents/agents/title.md +13 -13
  102. package/node_modules/@vitos-pizza/subagents/agents/worker.md +36 -36
  103. package/node_modules/@vitos-pizza/subagents/extensions/index.ts +164 -164
  104. package/node_modules/@vitos-pizza/subagents/package.json +1 -1
  105. package/node_modules/@vitos-pizza/subagents/skills/subagents/SKILL.md +86 -80
  106. package/node_modules/@vitos-pizza/subagents/src/agents.ts +166 -166
  107. package/node_modules/@vitos-pizza/subagents/src/async/job-tracker.ts +71 -71
  108. package/node_modules/@vitos-pizza/subagents/src/async/spawn-async.ts +220 -220
  109. package/node_modules/@vitos-pizza/subagents/src/async/storage.ts +57 -57
  110. package/node_modules/@vitos-pizza/subagents/src/env.ts +4 -4
  111. package/node_modules/@vitos-pizza/subagents/src/execute-subagent.ts +285 -285
  112. package/node_modules/@vitos-pizza/subagents/src/progress.ts +187 -187
  113. package/node_modules/@vitos-pizza/subagents/src/render-animation.ts +40 -40
  114. package/node_modules/@vitos-pizza/subagents/src/render.ts +428 -428
  115. package/node_modules/@vitos-pizza/subagents/src/rpc/channels.ts +21 -21
  116. package/node_modules/@vitos-pizza/subagents/src/rpc/client.ts +144 -144
  117. package/node_modules/@vitos-pizza/subagents/src/rpc/server.ts +11 -11
  118. package/node_modules/@vitos-pizza/subagents/src/run-agent.ts +313 -313
  119. package/node_modules/@vitos-pizza/subagents/src/runtime.ts +102 -102
  120. package/node_modules/@vitos-pizza/subagents/src/schema.ts +62 -62
  121. package/node_modules/@vitos-pizza/subagents/src/spawn.ts +104 -104
  122. package/node_modules/@vitos-pizza/subagents/src/types.ts +92 -92
  123. package/node_modules/@vitos-pizza/subagents/src/utils.ts +100 -100
  124. package/node_modules/@vitos-pizza/subagents/src/wait.ts +159 -159
  125. package/node_modules/@vitos-pizza/subagents/tests/agents.test.ts +19 -19
  126. package/node_modules/@vitos-pizza/subagents/tests/execute-subagent.test.ts +96 -96
  127. package/node_modules/@vitos-pizza/subagents/tests/extension.test.ts +42 -42
  128. package/node_modules/@vitos-pizza/subagents/tests/progress.test.ts +206 -206
  129. package/node_modules/@vitos-pizza/subagents/tests/rpc.test.ts +74 -74
  130. package/node_modules/@vitos-pizza/subagents/tsconfig.json +13 -13
  131. package/node_modules/@vitos-pizza/subagents/vitest.config.ts +8 -8
  132. package/node_modules/@vitos-pizza/ui-enhancements/package.json +1 -1
  133. package/node_modules/@vitos-pizza/ui-enhancements/src/chrome/agent-mode-badge.ts +60 -60
  134. package/node_modules/@vitos-pizza/ui-enhancements/src/chrome/border-status.ts +14 -1
  135. package/node_modules/@vitos-pizza/ui-enhancements/src/chrome/resize-recovery.ts +63 -0
  136. package/node_modules/@vitos-pizza/ui-enhancements/tests/agent-mode-badge.test.ts +35 -35
  137. package/node_modules/@vitos-pizza/ui-enhancements/tests/resize-recovery.test.ts +135 -0
  138. package/node_modules/@vitos-pizza/websearch/package.json +1 -1
  139. package/node_modules/node-addon-api/tools/conversion.js +0 -0
  140. package/node_modules/node-gyp-build/bin.js +0 -0
  141. package/node_modules/node-gyp-build/build-test.js +0 -0
  142. package/node_modules/node-gyp-build/optional.js +0 -0
  143. package/package.json +11 -9
  144. package/packages/agent-mode/extensions/index.ts +138 -117
  145. package/packages/agent-mode/package.json +3 -3
  146. package/packages/agent-mode/src/apply-mode.ts +60 -60
  147. package/packages/agent-mode/src/mode-events.ts +102 -102
  148. package/packages/agent-mode/src/modes.ts +43 -43
  149. package/packages/agent-mode/src/plan-instructions.ts +85 -44
  150. package/packages/agent-mode/tsconfig.json +13 -13
  151. package/packages/agent-mode/vitest.config.ts +8 -8
  152. package/packages/keybindings/extensions/index.ts +104 -104
  153. package/packages/keybindings/package.json +1 -1
  154. package/packages/keybindings/presets/shortcuts.json +3 -3
  155. package/packages/keybindings/src/bind.ts +57 -57
  156. package/packages/keybindings/src/config.ts +84 -84
  157. package/packages/keybindings/src/registry.ts +43 -43
  158. package/packages/keybindings/src/types.ts +54 -54
  159. package/packages/keybindings/tsconfig.json +13 -13
  160. package/packages/keybindings/vitest.config.ts +8 -8
  161. package/packages/permission-system/extensions/index.ts +162 -162
  162. package/packages/permission-system/node_modules/web-tree-sitter/debug/tree-sitter.wasm +0 -0
  163. package/packages/permission-system/node_modules/web-tree-sitter/tree-sitter.wasm +0 -0
  164. package/packages/permission-system/package.json +2 -2
  165. package/packages/permission-system/src/bash/matcher.ts +54 -51
  166. package/packages/permission-system/src/bash/parser.ts +40 -40
  167. package/packages/permission-system/src/config-paths.ts +23 -23
  168. package/packages/permission-system/src/detect-preset-mode.ts +61 -61
  169. package/packages/permission-system/src/expand-home.ts +12 -12
  170. package/packages/permission-system/src/forwarding/forwarder.ts +224 -224
  171. package/packages/permission-system/src/forwarding/subagent-registry.ts +61 -61
  172. package/packages/permission-system/src/gates/path-utils.ts +66 -66
  173. package/packages/permission-system/src/gates/pipeline.ts +151 -155
  174. package/packages/permission-system/src/handlers/before-agent-start.ts +86 -65
  175. package/packages/permission-system/src/handlers/skill-input.ts +1 -1
  176. package/packages/permission-system/src/handlers/tool-call-gate.ts +204 -199
  177. package/packages/permission-system/src/mode-api.ts +44 -44
  178. package/packages/permission-system/src/permission-evaluator.ts +233 -216
  179. package/packages/permission-system/src/permission-session.ts +62 -62
  180. package/packages/permission-system/src/policy-loader.ts +211 -211
  181. package/packages/permission-system/src/sanitizers/skill-prompt.ts +99 -99
  182. package/packages/permission-system/src/sanitizers/system-prompt.ts +221 -221
  183. package/packages/permission-system/src/service.ts +66 -66
  184. package/packages/permission-system/src/session-approvals.ts +4 -1
  185. package/packages/permission-system/src/types.ts +80 -80
  186. package/packages/permission-system/src/ui/approval-summary.ts +43 -43
  187. package/packages/permission-system/src/ui/config-modal.ts +36 -36
  188. package/packages/permission-system/src/ui/permission-dialog.ts +52 -52
  189. package/packages/permission-system/src/wildcard-matcher.ts +81 -81
  190. package/packages/permission-system/src/yaml-frontmatter.ts +84 -84
  191. package/packages/permission-system/src/yolo/runtime-api.ts +49 -49
  192. package/packages/permission-system/tsconfig.json +13 -13
  193. package/packages/permission-system/vitest.config.ts +8 -8
  194. package/packages/question/package.json +1 -1
  195. package/packages/question/src/question-ui.ts +5 -1
  196. package/packages/question/src/register-tool.ts +1 -4
  197. package/packages/session-title/extensions/index.ts +137 -137
  198. package/packages/session-title/package.json +3 -3
  199. package/packages/session-title/src/build-title-prompt.ts +16 -16
  200. package/packages/session-title/src/extract-title-context.ts +55 -55
  201. package/packages/session-title/src/fast-rules.ts +48 -48
  202. package/packages/session-title/src/load-settings.ts +70 -70
  203. package/packages/session-title/src/normalize-title.ts +20 -20
  204. package/packages/session-title/src/parse-title-response.ts +6 -6
  205. package/packages/session-title/src/resolve-title-model.ts +33 -33
  206. package/packages/session-title/src/schedule-title-job.ts +53 -53
  207. package/packages/session-title/src/should-schedule.ts +30 -30
  208. package/packages/session-title/src/title-agent.ts +60 -60
  209. package/packages/session-title/src/truncate-input.ts +10 -10
  210. package/packages/session-title/src/types.ts +29 -29
  211. package/packages/session-title/tsconfig.json +13 -13
  212. package/packages/session-title/vitest.config.ts +8 -8
  213. package/packages/subagents/agents/planner.md +46 -43
  214. package/packages/subagents/agents/scout.md +40 -40
  215. package/packages/subagents/agents/title.md +13 -13
  216. package/packages/subagents/agents/worker.md +36 -36
  217. package/packages/subagents/extensions/index.ts +164 -164
  218. package/packages/subagents/package.json +1 -1
  219. package/packages/subagents/skills/subagents/SKILL.md +86 -80
  220. package/packages/subagents/src/agents.ts +166 -166
  221. package/packages/subagents/src/async/job-tracker.ts +71 -71
  222. package/packages/subagents/src/async/spawn-async.ts +220 -220
  223. package/packages/subagents/src/async/storage.ts +57 -57
  224. package/packages/subagents/src/env.ts +4 -4
  225. package/packages/subagents/src/execute-subagent.ts +285 -285
  226. package/packages/subagents/src/progress.ts +187 -187
  227. package/packages/subagents/src/render-animation.ts +40 -40
  228. package/packages/subagents/src/render.ts +428 -428
  229. package/packages/subagents/src/rpc/channels.ts +21 -21
  230. package/packages/subagents/src/rpc/client.ts +144 -144
  231. package/packages/subagents/src/rpc/server.ts +11 -11
  232. package/packages/subagents/src/run-agent.ts +313 -313
  233. package/packages/subagents/src/runtime.ts +102 -102
  234. package/packages/subagents/src/schema.ts +62 -62
  235. package/packages/subagents/src/spawn.ts +104 -104
  236. package/packages/subagents/src/types.ts +92 -92
  237. package/packages/subagents/src/utils.ts +100 -100
  238. package/packages/subagents/src/wait.ts +159 -159
  239. package/packages/subagents/tsconfig.json +13 -13
  240. package/packages/subagents/vitest.config.ts +8 -8
  241. package/packages/todoist/extensions/index.ts +163 -0
  242. package/packages/todoist/package.json +34 -0
  243. package/packages/todoist/src/events.ts +7 -0
  244. package/packages/todoist/src/silent-render.ts +8 -0
  245. package/packages/todoist/src/state.ts +147 -0
  246. package/packages/todoist/src/tools.ts +175 -0
  247. package/packages/todoist/src/types.ts +34 -0
  248. package/packages/todoist/src/widget.ts +109 -0
  249. package/packages/todoist/tsconfig.json +13 -0
  250. package/packages/todoist/vitest.config.ts +8 -0
  251. package/packages/ui-enhancements/package.json +1 -1
  252. package/packages/ui-enhancements/src/chrome/agent-mode-badge.ts +60 -60
  253. package/packages/ui-enhancements/src/chrome/border-status.ts +14 -1
  254. package/packages/ui-enhancements/src/chrome/resize-recovery.ts +63 -0
  255. package/packages/websearch/package.json +1 -1
  256. package/scripts/sync-pi-manifest.mjs +1 -1
  257. package/packages/permission-system/node_modules/web-tree-sitter/lib/tree-sitter.cjs +0 -2988
  258. package/packages/permission-system/node_modules/web-tree-sitter/lib/tree-sitter.wasm +0 -0
  259. package/packages/permission-system/node_modules/web-tree-sitter/lib/tree-sitter.wasm.map +0 -1
@@ -1,84 +1,84 @@
1
- export function extractFrontmatter(content: string): {
2
- frontmatter: string;
3
- body: string;
4
- } | null {
5
- const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);
6
- if (!match) return null;
7
- return {
8
- frontmatter: match[1],
9
- body: content.slice(match[0].length),
10
- };
11
- }
12
-
13
- export function parseSimpleYamlMap(yaml: string): Record<string, unknown> {
14
- const result: Record<string, unknown> = {};
15
- const lines = yaml.split(/\r?\n/);
16
- let currentKey: string | null = null;
17
- let currentIndent = 0;
18
- const nested: Record<string, Record<string, unknown>> = {};
19
-
20
- for (const rawLine of lines) {
21
- if (!rawLine.trim() || rawLine.trim().startsWith("#")) continue;
22
-
23
- const indent = rawLine.search(/\S/);
24
- const trimmed = rawLine.trim();
25
-
26
- if (indent === 0) {
27
- const colon = trimmed.indexOf(":");
28
- if (colon === -1) continue;
29
- const key = trimmed.slice(0, colon).trim();
30
- const value = trimmed.slice(colon + 1).trim();
31
- currentKey = key;
32
- currentIndent = 0;
33
- if (value) {
34
- result[key] = parseScalar(value);
35
- } else {
36
- nested[key] = {};
37
- result[key] = nested[key];
38
- }
39
- continue;
40
- }
41
-
42
- if (currentKey && indent > currentIndent) {
43
- const colon = trimmed.indexOf(":");
44
- if (colon === -1) continue;
45
- const key = trimmed.slice(0, colon).trim();
46
- const value = trimmed.slice(colon + 1).trim();
47
- const bucket = nested[currentKey] ?? {};
48
- if (!nested[currentKey]) nested[currentKey] = bucket;
49
- bucket[key] = parseScalar(value);
50
- }
51
- }
52
-
53
- return result;
54
- }
55
-
56
- function parseScalar(value: string): unknown {
57
- if (
58
- (value.startsWith('"') && value.endsWith('"')) ||
59
- (value.startsWith("'") && value.endsWith("'"))
60
- ) {
61
- return value.slice(1, -1);
62
- }
63
- if (value === "true") return true;
64
- if (value === "false") return false;
65
- if (value === "null") return null;
66
- return value;
67
- }
68
-
69
- export function parseAgentFrontmatterPermission(
70
- content: string,
71
- ): Record<string, unknown> | null {
72
- const extracted = extractFrontmatter(content);
73
- if (!extracted) return null;
74
- const map = parseSimpleYamlMap(extracted.frontmatter);
75
- const permission = map.permission;
76
- if (
77
- !permission ||
78
- typeof permission !== "object" ||
79
- Array.isArray(permission)
80
- ) {
81
- return null;
82
- }
83
- return permission as Record<string, unknown>;
84
- }
1
+ export function extractFrontmatter(content: string): {
2
+ frontmatter: string;
3
+ body: string;
4
+ } | null {
5
+ const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(content);
6
+ if (!match) return null;
7
+ return {
8
+ frontmatter: match[1],
9
+ body: content.slice(match[0].length),
10
+ };
11
+ }
12
+
13
+ export function parseSimpleYamlMap(yaml: string): Record<string, unknown> {
14
+ const result: Record<string, unknown> = {};
15
+ const lines = yaml.split(/\r?\n/);
16
+ let currentKey: string | null = null;
17
+ let currentIndent = 0;
18
+ const nested: Record<string, Record<string, unknown>> = {};
19
+
20
+ for (const rawLine of lines) {
21
+ if (!rawLine.trim() || rawLine.trim().startsWith("#")) continue;
22
+
23
+ const indent = rawLine.search(/\S/);
24
+ const trimmed = rawLine.trim();
25
+
26
+ if (indent === 0) {
27
+ const colon = trimmed.indexOf(":");
28
+ if (colon === -1) continue;
29
+ const key = trimmed.slice(0, colon).trim();
30
+ const value = trimmed.slice(colon + 1).trim();
31
+ currentKey = key;
32
+ currentIndent = 0;
33
+ if (value) {
34
+ result[key] = parseScalar(value);
35
+ } else {
36
+ nested[key] = {};
37
+ result[key] = nested[key];
38
+ }
39
+ continue;
40
+ }
41
+
42
+ if (currentKey && indent > currentIndent) {
43
+ const colon = trimmed.indexOf(":");
44
+ if (colon === -1) continue;
45
+ const key = trimmed.slice(0, colon).trim();
46
+ const value = trimmed.slice(colon + 1).trim();
47
+ const bucket = nested[currentKey] ?? {};
48
+ if (!nested[currentKey]) nested[currentKey] = bucket;
49
+ bucket[key] = parseScalar(value);
50
+ }
51
+ }
52
+
53
+ return result;
54
+ }
55
+
56
+ function parseScalar(value: string): unknown {
57
+ if (
58
+ (value.startsWith('"') && value.endsWith('"')) ||
59
+ (value.startsWith("'") && value.endsWith("'"))
60
+ ) {
61
+ return value.slice(1, -1);
62
+ }
63
+ if (value === "true") return true;
64
+ if (value === "false") return false;
65
+ if (value === "null") return null;
66
+ return value;
67
+ }
68
+
69
+ export function parseAgentFrontmatterPermission(
70
+ content: string,
71
+ ): Record<string, unknown> | null {
72
+ const extracted = extractFrontmatter(content);
73
+ if (!extracted) return null;
74
+ const map = parseSimpleYamlMap(extracted.frontmatter);
75
+ const permission = map.permission;
76
+ if (
77
+ !permission ||
78
+ typeof permission !== "object" ||
79
+ Array.isArray(permission)
80
+ ) {
81
+ return null;
82
+ }
83
+ return permission as Record<string, unknown>;
84
+ }
@@ -1,49 +1,49 @@
1
- import type { ExtensionConfig } from "../types.ts";
2
-
3
- export interface YoloRuntimeApi {
4
- getYoloMode(): boolean;
5
- setYoloMode(
6
- enabled: boolean,
7
- options?: { persist?: boolean },
8
- ): { error?: string };
9
- toggleYoloMode(options?: { persist?: boolean; source?: string }): {
10
- error?: string;
11
- };
12
- }
13
-
14
- type PermissionSystemGlobal = typeof globalThis & {
15
- __piPermissionSystem?: YoloRuntimeApi;
16
- };
17
-
18
- export function installYoloRuntimeApi(
19
- getConfig: () => ExtensionConfig,
20
- setConfig: (config: ExtensionConfig) => void,
21
- onConfigChange?: (config: ExtensionConfig) => void,
22
- ): YoloRuntimeApi {
23
- const applyConfig = (next: ExtensionConfig, persist: boolean) => {
24
- if (persist) {
25
- setConfig(next);
26
- } else {
27
- Object.assign(getConfig(), next);
28
- }
29
- onConfigChange?.(getConfig());
30
- };
31
-
32
- const api: YoloRuntimeApi = {
33
- getYoloMode() {
34
- return getConfig().yoloMode === true;
35
- },
36
- setYoloMode(enabled, options = {}) {
37
- const next = { ...getConfig(), yoloMode: enabled };
38
- applyConfig(next, options.persist !== false);
39
- return {};
40
- },
41
- toggleYoloMode(options = {}) {
42
- const enabled = !(getConfig().yoloMode === true);
43
- return api.setYoloMode(enabled, options);
44
- },
45
- };
46
-
47
- (globalThis as PermissionSystemGlobal).__piPermissionSystem = api;
48
- return api;
49
- }
1
+ import type { ExtensionConfig } from "../types.ts";
2
+
3
+ export interface YoloRuntimeApi {
4
+ getYoloMode(): boolean;
5
+ setYoloMode(
6
+ enabled: boolean,
7
+ options?: { persist?: boolean },
8
+ ): { error?: string };
9
+ toggleYoloMode(options?: { persist?: boolean; source?: string }): {
10
+ error?: string;
11
+ };
12
+ }
13
+
14
+ type PermissionSystemGlobal = typeof globalThis & {
15
+ __piPermissionSystem?: YoloRuntimeApi;
16
+ };
17
+
18
+ export function installYoloRuntimeApi(
19
+ getConfig: () => ExtensionConfig,
20
+ setConfig: (config: ExtensionConfig) => void,
21
+ onConfigChange?: (config: ExtensionConfig) => void,
22
+ ): YoloRuntimeApi {
23
+ const applyConfig = (next: ExtensionConfig, persist: boolean) => {
24
+ if (persist) {
25
+ setConfig(next);
26
+ } else {
27
+ Object.assign(getConfig(), next);
28
+ }
29
+ onConfigChange?.(getConfig());
30
+ };
31
+
32
+ const api: YoloRuntimeApi = {
33
+ getYoloMode() {
34
+ return getConfig().yoloMode === true;
35
+ },
36
+ setYoloMode(enabled, options = {}) {
37
+ const next = { ...getConfig(), yoloMode: enabled };
38
+ applyConfig(next, options.persist !== false);
39
+ return {};
40
+ },
41
+ toggleYoloMode(options = {}) {
42
+ const enabled = !(getConfig().yoloMode === true);
43
+ return api.setYoloMode(enabled, options);
44
+ },
45
+ };
46
+
47
+ (globalThis as PermissionSystemGlobal).__piPermissionSystem = api;
48
+ return api;
49
+ }
@@ -1,13 +1,13 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "allowImportingTsExtensions": true
5
- },
6
- "include": [
7
- "extensions/**/*.ts",
8
- "src/**/*.ts",
9
- "tests/**/*.ts",
10
- "vitest.config.ts"
11
- ],
12
- "exclude": ["node_modules"]
13
- }
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "allowImportingTsExtensions": true
5
+ },
6
+ "include": [
7
+ "extensions/**/*.ts",
8
+ "src/**/*.ts",
9
+ "tests/**/*.ts",
10
+ "vitest.config.ts"
11
+ ],
12
+ "exclude": ["node_modules"]
13
+ }
@@ -1,8 +1,8 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- environment: "node",
6
- include: ["tests/**/*.test.ts"],
7
- },
8
- });
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["tests/**/*.test.ts"],
7
+ },
8
+ });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitos-pizza/question",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Structured ask-user question tool for Vito's Pizzeria Pi distribution",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,6 +26,7 @@ export async function runQuestionUi(
26
26
  return ui.custom<QuestionUiResult | null>((tui, theme, _kb, done) => {
27
27
  let optionIndex = 0;
28
28
  let cachedLines: string[] | undefined;
29
+ let cachedWidth: number | undefined;
29
30
  const customInput = new Input();
30
31
 
31
32
  customInput.onSubmit = (value) => {
@@ -41,6 +42,7 @@ export async function runQuestionUi(
41
42
 
42
43
  function refresh() {
43
44
  cachedLines = undefined;
45
+ cachedWidth = undefined;
44
46
  tui.requestRender();
45
47
  }
46
48
 
@@ -161,7 +163,7 @@ export async function runQuestionUi(
161
163
  }
162
164
 
163
165
  function render(width: number): string[] {
164
- if (cachedLines) return cachedLines;
166
+ if (cachedLines && cachedWidth === width) return cachedLines;
165
167
 
166
168
  const lines: string[] = [];
167
169
  const renderWidth = Math.max(1, width);
@@ -224,6 +226,7 @@ export async function runQuestionUi(
224
226
  lines.push(theme.fg("accent", "─".repeat(renderWidth)));
225
227
 
226
228
  cachedLines = lines;
229
+ cachedWidth = width;
227
230
  return lines;
228
231
  }
229
232
 
@@ -231,6 +234,7 @@ export async function runQuestionUi(
231
234
  render,
232
235
  invalidate: () => {
233
236
  cachedLines = undefined;
237
+ cachedWidth = undefined;
234
238
  },
235
239
  handleInput,
236
240
  };
@@ -8,10 +8,7 @@ import { Type } from "typebox";
8
8
  import { forwardQuestionPrompt } from "./forwarding/forwarder.ts";
9
9
  import { isSubagentChild, resolveParentSessionId } from "./parent-session.ts";
10
10
  import { runQuestionUi } from "./question-ui.ts";
11
- import type {
12
- QuestionDetails,
13
- QuestionParams,
14
- } from "./types.ts";
11
+ import type { QuestionDetails, QuestionParams } from "./types.ts";
15
12
 
16
13
  const OptionSchema = Type.Object({
17
14
  label: Type.String({ description: "Display label for the option" }),
@@ -1,137 +1,137 @@
1
- /**
2
- * @vitos-pizza/session-title — async session auto-naming for Vito's Pizzeria.
3
- */
4
-
5
- import type {
6
- AgentEndEvent,
7
- ExtensionAPI,
8
- ExtensionContext,
9
- } from "@earendil-works/pi-coding-agent";
10
- import { extractTitleContext } from "../src/extract-title-context.ts";
11
- import { loadAutoTitleSettings } from "../src/load-settings.ts";
12
- import { resolveTitleModelRef } from "../src/resolve-title-model.ts";
13
- import { scheduleTitleJob } from "../src/schedule-title-job.ts";
14
- import { decideSchedule } from "../src/should-schedule.ts";
15
- import { createTitleAgent } from "../src/title-agent.ts";
16
- import type { AutoTitleSettings } from "../src/types.ts";
17
-
18
- type EventHandler = (event: unknown, ctx: ExtensionContext) => void;
19
-
20
- export interface SessionTitleDeps {
21
- loadSettings?: (cwd: string) => AutoTitleSettings;
22
- createAgent?: typeof createTitleAgent;
23
- }
24
-
25
- export interface SessionTitleTestHarness {
26
- handlers: {
27
- agent_end?: EventHandler;
28
- session_start?: EventHandler;
29
- session_shutdown?: EventHandler;
30
- };
31
- }
32
-
33
- function tryScheduleFromAgentEnd(
34
- event: AgentEndEvent,
35
- pi: ExtensionAPI,
36
- ctx: ExtensionContext,
37
- state: {
38
- titleSettled: boolean;
39
- jobState: { inFlight: boolean };
40
- abortController: AbortController;
41
- settings: AutoTitleSettings;
42
- },
43
- deps: SessionTitleDeps,
44
- ): void {
45
- if (state.titleSettled || !state.settings.enabled) return;
46
-
47
- const titleContext = extractTitleContext(event.messages);
48
- if (!titleContext) return;
49
-
50
- const decision = decideSchedule(titleContext.userMessage, {
51
- hasSessionName: Boolean(pi.getSessionName()),
52
- inFlight: state.jobState.inFlight,
53
- fastRules: state.settings.fastRules,
54
- minCharsForLlm: state.settings.minCharsForLlm,
55
- });
56
-
57
- if (decision !== "schedule") return;
58
-
59
- const agentFactory = deps.createAgent ?? createTitleAgent;
60
- const agent = agentFactory({
61
- events: pi.events,
62
- resolveModelRef: () => resolveTitleModelRef(ctx, state.settings.model),
63
- settings: state.settings,
64
- });
65
-
66
- scheduleTitleJob(
67
- {
68
- agent,
69
- context: titleContext,
70
- signal: state.abortController.signal,
71
- sessionName: {
72
- getSessionName: () => pi.getSessionName(),
73
- setSessionName: (name) => pi.setSessionName(name),
74
- },
75
- maxTitleLength: state.settings.maxTitleLength,
76
- onSettled: () => {
77
- state.titleSettled = true;
78
- },
79
- },
80
- state.jobState,
81
- );
82
- }
83
-
84
- export function registerSessionTitle(
85
- pi: ExtensionAPI,
86
- deps: SessionTitleDeps = {},
87
- ): SessionTitleTestHarness {
88
- const handlers: SessionTitleTestHarness["handlers"] = {};
89
- let titleSettled = false;
90
- const jobState = { inFlight: false };
91
- let abortController = new AbortController();
92
- let settings = loadAutoTitleSettings(process.cwd());
93
-
94
- const getState = () => ({
95
- titleSettled,
96
- jobState,
97
- abortController,
98
- settings,
99
- });
100
-
101
- handlers.agent_end = (event, ctx) => {
102
- settings = (deps.loadSettings ?? loadAutoTitleSettings)(ctx.cwd);
103
- if (pi.getSessionName()) {
104
- titleSettled = true;
105
- return;
106
- }
107
-
108
- tryScheduleFromAgentEnd(event as AgentEndEvent, pi, ctx, getState(), deps);
109
- };
110
-
111
- pi.on("agent_end", handlers.agent_end);
112
-
113
- handlers.session_start = (_event, ctx) => {
114
- abortController.abort();
115
- abortController = new AbortController();
116
- titleSettled = false;
117
- jobState.inFlight = false;
118
- settings = (deps.loadSettings ?? loadAutoTitleSettings)(ctx.cwd);
119
- if (pi.getSessionName()) {
120
- titleSettled = true;
121
- }
122
- };
123
-
124
- pi.on("session_start", handlers.session_start);
125
-
126
- handlers.session_shutdown = () => {
127
- abortController.abort();
128
- };
129
-
130
- pi.on("session_shutdown", handlers.session_shutdown);
131
-
132
- return { handlers };
133
- }
134
-
135
- export default function sessionTitleExtension(pi: ExtensionAPI) {
136
- registerSessionTitle(pi);
137
- }
1
+ /**
2
+ * @vitos-pizza/session-title — async session auto-naming for Vito's Pizzeria.
3
+ */
4
+
5
+ import type {
6
+ AgentEndEvent,
7
+ ExtensionAPI,
8
+ ExtensionContext,
9
+ } from "@earendil-works/pi-coding-agent";
10
+ import { extractTitleContext } from "../src/extract-title-context.ts";
11
+ import { loadAutoTitleSettings } from "../src/load-settings.ts";
12
+ import { resolveTitleModelRef } from "../src/resolve-title-model.ts";
13
+ import { scheduleTitleJob } from "../src/schedule-title-job.ts";
14
+ import { decideSchedule } from "../src/should-schedule.ts";
15
+ import { createTitleAgent } from "../src/title-agent.ts";
16
+ import type { AutoTitleSettings } from "../src/types.ts";
17
+
18
+ type EventHandler = (event: unknown, ctx: ExtensionContext) => void;
19
+
20
+ export interface SessionTitleDeps {
21
+ loadSettings?: (cwd: string) => AutoTitleSettings;
22
+ createAgent?: typeof createTitleAgent;
23
+ }
24
+
25
+ export interface SessionTitleTestHarness {
26
+ handlers: {
27
+ agent_end?: EventHandler;
28
+ session_start?: EventHandler;
29
+ session_shutdown?: EventHandler;
30
+ };
31
+ }
32
+
33
+ function tryScheduleFromAgentEnd(
34
+ event: AgentEndEvent,
35
+ pi: ExtensionAPI,
36
+ ctx: ExtensionContext,
37
+ state: {
38
+ titleSettled: boolean;
39
+ jobState: { inFlight: boolean };
40
+ abortController: AbortController;
41
+ settings: AutoTitleSettings;
42
+ },
43
+ deps: SessionTitleDeps,
44
+ ): void {
45
+ if (state.titleSettled || !state.settings.enabled) return;
46
+
47
+ const titleContext = extractTitleContext(event.messages);
48
+ if (!titleContext) return;
49
+
50
+ const decision = decideSchedule(titleContext.userMessage, {
51
+ hasSessionName: Boolean(pi.getSessionName()),
52
+ inFlight: state.jobState.inFlight,
53
+ fastRules: state.settings.fastRules,
54
+ minCharsForLlm: state.settings.minCharsForLlm,
55
+ });
56
+
57
+ if (decision !== "schedule") return;
58
+
59
+ const agentFactory = deps.createAgent ?? createTitleAgent;
60
+ const agent = agentFactory({
61
+ events: pi.events,
62
+ resolveModelRef: () => resolveTitleModelRef(ctx, state.settings.model),
63
+ settings: state.settings,
64
+ });
65
+
66
+ scheduleTitleJob(
67
+ {
68
+ agent,
69
+ context: titleContext,
70
+ signal: state.abortController.signal,
71
+ sessionName: {
72
+ getSessionName: () => pi.getSessionName(),
73
+ setSessionName: (name) => pi.setSessionName(name),
74
+ },
75
+ maxTitleLength: state.settings.maxTitleLength,
76
+ onSettled: () => {
77
+ state.titleSettled = true;
78
+ },
79
+ },
80
+ state.jobState,
81
+ );
82
+ }
83
+
84
+ export function registerSessionTitle(
85
+ pi: ExtensionAPI,
86
+ deps: SessionTitleDeps = {},
87
+ ): SessionTitleTestHarness {
88
+ const handlers: SessionTitleTestHarness["handlers"] = {};
89
+ let titleSettled = false;
90
+ const jobState = { inFlight: false };
91
+ let abortController = new AbortController();
92
+ let settings = loadAutoTitleSettings(process.cwd());
93
+
94
+ const getState = () => ({
95
+ titleSettled,
96
+ jobState,
97
+ abortController,
98
+ settings,
99
+ });
100
+
101
+ handlers.agent_end = (event, ctx) => {
102
+ settings = (deps.loadSettings ?? loadAutoTitleSettings)(ctx.cwd);
103
+ if (pi.getSessionName()) {
104
+ titleSettled = true;
105
+ return;
106
+ }
107
+
108
+ tryScheduleFromAgentEnd(event as AgentEndEvent, pi, ctx, getState(), deps);
109
+ };
110
+
111
+ pi.on("agent_end", handlers.agent_end);
112
+
113
+ handlers.session_start = (_event, ctx) => {
114
+ abortController.abort();
115
+ abortController = new AbortController();
116
+ titleSettled = false;
117
+ jobState.inFlight = false;
118
+ settings = (deps.loadSettings ?? loadAutoTitleSettings)(ctx.cwd);
119
+ if (pi.getSessionName()) {
120
+ titleSettled = true;
121
+ }
122
+ };
123
+
124
+ pi.on("session_start", handlers.session_start);
125
+
126
+ handlers.session_shutdown = () => {
127
+ abortController.abort();
128
+ };
129
+
130
+ pi.on("session_shutdown", handlers.session_shutdown);
131
+
132
+ return { handlers };
133
+ }
134
+
135
+ export default function sessionTitleExtension(pi: ExtensionAPI) {
136
+ registerSessionTitle(pi);
137
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitos-pizza/session-title",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
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.1.0"
14
+ "@vitos-pizza/subagents": "0.2.0"
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.1.0",
33
+ "@vitos-pizza/subagents": "0.2.0",
34
34
  "typebox": "*",
35
35
  "vitest": "^3.2.4"
36
36
  }