@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,61 +1,61 @@
1
- const SUBAGENT_SESSION_REGISTRY_KEY = Symbol.for(
2
- "@vitos-pizza/permission-system:subagent-registry",
3
- );
4
-
5
- export interface SubagentSessionInfo {
6
- parentSessionId?: string;
7
- }
8
-
9
- export class SubagentSessionRegistry {
10
- private readonly sessions = new Map<string, SubagentSessionInfo>();
11
-
12
- register(sessionId: string, info: SubagentSessionInfo): void {
13
- this.sessions.set(sessionId, info);
14
- }
15
-
16
- unregister(sessionId: string): void {
17
- this.sessions.delete(sessionId);
18
- }
19
-
20
- get(sessionId: string): SubagentSessionInfo | undefined {
21
- return this.sessions.get(sessionId);
22
- }
23
- }
24
-
25
- export function getSubagentSessionRegistry(): SubagentSessionRegistry {
26
- const store = globalThis as Record<symbol, unknown>;
27
- const existing = store[SUBAGENT_SESSION_REGISTRY_KEY] as
28
- | SubagentSessionRegistry
29
- | undefined;
30
- if (existing) return existing;
31
- const registry = new SubagentSessionRegistry();
32
- store[SUBAGENT_SESSION_REGISTRY_KEY] = registry;
33
- return registry;
34
- }
35
-
36
- export const SUBAGENT_CHILD_SESSION_CREATED = "subagents:child:session-created";
37
- export const SUBAGENT_CHILD_DISPOSED = "subagents:child:disposed";
38
-
39
- interface LifecycleEventBus {
40
- on(channel: string, handler: (data: unknown) => void): () => void;
41
- }
42
-
43
- export function subscribeSubagentLifecycle(
44
- events: LifecycleEventBus,
45
- registry: SubagentSessionRegistry,
46
- ): () => void {
47
- const unsubCreated = events.on(SUBAGENT_CHILD_SESSION_CREATED, (data) => {
48
- const event = data as { sessionId: string; parentSessionId?: string };
49
- registry.register(event.sessionId, {
50
- parentSessionId: event.parentSessionId,
51
- });
52
- });
53
- const unsubDisposed = events.on(SUBAGENT_CHILD_DISPOSED, (data) => {
54
- const event = data as { sessionId: string };
55
- registry.unregister(event.sessionId);
56
- });
57
- return () => {
58
- unsubCreated();
59
- unsubDisposed();
60
- };
61
- }
1
+ const SUBAGENT_SESSION_REGISTRY_KEY = Symbol.for(
2
+ "@vitos-pizza/permission-system:subagent-registry",
3
+ );
4
+
5
+ export interface SubagentSessionInfo {
6
+ parentSessionId?: string;
7
+ }
8
+
9
+ export class SubagentSessionRegistry {
10
+ private readonly sessions = new Map<string, SubagentSessionInfo>();
11
+
12
+ register(sessionId: string, info: SubagentSessionInfo): void {
13
+ this.sessions.set(sessionId, info);
14
+ }
15
+
16
+ unregister(sessionId: string): void {
17
+ this.sessions.delete(sessionId);
18
+ }
19
+
20
+ get(sessionId: string): SubagentSessionInfo | undefined {
21
+ return this.sessions.get(sessionId);
22
+ }
23
+ }
24
+
25
+ export function getSubagentSessionRegistry(): SubagentSessionRegistry {
26
+ const store = globalThis as Record<symbol, unknown>;
27
+ const existing = store[SUBAGENT_SESSION_REGISTRY_KEY] as
28
+ | SubagentSessionRegistry
29
+ | undefined;
30
+ if (existing) return existing;
31
+ const registry = new SubagentSessionRegistry();
32
+ store[SUBAGENT_SESSION_REGISTRY_KEY] = registry;
33
+ return registry;
34
+ }
35
+
36
+ export const SUBAGENT_CHILD_SESSION_CREATED = "subagents:child:session-created";
37
+ export const SUBAGENT_CHILD_DISPOSED = "subagents:child:disposed";
38
+
39
+ interface LifecycleEventBus {
40
+ on(channel: string, handler: (data: unknown) => void): () => void;
41
+ }
42
+
43
+ export function subscribeSubagentLifecycle(
44
+ events: LifecycleEventBus,
45
+ registry: SubagentSessionRegistry,
46
+ ): () => void {
47
+ const unsubCreated = events.on(SUBAGENT_CHILD_SESSION_CREATED, (data) => {
48
+ const event = data as { sessionId: string; parentSessionId?: string };
49
+ registry.register(event.sessionId, {
50
+ parentSessionId: event.parentSessionId,
51
+ });
52
+ });
53
+ const unsubDisposed = events.on(SUBAGENT_CHILD_DISPOSED, (data) => {
54
+ const event = data as { sessionId: string };
55
+ registry.unregister(event.sessionId);
56
+ });
57
+ return () => {
58
+ unsubCreated();
59
+ unsubDisposed();
60
+ };
61
+ }
@@ -1,66 +1,66 @@
1
- import { existsSync } from "node:fs";
2
- import { dirname, isAbsolute, relative, resolve } from "node:path";
3
- import { expandHomePath } from "../expand-home.ts";
4
-
5
- export function normalizePathValue(pathValue: string, cwd: string): string {
6
- const expanded = expandHomePath(pathValue.trim());
7
- if (!expanded) return expanded;
8
- return isAbsolute(expanded) ? resolve(expanded) : resolve(cwd, expanded);
9
- }
10
-
11
- export function findProjectRoot(cwd: string): string {
12
- let dir = resolve(cwd);
13
- while (true) {
14
- if (existsSync(resolve(dir, ".git"))) {
15
- return dir;
16
- }
17
- const parent = dirname(dir);
18
- if (parent === dir) break;
19
- dir = parent;
20
- }
21
- return resolve(cwd);
22
- }
23
-
24
- export function isPathWithinRoot(normalizedPath: string, root: string): boolean {
25
- const resolvedRoot = resolve(root);
26
- const resolvedPath = resolve(normalizedPath);
27
- if (resolvedPath === resolvedRoot) return true;
28
- const rel = relative(resolvedRoot, resolvedPath);
29
- return !rel.startsWith("..") && !isAbsolute(rel);
30
- }
31
-
32
- export function isExternalPath(pathValue: string, cwd: string): boolean {
33
- const normalized = normalizePathValue(pathValue, cwd);
34
- const projectRoot = findProjectRoot(cwd);
35
- return !isPathWithinRoot(normalized, projectRoot);
36
- }
37
- export function extractPathFromToolInput(
38
- toolName: string,
39
- input: Record<string, unknown>,
40
- ): string | null {
41
- if (typeof input.path === "string") return input.path;
42
- if (toolName === "bash" && typeof input.command === "string") {
43
- return input.command;
44
- }
45
- if (toolName === "mcp") {
46
- const args = input.arguments;
47
- if (
48
- typeof args === "object" &&
49
- args !== null &&
50
- typeof (args as { path?: string }).path === "string"
51
- ) {
52
- return (args as { path: string }).path;
53
- }
54
- }
55
- return null;
56
- }
57
-
58
- export function extractMcpTarget(
59
- input: Record<string, unknown>,
60
- ): string | null {
61
- if (typeof input.server === "string" && typeof input.tool === "string") {
62
- return `${input.server}/${input.tool}`;
63
- }
64
- if (typeof input.tool === "string") return input.tool;
65
- return null;
66
- }
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, isAbsolute, relative, resolve } from "node:path";
3
+ import { expandHomePath } from "../expand-home.ts";
4
+
5
+ export function normalizePathValue(pathValue: string, cwd: string): string {
6
+ const expanded = expandHomePath(pathValue.trim());
7
+ if (!expanded) return expanded;
8
+ return isAbsolute(expanded) ? resolve(expanded) : resolve(cwd, expanded);
9
+ }
10
+
11
+ export function findProjectRoot(cwd: string): string {
12
+ let dir = resolve(cwd);
13
+ while (true) {
14
+ if (existsSync(resolve(dir, ".git"))) {
15
+ return dir;
16
+ }
17
+ const parent = dirname(dir);
18
+ if (parent === dir) break;
19
+ dir = parent;
20
+ }
21
+ return resolve(cwd);
22
+ }
23
+
24
+ export function isPathWithinRoot(normalizedPath: string, root: string): boolean {
25
+ const resolvedRoot = resolve(root);
26
+ const resolvedPath = resolve(normalizedPath);
27
+ if (resolvedPath === resolvedRoot) return true;
28
+ const rel = relative(resolvedRoot, resolvedPath);
29
+ return !rel.startsWith("..") && !isAbsolute(rel);
30
+ }
31
+
32
+ export function isExternalPath(pathValue: string, cwd: string): boolean {
33
+ const normalized = normalizePathValue(pathValue, cwd);
34
+ const projectRoot = findProjectRoot(cwd);
35
+ return !isPathWithinRoot(normalized, projectRoot);
36
+ }
37
+ export function extractPathFromToolInput(
38
+ toolName: string,
39
+ input: Record<string, unknown>,
40
+ ): string | null {
41
+ if (typeof input.path === "string") return input.path;
42
+ if (toolName === "bash" && typeof input.command === "string") {
43
+ return input.command;
44
+ }
45
+ if (toolName === "mcp") {
46
+ const args = input.arguments;
47
+ if (
48
+ typeof args === "object" &&
49
+ args !== null &&
50
+ typeof (args as { path?: string }).path === "string"
51
+ ) {
52
+ return (args as { path: string }).path;
53
+ }
54
+ }
55
+ return null;
56
+ }
57
+
58
+ export function extractMcpTarget(
59
+ input: Record<string, unknown>,
60
+ ): string | null {
61
+ if (typeof input.server === "string" && typeof input.tool === "string") {
62
+ return `${input.server}/${input.tool}`;
63
+ }
64
+ if (typeof input.tool === "string") return input.tool;
65
+ return null;
66
+ }
@@ -1,155 +1,151 @@
1
- import { evaluateBashCommand } from "../bash/matcher.ts";
2
- import type { PermissionEvaluator } from "../permission-evaluator.ts";
3
- import { inferSkillNameFromPath } from "../sanitizers/skill-prompt.ts";
4
- import type {
5
- FlatPermissionConfig,
6
- GateContext,
7
- PermissionCheckResult,
8
- PermissionState,
9
- } from "../types.ts";
10
- import {
11
- extractMcpTarget,
12
- extractPathFromToolInput,
13
- isExternalPath,
14
- normalizePathValue,
15
- } from "./path-utils.ts";
16
-
17
- export interface GatePipelineOptions {
18
- yoloMode?: boolean;
19
- platform?: NodeJS.Platform;
20
- skillDirs?: readonly string[];
21
- registeredTools?: ReadonlySet<string>;
22
- }
23
-
24
- export function runGatePipeline(
25
- permission: FlatPermissionConfig,
26
- evaluator: PermissionEvaluator,
27
- ctx: GateContext,
28
- options: GatePipelineOptions = {},
29
- ): PermissionCheckResult {
30
- const { toolName, input, cwd } = ctx;
31
- const evalOptions = {
32
- yoloMode: options.yoloMode,
33
- platform: options.platform,
34
- };
35
-
36
- if (options.registeredTools && !options.registeredTools.has(toolName)) {
37
- return {
38
- state: "deny",
39
- reason: `Tool "${toolName}" is not registered`,
40
- matchedPattern: "<unregistered-tool>",
41
- surface: toolName,
42
- value: toolName,
43
- origin: "builtin",
44
- };
45
- }
46
-
47
- const checks: PermissionCheckResult[] = [];
48
- const pathValue = extractPathFromToolInput(toolName, input);
49
- if (pathValue) {
50
- const normalizedPath = normalizePathValue(pathValue, cwd);
51
- checks.push(
52
- evaluator.evaluateSurface(
53
- permission,
54
- "path",
55
- normalizedPath,
56
- "project",
57
- evalOptions,
58
- ),
59
- );
60
- if (isExternalPath(pathValue, cwd)) {
61
- const externalRules = permission.external_directory;
62
- if (
63
- typeof externalRules === "object" &&
64
- externalRules !== null &&
65
- !Array.isArray(externalRules)
66
- ) {
67
- checks.push(
68
- evaluator.evaluateSurface(
69
- permission,
70
- "external_directory",
71
- normalizedPath,
72
- "project",
73
- evalOptions,
74
- ),
75
- );
76
- } else if (typeof externalRules === "string") {
77
- checks.push({
78
- state: externalRules as PermissionState,
79
- matchedPattern: "external_directory",
80
- surface: "external_directory",
81
- value: normalizedPath,
82
- origin: "project",
83
- });
84
- }
85
- }
86
- }
87
-
88
- const toolPermission = permission[toolName];
89
- if (typeof toolPermission === "string") {
90
- checks.push({
91
- state: toolPermission as PermissionState,
92
- matchedPattern: toolName,
93
- surface: toolName,
94
- value: toolName,
95
- origin: "project",
96
- });
97
- } else {
98
- checks.push(
99
- evaluator.evaluateSurface(
100
- permission,
101
- "*",
102
- toolName,
103
- "project",
104
- evalOptions,
105
- ),
106
- );
107
- }
108
-
109
- if (toolName === "bash" && typeof input.command === "string") {
110
- checks.push(
111
- evaluateBashCommand(input.command, permission, evaluator, evalOptions),
112
- );
113
- }
114
-
115
- if (toolName === "mcp") {
116
- const target = extractMcpTarget(input);
117
- if (target) {
118
- checks.push(
119
- evaluator.evaluateSurface(
120
- permission,
121
- "mcp",
122
- target,
123
- "project",
124
- evalOptions,
125
- ),
126
- );
127
- }
128
- }
129
-
130
- if (toolName === "read" && pathValue && options.skillDirs?.length) {
131
- const skillName = inferSkillNameFromPath(pathValue, options.skillDirs);
132
- if (skillName) {
133
- checks.push(
134
- evaluator.evaluateSurface(
135
- permission,
136
- "skill",
137
- skillName,
138
- "project",
139
- evalOptions,
140
- ),
141
- );
142
- }
143
- }
144
-
145
- const mostRestrictive = evaluator.pickMostRestrictive(checks);
146
- return (
147
- mostRestrictive ?? {
148
- state: "ask",
149
- matchedPattern: "*",
150
- surface: toolName,
151
- value: toolName,
152
- origin: "builtin",
153
- }
154
- );
155
- }
1
+ import { evaluateBashCommand } from "../bash/matcher.ts";
2
+ import type {
3
+ EvaluateOptions,
4
+ PermissionEvaluator,
5
+ SessionApprovals,
6
+ } from "../permission-evaluator.ts";
7
+ import { inferSkillNameFromPath } from "../sanitizers/skill-prompt.ts";
8
+ import type {
9
+ FlatPermissionConfig,
10
+ GateContext,
11
+ PermissionCheckResult,
12
+ } from "../types.ts";
13
+ import {
14
+ extractMcpTarget,
15
+ extractPathFromToolInput,
16
+ isExternalPath,
17
+ normalizePathValue,
18
+ } from "./path-utils.ts";
19
+
20
+ export interface GatePipelineOptions {
21
+ yoloMode?: boolean;
22
+ platform?: NodeJS.Platform;
23
+ skillDirs?: readonly string[];
24
+ registeredTools?: ReadonlySet<string>;
25
+ sessionApprovals?: SessionApprovals;
26
+ }
27
+
28
+ export function runGatePipeline(
29
+ permission: FlatPermissionConfig,
30
+ evaluator: PermissionEvaluator,
31
+ ctx: GateContext,
32
+ options: GatePipelineOptions = {},
33
+ ): PermissionCheckResult {
34
+ const { toolName, input, cwd } = ctx;
35
+ const evalOptions: EvaluateOptions = {
36
+ yoloMode: options.yoloMode,
37
+ platform: options.platform,
38
+ sessionApprovals: options.sessionApprovals,
39
+ };
40
+
41
+ if (options.registeredTools && !options.registeredTools.has(toolName)) {
42
+ return {
43
+ state: "deny",
44
+ reason: `Tool "${toolName}" is not registered`,
45
+ matchedPattern: "<unregistered-tool>",
46
+ surface: toolName,
47
+ value: toolName,
48
+ origin: "builtin",
49
+ };
50
+ }
51
+
52
+ const checks: PermissionCheckResult[] = [];
53
+ const pathValue = extractPathFromToolInput(toolName, input);
54
+ if (pathValue) {
55
+ const normalizedPath = normalizePathValue(pathValue, cwd);
56
+ checks.push(
57
+ evaluator.evaluateSurface(
58
+ permission,
59
+ "path",
60
+ normalizedPath,
61
+ "project",
62
+ evalOptions,
63
+ ),
64
+ );
65
+ if (isExternalPath(pathValue, cwd)) {
66
+ const externalRules = permission.external_directory;
67
+ if (externalRules !== undefined) {
68
+ checks.push(
69
+ evaluator.evaluateSurface(
70
+ permission,
71
+ "external_directory",
72
+ normalizedPath,
73
+ "project",
74
+ evalOptions,
75
+ ),
76
+ );
77
+ }
78
+ }
79
+ }
80
+
81
+ const toolPermission = permission[toolName];
82
+ if (typeof toolPermission === "string") {
83
+ // Evaluate via the tool surface so session approvals / yolo apply.
84
+ checks.push(
85
+ evaluator.evaluateSurface(
86
+ permission,
87
+ toolName,
88
+ toolName,
89
+ "project",
90
+ evalOptions,
91
+ ),
92
+ );
93
+ } else {
94
+ checks.push(
95
+ evaluator.evaluateSurface(
96
+ permission,
97
+ "*",
98
+ toolName,
99
+ "project",
100
+ evalOptions,
101
+ ),
102
+ );
103
+ }
104
+
105
+ if (toolName === "bash" && typeof input.command === "string") {
106
+ checks.push(
107
+ evaluateBashCommand(input.command, permission, evaluator, evalOptions),
108
+ );
109
+ }
110
+
111
+ if (toolName === "mcp") {
112
+ const target = extractMcpTarget(input);
113
+ if (target) {
114
+ checks.push(
115
+ evaluator.evaluateSurface(
116
+ permission,
117
+ "mcp",
118
+ target,
119
+ "project",
120
+ evalOptions,
121
+ ),
122
+ );
123
+ }
124
+ }
125
+
126
+ if (toolName === "read" && pathValue && options.skillDirs?.length) {
127
+ const skillName = inferSkillNameFromPath(pathValue, options.skillDirs);
128
+ if (skillName) {
129
+ checks.push(
130
+ evaluator.evaluateSurface(
131
+ permission,
132
+ "skill",
133
+ skillName,
134
+ "project",
135
+ evalOptions,
136
+ ),
137
+ );
138
+ }
139
+ }
140
+
141
+ const mostRestrictive = evaluator.pickMostRestrictive(checks);
142
+ return (
143
+ mostRestrictive ?? {
144
+ state: "ask",
145
+ matchedPattern: "*",
146
+ surface: toolName,
147
+ value: toolName,
148
+ origin: "builtin",
149
+ }
150
+ );
151
+ }