@astralyn/pi 0.84.3 → 0.84.5

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 (269) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/cli/args.d.ts +1 -0
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +11 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/auth-command.d.ts.map +1 -1
  7. package/dist/cli/auth-command.js +5 -4
  8. package/dist/cli/auth-command.js.map +1 -1
  9. package/dist/cli/project-trust.d.ts.map +1 -1
  10. package/dist/cli/project-trust.js +1 -4
  11. package/dist/cli/project-trust.js.map +1 -1
  12. package/dist/core/agent-session.d.ts +6 -1
  13. package/dist/core/agent-session.d.ts.map +1 -1
  14. package/dist/core/agent-session.js +7 -6
  15. package/dist/core/agent-session.js.map +1 -1
  16. package/dist/core/experimental.d.ts +4 -0
  17. package/dist/core/experimental.d.ts.map +1 -1
  18. package/dist/core/experimental.js +4 -0
  19. package/dist/core/experimental.js.map +1 -1
  20. package/dist/core/extensions/index.d.ts +1 -1
  21. package/dist/core/extensions/index.d.ts.map +1 -1
  22. package/dist/core/extensions/index.js.map +1 -1
  23. package/dist/core/extensions/runner.d.ts.map +1 -1
  24. package/dist/core/extensions/runner.js +4 -0
  25. package/dist/core/extensions/runner.js.map +1 -1
  26. package/dist/core/extensions/types.d.ts +10 -14
  27. package/dist/core/extensions/types.d.ts.map +1 -1
  28. package/dist/core/extensions/types.js.map +1 -1
  29. package/dist/core/keybindings.d.ts +29 -0
  30. package/dist/core/keybindings.d.ts.map +1 -1
  31. package/dist/core/keybindings.js +4 -0
  32. package/dist/core/keybindings.js.map +1 -1
  33. package/dist/core/model-config.d.ts +5 -0
  34. package/dist/core/model-config.d.ts.map +1 -1
  35. package/dist/core/model-config.js +1 -0
  36. package/dist/core/model-config.js.map +1 -1
  37. package/dist/core/model-registry.d.ts +2 -0
  38. package/dist/core/model-registry.d.ts.map +1 -1
  39. package/dist/core/model-registry.js +4 -0
  40. package/dist/core/model-registry.js.map +1 -1
  41. package/dist/core/project-trust.js +2 -2
  42. package/dist/core/project-trust.js.map +1 -1
  43. package/dist/core/sdk.d.ts +5 -3
  44. package/dist/core/sdk.d.ts.map +1 -1
  45. package/dist/core/sdk.js +2 -1
  46. package/dist/core/sdk.js.map +1 -1
  47. package/dist/core/session-manager.js +2 -2
  48. package/dist/core/session-manager.js.map +1 -1
  49. package/dist/core/settings-manager.d.ts +6 -0
  50. package/dist/core/settings-manager.d.ts.map +1 -1
  51. package/dist/core/settings-manager.js +12 -0
  52. package/dist/core/settings-manager.js.map +1 -1
  53. package/dist/core/system-prompt.js +1 -1
  54. package/dist/core/system-prompt.js.map +1 -1
  55. package/dist/core/tools/bash.d.ts +2 -1
  56. package/dist/core/tools/bash.d.ts.map +1 -1
  57. package/dist/core/tools/bash.js +3 -1
  58. package/dist/core/tools/bash.js.map +1 -1
  59. package/dist/core/tools/edit.d.ts.map +1 -1
  60. package/dist/core/tools/edit.js +2 -0
  61. package/dist/core/tools/edit.js.map +1 -1
  62. package/dist/core/tools/find.js +1 -1
  63. package/dist/core/tools/find.js.map +1 -1
  64. package/dist/core/tools/grep.js +1 -1
  65. package/dist/core/tools/grep.js.map +1 -1
  66. package/dist/core/tools/read.d.ts.map +1 -1
  67. package/dist/core/tools/read.js +2 -0
  68. package/dist/core/tools/read.js.map +1 -1
  69. package/dist/core/tools/write.d.ts.map +1 -1
  70. package/dist/core/tools/write.js +2 -0
  71. package/dist/core/tools/write.js.map +1 -1
  72. package/dist/extensions/background/index.d.ts +74 -0
  73. package/dist/extensions/background/index.d.ts.map +1 -0
  74. package/dist/extensions/background/index.js +332 -0
  75. package/dist/extensions/background/index.js.map +1 -0
  76. package/dist/extensions/background/manager.d.ts +81 -0
  77. package/dist/extensions/background/manager.d.ts.map +1 -0
  78. package/dist/extensions/background/manager.js +320 -0
  79. package/dist/extensions/background/manager.js.map +1 -0
  80. package/dist/extensions/background/registry.d.ts +138 -0
  81. package/dist/extensions/background/registry.d.ts.map +1 -0
  82. package/dist/extensions/background/registry.js +358 -0
  83. package/dist/extensions/background/registry.js.map +1 -0
  84. package/dist/extensions/background/render.d.ts +26 -0
  85. package/dist/extensions/background/render.d.ts.map +1 -0
  86. package/dist/extensions/background/render.js +118 -0
  87. package/dist/extensions/background/render.js.map +1 -0
  88. package/dist/extensions/index.d.ts.map +1 -1
  89. package/dist/extensions/index.js +2 -0
  90. package/dist/extensions/index.js.map +1 -1
  91. package/dist/extensions/subagent/activity.d.ts +0 -1
  92. package/dist/extensions/subagent/activity.d.ts.map +1 -1
  93. package/dist/extensions/subagent/activity.js +2 -5
  94. package/dist/extensions/subagent/activity.js.map +1 -1
  95. package/dist/extensions/subagent/agents-command.d.ts +4 -0
  96. package/dist/extensions/subagent/agents-command.d.ts.map +1 -0
  97. package/dist/extensions/subagent/agents-command.js +385 -0
  98. package/dist/extensions/subagent/agents-command.js.map +1 -0
  99. package/dist/extensions/subagent/agents.d.ts +3 -6
  100. package/dist/extensions/subagent/agents.d.ts.map +1 -1
  101. package/dist/extensions/subagent/agents.js +22 -190
  102. package/dist/extensions/subagent/agents.js.map +1 -1
  103. package/dist/extensions/subagent/constants.d.ts +4 -5
  104. package/dist/extensions/subagent/constants.d.ts.map +1 -1
  105. package/dist/extensions/subagent/constants.js +11 -7
  106. package/dist/extensions/subagent/constants.js.map +1 -1
  107. package/dist/extensions/subagent/index.d.ts +0 -3
  108. package/dist/extensions/subagent/index.d.ts.map +1 -1
  109. package/dist/extensions/subagent/index.js +58 -315
  110. package/dist/extensions/subagent/index.js.map +1 -1
  111. package/dist/extensions/subagent/render.d.ts +1 -1
  112. package/dist/extensions/subagent/render.d.ts.map +1 -1
  113. package/dist/extensions/subagent/render.js +208 -585
  114. package/dist/extensions/subagent/render.js.map +1 -1
  115. package/dist/extensions/subagent/resolve.d.ts +2 -2
  116. package/dist/extensions/subagent/resolve.d.ts.map +1 -1
  117. package/dist/extensions/subagent/resolve.js +23 -15
  118. package/dist/extensions/subagent/resolve.js.map +1 -1
  119. package/dist/extensions/subagent/runner.d.ts +1 -2
  120. package/dist/extensions/subagent/runner.d.ts.map +1 -1
  121. package/dist/extensions/subagent/runner.js +109 -131
  122. package/dist/extensions/subagent/runner.js.map +1 -1
  123. package/dist/extensions/subagent/schema.d.ts +4 -10
  124. package/dist/extensions/subagent/schema.d.ts.map +1 -1
  125. package/dist/extensions/subagent/schema.js +8 -13
  126. package/dist/extensions/subagent/schema.js.map +1 -1
  127. package/dist/extensions/subagent/sdk-runner.d.ts.map +1 -1
  128. package/dist/extensions/subagent/sdk-runner.js +9 -20
  129. package/dist/extensions/subagent/sdk-runner.js.map +1 -1
  130. package/dist/extensions/subagent/settings.d.ts +2 -3
  131. package/dist/extensions/subagent/settings.d.ts.map +1 -1
  132. package/dist/extensions/subagent/settings.js +30 -21
  133. package/dist/extensions/subagent/settings.js.map +1 -1
  134. package/dist/extensions/subagent/text.d.ts +3 -0
  135. package/dist/extensions/subagent/text.d.ts.map +1 -0
  136. package/dist/extensions/subagent/text.js +16 -0
  137. package/dist/extensions/subagent/text.js.map +1 -0
  138. package/dist/extensions/subagent/types.d.ts +13 -33
  139. package/dist/extensions/subagent/types.d.ts.map +1 -1
  140. package/dist/extensions/subagent/types.js.map +1 -1
  141. package/dist/extensions/subagent/ui/model-list.d.ts +68 -0
  142. package/dist/extensions/subagent/ui/model-list.d.ts.map +1 -0
  143. package/dist/extensions/subagent/ui/model-list.js +248 -0
  144. package/dist/extensions/subagent/ui/model-list.js.map +1 -0
  145. package/dist/extensions/todo/constants.d.ts +6 -17
  146. package/dist/extensions/todo/constants.d.ts.map +1 -1
  147. package/dist/extensions/todo/constants.js +20 -31
  148. package/dist/extensions/todo/constants.js.map +1 -1
  149. package/dist/extensions/todo/index.d.ts.map +1 -1
  150. package/dist/extensions/todo/index.js +36 -57
  151. package/dist/extensions/todo/index.js.map +1 -1
  152. package/dist/extensions/todo/schema.d.ts +20 -59
  153. package/dist/extensions/todo/schema.d.ts.map +1 -1
  154. package/dist/extensions/todo/schema.js +23 -69
  155. package/dist/extensions/todo/schema.js.map +1 -1
  156. package/dist/extensions/todo/state.d.ts +23 -65
  157. package/dist/extensions/todo/state.d.ts.map +1 -1
  158. package/dist/extensions/todo/state.js +238 -1262
  159. package/dist/extensions/todo/state.js.map +1 -1
  160. package/dist/extensions/todo/view.d.ts +19 -10
  161. package/dist/extensions/todo/view.d.ts.map +1 -1
  162. package/dist/extensions/todo/view.js +411 -463
  163. package/dist/extensions/todo/view.js.map +1 -1
  164. package/dist/extensions/todo/widget.d.ts +15 -0
  165. package/dist/extensions/todo/widget.d.ts.map +1 -0
  166. package/dist/extensions/todo/widget.js +50 -0
  167. package/dist/extensions/todo/widget.js.map +1 -0
  168. package/dist/index.d.ts +1 -1
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js.map +1 -1
  171. package/dist/main.d.ts.map +1 -1
  172. package/dist/main.js +5 -1
  173. package/dist/main.js.map +1 -1
  174. package/dist/modes/interactive/components/extension-selector.d.ts +1 -2
  175. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  176. package/dist/modes/interactive/components/extension-selector.js +5 -11
  177. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  178. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  179. package/dist/modes/interactive/components/model-selector.js +2 -1
  180. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  181. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  182. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  183. package/dist/modes/interactive/components/settings-selector.js +10 -0
  184. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  185. package/dist/modes/interactive/interactive-mode.d.ts +8 -2
  186. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  187. package/dist/modes/interactive/interactive-mode.js +77 -25
  188. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  189. package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
  190. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
  191. package/dist/modes/interactive/model-catalog-refresh.js +36 -0
  192. package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
  193. package/dist/modes/interactive/theme/dark.json +2 -0
  194. package/dist/modes/interactive/theme/light.json +2 -0
  195. package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
  196. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  197. package/dist/modes/interactive/theme/theme-controller.js +23 -10
  198. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  199. package/dist/modes/interactive/theme/theme-schema.json +9 -1
  200. package/dist/modes/interactive/theme/theme.d.ts +5 -3
  201. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  202. package/dist/modes/interactive/theme/theme.js +12 -2
  203. package/dist/modes/interactive/theme/theme.js.map +1 -1
  204. package/dist/modes/json-event.d.ts +4 -1
  205. package/dist/modes/json-event.d.ts.map +1 -1
  206. package/dist/modes/json-event.js +5 -2
  207. package/dist/modes/json-event.js.map +1 -1
  208. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  209. package/dist/modes/rpc/rpc-mode.js +1 -8
  210. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  211. package/dist/package-manager-cli.js +1 -1
  212. package/dist/package-manager-cli.js.map +1 -1
  213. package/dist/server/create-harness.d.ts.map +1 -1
  214. package/dist/server/create-harness.js +2 -0
  215. package/dist/server/create-harness.js.map +1 -1
  216. package/dist/utils/tools-manager.d.ts +10 -1
  217. package/dist/utils/tools-manager.d.ts.map +1 -1
  218. package/dist/utils/tools-manager.js +14 -19
  219. package/dist/utils/tools-manager.js.map +1 -1
  220. package/docs/bundled/README.md +2 -1
  221. package/docs/bundled/extensions/background.md +64 -0
  222. package/docs/bundled/extensions/subagent.md +84 -57
  223. package/docs/bundled/extensions/todo.md +84 -24
  224. package/docs/bundled/tool-presentation.md +1 -1
  225. package/docs/compaction.md +6 -6
  226. package/docs/custom-provider.md +1 -1
  227. package/docs/docs.json +4 -0
  228. package/docs/environment-variables.md +8 -2
  229. package/docs/extensions.md +6 -2
  230. package/docs/json.md +6 -4
  231. package/docs/keybindings.md +9 -2
  232. package/docs/rpc.md +15 -4
  233. package/docs/sdk.md +9 -0
  234. package/docs/settings.md +31 -0
  235. package/docs/terminal-setup.md +23 -2
  236. package/docs/themes.md +24 -3
  237. package/docs/tui.md +2 -2
  238. package/docs/usage.md +4 -3
  239. package/examples/README.md +1 -1
  240. package/examples/extensions/README.md +0 -1
  241. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  242. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  243. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  244. package/examples/extensions/gondolin/package-lock.json +2 -2
  245. package/examples/extensions/gondolin/package.json +1 -1
  246. package/examples/extensions/sandbox/package-lock.json +2 -2
  247. package/examples/extensions/sandbox/package.json +1 -1
  248. package/examples/extensions/with-deps/package-lock.json +2 -2
  249. package/examples/extensions/with-deps/package.json +1 -1
  250. package/npm-shrinkwrap.json +170 -221
  251. package/package.json +6 -6
  252. package/dist/extensions/subagent/picker.d.ts +0 -31
  253. package/dist/extensions/subagent/picker.d.ts.map +0 -1
  254. package/dist/extensions/subagent/picker.js +0 -109
  255. package/dist/extensions/subagent/picker.js.map +0 -1
  256. package/dist/extensions/todo/overlay.d.ts +0 -24
  257. package/dist/extensions/todo/overlay.d.ts.map +0 -1
  258. package/dist/extensions/todo/overlay.js +0 -135
  259. package/dist/extensions/todo/overlay.js.map +0 -1
  260. package/examples/extensions/subagent/README.md +0 -175
  261. package/examples/extensions/subagent/agents/planner.md +0 -37
  262. package/examples/extensions/subagent/agents/reviewer.md +0 -35
  263. package/examples/extensions/subagent/agents/scout.md +0 -50
  264. package/examples/extensions/subagent/agents/worker.md +0 -24
  265. package/examples/extensions/subagent/agents.ts +0 -126
  266. package/examples/extensions/subagent/index.ts +0 -1009
  267. package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
  268. package/examples/extensions/subagent/prompts/implement.md +0 -10
  269. package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
@@ -0,0 +1,68 @@
1
+ import type { Api, Model } from "@earendil-works/pi-ai";
2
+ import { Container, type Focusable, type KeybindingsManager } from "@earendil-works/pi-tui";
3
+ import type { Theme } from "../../../modes/interactive/theme/theme.ts";
4
+ type ModelScope = "all" | "scoped";
5
+ type StatusTone = "muted" | "success" | "error";
6
+ export interface ProfileModelChoice {
7
+ /** Undefined represents inheriting the current session model. */
8
+ modelId: string | undefined;
9
+ /** Effective model for capability checks; unavailable saved overrides have none. */
10
+ model: Model<Api> | undefined;
11
+ unavailable: boolean;
12
+ }
13
+ export interface ProfileModelListOptions {
14
+ theme: Theme;
15
+ keybindings: KeybindingsManager;
16
+ models: readonly Model<Api>[];
17
+ scopedModels: readonly {
18
+ model: Model<Api>;
19
+ }[];
20
+ currentSessionModel: Model<Api> | undefined;
21
+ savedModelId: string | undefined;
22
+ /** Reports the confirmed choice; undefined means the picker was dismissed. */
23
+ onDone: (choice: ProfileModelChoice | undefined) => void;
24
+ }
25
+ /** Searchable /model-style model picker used by /agents; confirm reports the selected choice. */
26
+ export declare class ProfileModelListComponent extends Container implements Focusable {
27
+ private readonly theme;
28
+ private readonly keybindings;
29
+ private readonly currentSessionModel;
30
+ private readonly savedModelId;
31
+ private readonly scopedModelKeys;
32
+ private readonly onDone;
33
+ private readonly searchInput;
34
+ private readonly scopeContainer;
35
+ private readonly listContainer;
36
+ private models;
37
+ private allChoices;
38
+ private scopedChoices;
39
+ private activeChoices;
40
+ private filteredChoices;
41
+ private selectedIndex;
42
+ private scope;
43
+ private statusMessage;
44
+ private statusTone;
45
+ private _focused;
46
+ get focused(): boolean;
47
+ set focused(value: boolean);
48
+ constructor(options: ProfileModelListOptions);
49
+ private makeInheritChoice;
50
+ private makeModelChoice;
51
+ private makeUnavailableChoice;
52
+ private buildChoices;
53
+ private rebuildChoices;
54
+ private applyFilter;
55
+ private updateScopeView;
56
+ private choiceLabel;
57
+ private updateList;
58
+ private moveSelection;
59
+ private toggleScope;
60
+ getSelectedChoice(): ProfileModelChoice | undefined;
61
+ getScope(): ModelScope;
62
+ getSearchValue(): string;
63
+ updateModels(models: readonly Model<Api>[]): void;
64
+ setStatus(message: string | undefined, tone?: StatusTone): void;
65
+ handleInput(data: string): void;
66
+ }
67
+ export {};
68
+ //# sourceMappingURL=model-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-list.d.ts","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/model-list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,248 @@
1
+ import { Container, fuzzyFilter, Input, Spacer, Text, TruncatedText, } from "@earendil-works/pi-tui";
2
+ const MAX_VISIBLE_MODELS = 10;
3
+ function fullModelId(model) {
4
+ return `${model.provider}/${model.id}`;
5
+ }
6
+ function parseModelId(value) {
7
+ const separator = value.indexOf("/");
8
+ return separator > 0
9
+ ? { provider: value.slice(0, separator), id: value.slice(separator + 1) }
10
+ : { provider: "", id: value };
11
+ }
12
+ function compareModels(left, right) {
13
+ const provider = left.provider.localeCompare(right.provider);
14
+ return provider !== 0 ? provider : left.id.localeCompare(right.id);
15
+ }
16
+ function modelSearchText(item) {
17
+ if (item.modelId === undefined) {
18
+ const inherited = item.model ? ` ${fullModelId(item.model)} ${item.model.name}` : "";
19
+ return `inherit${inherited}`;
20
+ }
21
+ const name = item.name ? ` ${item.name}` : "";
22
+ return `${item.provider} ${item.provider}/${item.id} ${item.provider} ${item.id}${name}`;
23
+ }
24
+ /** Searchable /model-style model picker used by /agents; confirm reports the selected choice. */
25
+ export class ProfileModelListComponent extends Container {
26
+ get focused() {
27
+ return this._focused;
28
+ }
29
+ set focused(value) {
30
+ this._focused = value;
31
+ this.searchInput.focused = value;
32
+ }
33
+ constructor(options) {
34
+ super();
35
+ this.allChoices = [];
36
+ this.scopedChoices = [];
37
+ this.activeChoices = [];
38
+ this.filteredChoices = [];
39
+ this.selectedIndex = 0;
40
+ this.statusTone = "muted";
41
+ this._focused = false;
42
+ this.theme = options.theme;
43
+ this.keybindings = options.keybindings;
44
+ this.models = [...options.models];
45
+ this.currentSessionModel = options.currentSessionModel;
46
+ this.savedModelId = options.savedModelId;
47
+ this.scopedModelKeys = new Set(options.scopedModels.map(({ model }) => fullModelId(model)));
48
+ this.scope = this.scopedModelKeys.size > 0 ? "scoped" : "all";
49
+ this.onDone = options.onDone;
50
+ this.scopeContainer = new Container();
51
+ this.addChild(this.scopeContainer);
52
+ this.searchInput = new Input();
53
+ this.addChild(this.searchInput);
54
+ this.addChild(new Spacer(1));
55
+ this.listContainer = new Container();
56
+ this.addChild(this.listContainer);
57
+ this.rebuildChoices(this.savedModelId ?? "");
58
+ }
59
+ makeInheritChoice() {
60
+ return {
61
+ key: "",
62
+ modelId: undefined,
63
+ model: this.currentSessionModel,
64
+ unavailable: false,
65
+ provider: this.currentSessionModel?.provider ?? "",
66
+ id: "inherit",
67
+ name: this.currentSessionModel?.name,
68
+ };
69
+ }
70
+ makeModelChoice(model) {
71
+ return {
72
+ key: fullModelId(model),
73
+ modelId: fullModelId(model),
74
+ model,
75
+ unavailable: false,
76
+ provider: model.provider,
77
+ id: model.id,
78
+ name: model.name,
79
+ };
80
+ }
81
+ makeUnavailableChoice(modelId) {
82
+ const parsed = parseModelId(modelId);
83
+ return {
84
+ key: modelId,
85
+ modelId,
86
+ model: undefined,
87
+ unavailable: true,
88
+ provider: parsed.provider,
89
+ id: parsed.id,
90
+ name: undefined,
91
+ };
92
+ }
93
+ buildChoices(models) {
94
+ const sorted = [...models].sort(compareModels);
95
+ const availableById = new Map(this.models.map((model) => [fullModelId(model), model]));
96
+ const choices = [this.makeInheritChoice()];
97
+ if (this.savedModelId) {
98
+ const saved = availableById.get(this.savedModelId);
99
+ choices.push(saved ? this.makeModelChoice(saved) : this.makeUnavailableChoice(this.savedModelId));
100
+ }
101
+ for (const model of sorted) {
102
+ if (fullModelId(model) !== this.savedModelId)
103
+ choices.push(this.makeModelChoice(model));
104
+ }
105
+ return choices;
106
+ }
107
+ rebuildChoices(preferredKey) {
108
+ const currentKey = preferredKey ?? this.filteredChoices[this.selectedIndex]?.key ?? this.savedModelId ?? "";
109
+ this.allChoices = this.buildChoices(this.models);
110
+ const scopedModels = this.models.filter((model) => this.scopedModelKeys.has(fullModelId(model)));
111
+ this.scopedChoices = this.buildChoices(scopedModels);
112
+ this.activeChoices = this.scope === "scoped" ? this.scopedChoices : this.allChoices;
113
+ this.applyFilter(this.searchInput.getValue(), currentKey, false);
114
+ this.updateScopeView();
115
+ }
116
+ applyFilter(query, preferredKey, resetSelection = true) {
117
+ this.filteredChoices = query ? fuzzyFilter(this.activeChoices, query, modelSearchText) : this.activeChoices;
118
+ if (preferredKey !== undefined) {
119
+ const preferredIndex = this.filteredChoices.findIndex((choice) => choice.key === preferredKey);
120
+ this.selectedIndex = preferredIndex >= 0 ? preferredIndex : 0;
121
+ }
122
+ else if (query && resetSelection) {
123
+ this.selectedIndex = 0;
124
+ }
125
+ else {
126
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredChoices.length - 1));
127
+ }
128
+ this.updateList();
129
+ }
130
+ updateScopeView() {
131
+ this.scopeContainer.clear();
132
+ if (this.scopedModelKeys.size === 0) {
133
+ this.scopeContainer.addChild(new Text(this.theme.fg("warning", "Only showing models from configured providers. Use /login to add providers."), 0, 0));
134
+ this.scopeContainer.addChild(new Spacer(1));
135
+ return;
136
+ }
137
+ const all = this.scope === "all" ? this.theme.fg("accent", "all") : this.theme.fg("muted", "all");
138
+ const scoped = this.scope === "scoped" ? this.theme.fg("accent", "scoped") : this.theme.fg("muted", "scoped");
139
+ this.scopeContainer.addChild(new Text(`${this.theme.fg("muted", "Scope: ")}${all}${this.theme.fg("muted", " | ")}${scoped}`, 0, 0));
140
+ this.scopeContainer.addChild(new Spacer(1));
141
+ }
142
+ choiceLabel(choice) {
143
+ if (choice.modelId === undefined) {
144
+ const inherited = choice.model ? fullModelId(choice.model) : "none";
145
+ return `inherit ${this.theme.fg("muted", `(${inherited})`)}`;
146
+ }
147
+ if (choice.unavailable) {
148
+ const badge = choice.provider ? `${choice.provider} · unavailable` : "unavailable";
149
+ return `${choice.id} ${this.theme.fg("warning", `[${badge}]`)}`;
150
+ }
151
+ return `${choice.id} ${this.theme.fg("muted", `[${choice.provider}]`)}`;
152
+ }
153
+ updateList() {
154
+ this.listContainer.clear();
155
+ const startIndex = Math.max(0, Math.min(this.selectedIndex - Math.floor(MAX_VISIBLE_MODELS / 2), this.filteredChoices.length - MAX_VISIBLE_MODELS));
156
+ const endIndex = Math.min(startIndex + MAX_VISIBLE_MODELS, this.filteredChoices.length);
157
+ for (let index = startIndex; index < endIndex; index++) {
158
+ const choice = this.filteredChoices[index];
159
+ if (!choice)
160
+ continue;
161
+ const selected = index === this.selectedIndex;
162
+ const saved = choice.modelId === this.savedModelId;
163
+ const prefix = selected ? this.theme.fg("accent", "→ ") : " ";
164
+ const label = this.choiceLabel(choice);
165
+ const styledLabel = selected ? this.theme.fg("accent", label) : label;
166
+ const checkmark = saved ? this.theme.fg("success", " ✓") : "";
167
+ this.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`, 0, 0));
168
+ }
169
+ if (startIndex > 0 || endIndex < this.filteredChoices.length) {
170
+ this.listContainer.addChild(new TruncatedText(this.theme.fg("muted", ` (${this.selectedIndex + 1}/${this.filteredChoices.length})`), 0, 0));
171
+ }
172
+ if (this.filteredChoices.length === 0) {
173
+ this.listContainer.addChild(new Text(this.theme.fg("muted", " No matching models"), 0, 0));
174
+ }
175
+ else {
176
+ const selected = this.filteredChoices[this.selectedIndex];
177
+ if (selected?.model?.name) {
178
+ this.listContainer.addChild(new Spacer(1));
179
+ this.listContainer.addChild(new Text(this.theme.fg("muted", ` Model Name: ${selected.model.name}`), 0, 0));
180
+ }
181
+ }
182
+ if (this.statusMessage) {
183
+ this.listContainer.addChild(new Spacer(1));
184
+ this.listContainer.addChild(new Text(this.theme.fg(this.statusTone, ` ${this.statusMessage}`), 0, 0));
185
+ }
186
+ }
187
+ moveSelection(offset) {
188
+ if (this.filteredChoices.length === 0)
189
+ return;
190
+ this.selectedIndex = (this.selectedIndex + offset + this.filteredChoices.length) % this.filteredChoices.length;
191
+ this.updateList();
192
+ }
193
+ toggleScope() {
194
+ if (this.scopedModelKeys.size === 0)
195
+ return;
196
+ const currentKey = this.filteredChoices[this.selectedIndex]?.key;
197
+ this.scope = this.scope === "all" ? "scoped" : "all";
198
+ this.activeChoices = this.scope === "scoped" ? this.scopedChoices : this.allChoices;
199
+ this.applyFilter(this.searchInput.getValue(), currentKey, false);
200
+ this.updateScopeView();
201
+ }
202
+ getSelectedChoice() {
203
+ const selected = this.filteredChoices[this.selectedIndex];
204
+ if (!selected)
205
+ return undefined;
206
+ return { modelId: selected.modelId, model: selected.model, unavailable: selected.unavailable };
207
+ }
208
+ getScope() {
209
+ return this.scope;
210
+ }
211
+ getSearchValue() {
212
+ return this.searchInput.getValue();
213
+ }
214
+ updateModels(models) {
215
+ const selectedKey = this.filteredChoices[this.selectedIndex]?.key;
216
+ this.models = [...models];
217
+ this.rebuildChoices(selectedKey);
218
+ }
219
+ setStatus(message, tone = "muted") {
220
+ this.statusMessage = message;
221
+ this.statusTone = tone;
222
+ this.updateList();
223
+ }
224
+ handleInput(data) {
225
+ if (this.keybindings.matches(data, "tui.input.tab")) {
226
+ this.toggleScope();
227
+ }
228
+ else if (this.keybindings.matches(data, "tui.select.up")) {
229
+ this.moveSelection(-1);
230
+ }
231
+ else if (this.keybindings.matches(data, "tui.select.down")) {
232
+ this.moveSelection(1);
233
+ }
234
+ else if (this.keybindings.matches(data, "tui.select.confirm")) {
235
+ const selected = this.getSelectedChoice();
236
+ if (selected)
237
+ this.onDone(selected);
238
+ }
239
+ else if (this.keybindings.matches(data, "tui.select.cancel")) {
240
+ this.onDone(undefined);
241
+ }
242
+ else {
243
+ this.searchInput.handleInput(data);
244
+ this.applyFilter(this.searchInput.getValue());
245
+ }
246
+ }
247
+ }
248
+ //# sourceMappingURL=model-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-list.js","sourceRoot":"","sources":["../../../../src/extensions/subagent/ui/model-list.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport {\n\tContainer,\n\ttype Focusable,\n\tfuzzyFilter,\n\tInput,\n\ttype KeybindingsManager,\n\tSpacer,\n\tText,\n\tTruncatedText,\n} from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../modes/interactive/theme/theme.ts\";\n\nconst MAX_VISIBLE_MODELS = 10;\n\ntype ModelScope = \"all\" | \"scoped\";\ntype StatusTone = \"muted\" | \"success\" | \"error\";\n\nexport interface ProfileModelChoice {\n\t/** Undefined represents inheriting the current session model. */\n\tmodelId: string | undefined;\n\t/** Effective model for capability checks; unavailable saved overrides have none. */\n\tmodel: Model<Api> | undefined;\n\tunavailable: boolean;\n}\n\nexport interface ProfileModelListOptions {\n\ttheme: Theme;\n\tkeybindings: KeybindingsManager;\n\tmodels: readonly Model<Api>[];\n\tscopedModels: readonly { model: Model<Api> }[];\n\tcurrentSessionModel: Model<Api> | undefined;\n\tsavedModelId: string | undefined;\n\t/** Reports the confirmed choice; undefined means the picker was dismissed. */\n\tonDone: (choice: ProfileModelChoice | undefined) => void;\n}\n\ninterface ModelChoiceItem extends ProfileModelChoice {\n\tkey: string;\n\tprovider: string;\n\tid: string;\n\tname: string | undefined;\n}\n\nfunction fullModelId(model: Pick<Model<Api>, \"provider\" | \"id\">): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction parseModelId(value: string): { provider: string; id: string } {\n\tconst separator = value.indexOf(\"/\");\n\treturn separator > 0\n\t\t? { provider: value.slice(0, separator), id: value.slice(separator + 1) }\n\t\t: { provider: \"\", id: value };\n}\n\nfunction compareModels(left: Model<Api>, right: Model<Api>): number {\n\tconst provider = left.provider.localeCompare(right.provider);\n\treturn provider !== 0 ? provider : left.id.localeCompare(right.id);\n}\n\nfunction modelSearchText(item: ModelChoiceItem): string {\n\tif (item.modelId === undefined) {\n\t\tconst inherited = item.model ? ` ${fullModelId(item.model)} ${item.model.name}` : \"\";\n\t\treturn `inherit${inherited}`;\n\t}\n\tconst name = item.name ? ` ${item.name}` : \"\";\n\treturn `${item.provider} ${item.provider}/${item.id} ${item.provider} ${item.id}${name}`;\n}\n\n/** Searchable /model-style model picker used by /agents; confirm reports the selected choice. */\nexport class ProfileModelListComponent extends Container implements Focusable {\n\tprivate readonly theme: Theme;\n\tprivate readonly keybindings: KeybindingsManager;\n\tprivate readonly currentSessionModel: Model<Api> | undefined;\n\tprivate readonly savedModelId: string | undefined;\n\tprivate readonly scopedModelKeys: Set<string>;\n\tprivate readonly onDone: (choice: ProfileModelChoice | undefined) => void;\n\tprivate readonly searchInput: Input;\n\tprivate readonly scopeContainer: Container;\n\tprivate readonly listContainer: Container;\n\tprivate models: Model<Api>[];\n\tprivate allChoices: ModelChoiceItem[] = [];\n\tprivate scopedChoices: ModelChoiceItem[] = [];\n\tprivate activeChoices: ModelChoiceItem[] = [];\n\tprivate filteredChoices: ModelChoiceItem[] = [];\n\tprivate selectedIndex = 0;\n\tprivate scope: ModelScope;\n\tprivate statusMessage: string | undefined;\n\tprivate statusTone: StatusTone = \"muted\";\n\tprivate _focused = false;\n\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t\tthis.searchInput.focused = value;\n\t}\n\n\tconstructor(options: ProfileModelListOptions) {\n\t\tsuper();\n\t\tthis.theme = options.theme;\n\t\tthis.keybindings = options.keybindings;\n\t\tthis.models = [...options.models];\n\t\tthis.currentSessionModel = options.currentSessionModel;\n\t\tthis.savedModelId = options.savedModelId;\n\t\tthis.scopedModelKeys = new Set(options.scopedModels.map(({ model }) => fullModelId(model)));\n\t\tthis.scope = this.scopedModelKeys.size > 0 ? \"scoped\" : \"all\";\n\t\tthis.onDone = options.onDone;\n\n\t\tthis.scopeContainer = new Container();\n\t\tthis.addChild(this.scopeContainer);\n\t\tthis.searchInput = new Input();\n\t\tthis.addChild(this.searchInput);\n\t\tthis.addChild(new Spacer(1));\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.rebuildChoices(this.savedModelId ?? \"\");\n\t}\n\n\tprivate makeInheritChoice(): ModelChoiceItem {\n\t\treturn {\n\t\t\tkey: \"\",\n\t\t\tmodelId: undefined,\n\t\t\tmodel: this.currentSessionModel,\n\t\t\tunavailable: false,\n\t\t\tprovider: this.currentSessionModel?.provider ?? \"\",\n\t\t\tid: \"inherit\",\n\t\t\tname: this.currentSessionModel?.name,\n\t\t};\n\t}\n\n\tprivate makeModelChoice(model: Model<Api>): ModelChoiceItem {\n\t\treturn {\n\t\t\tkey: fullModelId(model),\n\t\t\tmodelId: fullModelId(model),\n\t\t\tmodel,\n\t\t\tunavailable: false,\n\t\t\tprovider: model.provider,\n\t\t\tid: model.id,\n\t\t\tname: model.name,\n\t\t};\n\t}\n\n\tprivate makeUnavailableChoice(modelId: string): ModelChoiceItem {\n\t\tconst parsed = parseModelId(modelId);\n\t\treturn {\n\t\t\tkey: modelId,\n\t\t\tmodelId,\n\t\t\tmodel: undefined,\n\t\t\tunavailable: true,\n\t\t\tprovider: parsed.provider,\n\t\t\tid: parsed.id,\n\t\t\tname: undefined,\n\t\t};\n\t}\n\n\tprivate buildChoices(models: readonly Model<Api>[]): ModelChoiceItem[] {\n\t\tconst sorted = [...models].sort(compareModels);\n\t\tconst availableById = new Map(this.models.map((model) => [fullModelId(model), model]));\n\t\tconst choices: ModelChoiceItem[] = [this.makeInheritChoice()];\n\t\tif (this.savedModelId) {\n\t\t\tconst saved = availableById.get(this.savedModelId);\n\t\t\tchoices.push(saved ? this.makeModelChoice(saved) : this.makeUnavailableChoice(this.savedModelId));\n\t\t}\n\t\tfor (const model of sorted) {\n\t\t\tif (fullModelId(model) !== this.savedModelId) choices.push(this.makeModelChoice(model));\n\t\t}\n\t\treturn choices;\n\t}\n\n\tprivate rebuildChoices(preferredKey?: string): void {\n\t\tconst currentKey = preferredKey ?? this.filteredChoices[this.selectedIndex]?.key ?? this.savedModelId ?? \"\";\n\t\tthis.allChoices = this.buildChoices(this.models);\n\t\tconst scopedModels = this.models.filter((model) => this.scopedModelKeys.has(fullModelId(model)));\n\t\tthis.scopedChoices = this.buildChoices(scopedModels);\n\t\tthis.activeChoices = this.scope === \"scoped\" ? this.scopedChoices : this.allChoices;\n\t\tthis.applyFilter(this.searchInput.getValue(), currentKey, false);\n\t\tthis.updateScopeView();\n\t}\n\n\tprivate applyFilter(query: string, preferredKey?: string, resetSelection = true): void {\n\t\tthis.filteredChoices = query ? fuzzyFilter(this.activeChoices, query, modelSearchText) : this.activeChoices;\n\t\tif (preferredKey !== undefined) {\n\t\t\tconst preferredIndex = this.filteredChoices.findIndex((choice) => choice.key === preferredKey);\n\t\t\tthis.selectedIndex = preferredIndex >= 0 ? preferredIndex : 0;\n\t\t} else if (query && resetSelection) {\n\t\t\tthis.selectedIndex = 0;\n\t\t} else {\n\t\t\tthis.selectedIndex = Math.min(this.selectedIndex, Math.max(0, this.filteredChoices.length - 1));\n\t\t}\n\t\tthis.updateList();\n\t}\n\n\tprivate updateScopeView(): void {\n\t\tthis.scopeContainer.clear();\n\t\tif (this.scopedModelKeys.size === 0) {\n\t\t\tthis.scopeContainer.addChild(\n\t\t\t\tnew Text(\n\t\t\t\t\tthis.theme.fg(\"warning\", \"Only showing models from configured providers. Use /login to add providers.\"),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t\tthis.scopeContainer.addChild(new Spacer(1));\n\t\t\treturn;\n\t\t}\n\t\tconst all = this.scope === \"all\" ? this.theme.fg(\"accent\", \"all\") : this.theme.fg(\"muted\", \"all\");\n\t\tconst scoped = this.scope === \"scoped\" ? this.theme.fg(\"accent\", \"scoped\") : this.theme.fg(\"muted\", \"scoped\");\n\t\tthis.scopeContainer.addChild(\n\t\t\tnew Text(`${this.theme.fg(\"muted\", \"Scope: \")}${all}${this.theme.fg(\"muted\", \" | \")}${scoped}`, 0, 0),\n\t\t);\n\t\tthis.scopeContainer.addChild(new Spacer(1));\n\t}\n\n\tprivate choiceLabel(choice: ModelChoiceItem): string {\n\t\tif (choice.modelId === undefined) {\n\t\t\tconst inherited = choice.model ? fullModelId(choice.model) : \"none\";\n\t\t\treturn `inherit ${this.theme.fg(\"muted\", `(${inherited})`)}`;\n\t\t}\n\t\tif (choice.unavailable) {\n\t\t\tconst badge = choice.provider ? `${choice.provider} · unavailable` : \"unavailable\";\n\t\t\treturn `${choice.id} ${this.theme.fg(\"warning\", `[${badge}]`)}`;\n\t\t}\n\t\treturn `${choice.id} ${this.theme.fg(\"muted\", `[${choice.provider}]`)}`;\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\t\tconst startIndex = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tthis.selectedIndex - Math.floor(MAX_VISIBLE_MODELS / 2),\n\t\t\t\tthis.filteredChoices.length - MAX_VISIBLE_MODELS,\n\t\t\t),\n\t\t);\n\t\tconst endIndex = Math.min(startIndex + MAX_VISIBLE_MODELS, this.filteredChoices.length);\n\t\tfor (let index = startIndex; index < endIndex; index++) {\n\t\t\tconst choice = this.filteredChoices[index];\n\t\t\tif (!choice) continue;\n\t\t\tconst selected = index === this.selectedIndex;\n\t\t\tconst saved = choice.modelId === this.savedModelId;\n\t\t\tconst prefix = selected ? this.theme.fg(\"accent\", \"→ \") : \" \";\n\t\t\tconst label = this.choiceLabel(choice);\n\t\t\tconst styledLabel = selected ? this.theme.fg(\"accent\", label) : label;\n\t\t\tconst checkmark = saved ? this.theme.fg(\"success\", \" ✓\") : \"\";\n\t\t\tthis.listContainer.addChild(new TruncatedText(`${prefix}${styledLabel}${checkmark}`, 0, 0));\n\t\t}\n\n\t\tif (startIndex > 0 || endIndex < this.filteredChoices.length) {\n\t\t\tthis.listContainer.addChild(\n\t\t\t\tnew TruncatedText(\n\t\t\t\t\tthis.theme.fg(\"muted\", ` (${this.selectedIndex + 1}/${this.filteredChoices.length})`),\n\t\t\t\t\t0,\n\t\t\t\t\t0,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (this.filteredChoices.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", \" No matching models\"), 0, 0));\n\t\t} else {\n\t\t\tconst selected = this.filteredChoices[this.selectedIndex];\n\t\t\tif (selected?.model?.name) {\n\t\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(\"muted\", ` Model Name: ${selected.model.name}`), 0, 0));\n\t\t\t}\n\t\t}\n\t\tif (this.statusMessage) {\n\t\t\tthis.listContainer.addChild(new Spacer(1));\n\t\t\tthis.listContainer.addChild(new Text(this.theme.fg(this.statusTone, ` ${this.statusMessage}`), 0, 0));\n\t\t}\n\t}\n\n\tprivate moveSelection(offset: -1 | 1): void {\n\t\tif (this.filteredChoices.length === 0) return;\n\t\tthis.selectedIndex = (this.selectedIndex + offset + this.filteredChoices.length) % this.filteredChoices.length;\n\t\tthis.updateList();\n\t}\n\n\tprivate toggleScope(): void {\n\t\tif (this.scopedModelKeys.size === 0) return;\n\t\tconst currentKey = this.filteredChoices[this.selectedIndex]?.key;\n\t\tthis.scope = this.scope === \"all\" ? \"scoped\" : \"all\";\n\t\tthis.activeChoices = this.scope === \"scoped\" ? this.scopedChoices : this.allChoices;\n\t\tthis.applyFilter(this.searchInput.getValue(), currentKey, false);\n\t\tthis.updateScopeView();\n\t}\n\n\tgetSelectedChoice(): ProfileModelChoice | undefined {\n\t\tconst selected = this.filteredChoices[this.selectedIndex];\n\t\tif (!selected) return undefined;\n\t\treturn { modelId: selected.modelId, model: selected.model, unavailable: selected.unavailable };\n\t}\n\n\tgetScope(): ModelScope {\n\t\treturn this.scope;\n\t}\n\n\tgetSearchValue(): string {\n\t\treturn this.searchInput.getValue();\n\t}\n\n\tupdateModels(models: readonly Model<Api>[]): void {\n\t\tconst selectedKey = this.filteredChoices[this.selectedIndex]?.key;\n\t\tthis.models = [...models];\n\t\tthis.rebuildChoices(selectedKey);\n\t}\n\n\tsetStatus(message: string | undefined, tone: StatusTone = \"muted\"): void {\n\t\tthis.statusMessage = message;\n\t\tthis.statusTone = tone;\n\t\tthis.updateList();\n\t}\n\n\thandleInput(data: string): void {\n\t\tif (this.keybindings.matches(data, \"tui.input.tab\")) {\n\t\t\tthis.toggleScope();\n\t\t} else if (this.keybindings.matches(data, \"tui.select.up\")) {\n\t\t\tthis.moveSelection(-1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.down\")) {\n\t\t\tthis.moveSelection(1);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.confirm\")) {\n\t\t\tconst selected = this.getSelectedChoice();\n\t\t\tif (selected) this.onDone(selected);\n\t\t} else if (this.keybindings.matches(data, \"tui.select.cancel\")) {\n\t\t\tthis.onDone(undefined);\n\t\t} else {\n\t\t\tthis.searchInput.handleInput(data);\n\t\t\tthis.applyFilter(this.searchInput.getValue());\n\t\t}\n\t}\n}\n"]}
@@ -4,24 +4,13 @@
4
4
  export declare const TODO_TOOL_NAME = "todo";
5
5
  export declare const TODO_TOOL_LABEL = "Todo";
6
6
  export declare const TODOS_COMMAND_NAME = "todos";
7
- /** Max tasks shown in a single `list` tool result body (model-facing). */
8
- export declare const LIST_DISPLAY_MAX_ITEMS = 50;
9
- export declare const TODO_MAX_LIST_LIMIT = 50;
10
- export declare const TODO_MAX_LIST_QUERY_LENGTH = 200;
11
- /** Input limits keep task snapshots and model-facing output bounded. */
7
+ /** Hard capacity of the task list and of a single create/delete batch. */
8
+ export declare const TODO_MAX_ITEMS = 20;
12
9
  export declare const TODO_MAX_BATCH_ITEMS = 20;
13
- export declare const TODO_MAX_SUBJECT_LENGTH = 240;
14
- export declare const TODO_MAX_DESCRIPTION_LENGTH = 4000;
15
- export declare const TODO_MAX_ACTIVE_FORM_LENGTH = 240;
16
- export declare const TODO_MAX_OWNER_LENGTH = 160;
17
- export declare const TODO_MAX_BATCH_KEY_LENGTH = 120;
18
- export declare const TODO_MAX_BLOCKED_BY = 50;
19
- /** Metadata is JSON-like, deeply copied, and bounded independently of task text. */
20
- export declare const TODO_MAX_METADATA_KEY_LENGTH = 160;
21
- export declare const TODO_MAX_METADATA_DEPTH = 8;
22
- export declare const TODO_MAX_METADATA_ENTRIES = 100;
23
- export declare const TODO_MAX_METADATA_BYTES = 16384;
24
- export declare const TODO_TOOL_DESCRIPTION = "Manage the conversation's task list for multi-step coding work.\n\n## When to Use\n- Work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift\n- Capture new user requirements as tasks right away; after completing a task, add follow-up tasks discovered during implementation\n\n## When NOT to Use\n- Trivial single-step tasks and simple Q&A \u2014 just do the work\n\n## Actions\n- create: add one pending task; subject (short, imperative, reviewable scope) and description (what done means: acceptance criteria or verification detail) are required\n- create_many: atomically add up to 20 pending tasks in input order; each item needs subject and description, and optional unique keys can be linked within the batch with blockedByKeys\n- update: change status or details, and manage dependencies via addBlockedBy/removeBlockedBy (what this task waits on) and addBlocks/removeBlocks (what waits on this task); dependencies are validated and cycle-checked\n- list: one-line summaries with unresolved blockers, optionally filtered by status, paged with limit/afterId, searched with query, or narrowed with unblockedOnly; get: one task in full; delete: tombstone an obsolete task and release its dependents; clear: requires confirm=true and the exact expectedCount, without reusing ids\n- Parameters that do not apply to the chosen action are rejected with guidance\n\n## Status Workflow\npending -> in_progress -> completed; deleted is the only terminal state. Keep exactly one task in_progress (starting one demotes any other active task): mark it in_progress BEFORE starting the work, and completed only when implementation and verification are genuinely done \u2014 never with failing tests or partial work; reopen instead of duplicating. When blocked, do not fake completion: create a task for the blocker and link it with addBlockedBy.\n\n## Examples\n{\"action\": \"create\", \"subject\": \"Fix login redirect\", \"description\": \"Redirect lands on the dashboard; auth tests pass\"}\n{\"action\": \"create_many\", \"items\": [{\"key\": \"parser\", \"subject\": \"Wire parser\", \"description\": \"Parser handles config\"}, {\"subject\": \"Test parser\", \"description\": \"Parser tests pass\", \"blockedByKeys\": [\"parser\"]}]}\n{\"action\": \"update\", \"id\": 2, \"status\": \"in_progress\", \"activeForm\": \"fixing login redirect\"}\n{\"action\": \"update\", \"id\": 1, \"addBlocks\": [2, 3]}\n\n## Tips\n- list before create to avoid duplicates; prefer working in id order \u2014 earlier tasks usually set up context for later ones\n- Use dependencies only for real ordering constraints, and delete obsolete tasks promptly so their dependents are released";
10
+ /** Input limits keep task snapshots and model-facing output bounded. */
11
+ export declare const TODO_MAX_SUBJECT_LENGTH = 160;
12
+ export declare const TODO_MAX_DESCRIPTION_LENGTH = 500;
13
+ export declare const TODO_TOOL_DESCRIPTION = "Manage the conversation's task list for multi-step coding work.\n\n## When to Use\n- Work with three or more meaningful steps, a user-provided task list, or a long session where progress can drift\n- Capture new user requirements as tasks right away; after completing a task, add follow-up tasks discovered during implementation\n\n## When NOT to Use\n- Trivial single-step tasks and simple Q&A \u2014 just do the work\n\n## Actions\n- create: atomically add one or many pending tasks from the ordered items array (1 to 20 items); each item needs a short imperative subject and a description of what done means\n- update: edit one task by id \u2014 subject, description, or status; all transitions and reopens are allowed\n- list: show every remaining task with its description, active first\n- delete: remove obsolete tasks by ids (1 to 20, duplicates ignored)\n- The current list holds at most 20 tasks; parameters that do not apply to the chosen action are rejected\n\n## Status Workflow\npending -> in_progress -> completed. Keep exactly one task in_progress: marking one active demotes any other active task to pending. Mark a task in_progress BEFORE starting the work, and completed only when its description is satisfied and relevant checks pass; never with failing tests or partial work. Reopen instead of duplicating. When blocked, do not fake completion: return the task to pending, create a task for the blocker, and finish the blocker first.\n\n## Examples\n{\"action\": \"create\", \"items\": [{\"subject\": \"Wire parser\", \"description\": \"Parser handles the config format\"}, {\"subject\": \"Test parser\", \"description\": \"Parser tests pass\"}]}\n{\"action\": \"update\", \"id\": 2, \"status\": \"in_progress\"}\n{\"action\": \"update\", \"id\": 2, \"status\": \"completed\", \"description\": \"Parser verified against config fixtures\"}\n{\"action\": \"delete\", \"ids\": [3]}\n\n## Tips\n- list before create to avoid duplicates; prefer working in id order \u2014 earlier tasks usually set up context for later ones\n- delete obsolete tasks promptly so the list stays short and accurate";
25
14
  export declare const TODO_PROMPT_SNIPPET = "Track multi-step coding work with a small outcome-oriented task list";
26
15
  export declare const TODO_PROMPT_GUIDELINES: string[];
27
16
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAE1C,0EAA0E;AAC1E,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,mBAAmB,KAAyB,CAAC;AAC1D,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AACjD,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC,oFAAoF;AACpF,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAChD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C,eAAO,MAAM,qBAAqB,kqFA2ByF,CAAC;AAE5H,eAAO,MAAM,mBAAmB,yEAAyE,CAAC;AAE1G,eAAO,MAAM,sBAAsB,UAIlC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,UAAU,CAAC;AAE1C,0EAA0E;AAC1E,eAAO,MAAM,cAAc,KAAK,CAAC;AACjC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,wEAAwE;AACxE,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,eAAO,MAAM,qBAAqB,kkEA2BoC,CAAC;AAEvE,eAAO,MAAM,mBAAmB,yEAAyE,CAAC;AAE1G,eAAO,MAAM,sBAAsB,UAIlC,CAAC"}
@@ -4,55 +4,44 @@
4
4
  export const TODO_TOOL_NAME = "todo";
5
5
  export const TODO_TOOL_LABEL = "Todo";
6
6
  export const TODOS_COMMAND_NAME = "todos";
7
- /** Max tasks shown in a single `list` tool result body (model-facing). */
8
- export const LIST_DISPLAY_MAX_ITEMS = 50;
9
- export const TODO_MAX_LIST_LIMIT = LIST_DISPLAY_MAX_ITEMS;
10
- export const TODO_MAX_LIST_QUERY_LENGTH = 200;
11
- /** Input limits keep task snapshots and model-facing output bounded. */
7
+ /** Hard capacity of the task list and of a single create/delete batch. */
8
+ export const TODO_MAX_ITEMS = 20;
12
9
  export const TODO_MAX_BATCH_ITEMS = 20;
13
- export const TODO_MAX_SUBJECT_LENGTH = 240;
14
- export const TODO_MAX_DESCRIPTION_LENGTH = 4_000;
15
- export const TODO_MAX_ACTIVE_FORM_LENGTH = 240;
16
- export const TODO_MAX_OWNER_LENGTH = 160;
17
- export const TODO_MAX_BATCH_KEY_LENGTH = 120;
18
- export const TODO_MAX_BLOCKED_BY = 50;
19
- /** Metadata is JSON-like, deeply copied, and bounded independently of task text. */
20
- export const TODO_MAX_METADATA_KEY_LENGTH = 160;
21
- export const TODO_MAX_METADATA_DEPTH = 8;
22
- export const TODO_MAX_METADATA_ENTRIES = 100;
23
- export const TODO_MAX_METADATA_BYTES = 16_384;
10
+ /** Input limits keep task snapshots and model-facing output bounded. */
11
+ export const TODO_MAX_SUBJECT_LENGTH = 160;
12
+ export const TODO_MAX_DESCRIPTION_LENGTH = 500;
24
13
  export const TODO_TOOL_DESCRIPTION = `Manage the conversation's task list for multi-step coding work.
25
14
 
26
15
  ## When to Use
27
- - Work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift
16
+ - Work with three or more meaningful steps, a user-provided task list, or a long session where progress can drift
28
17
  - Capture new user requirements as tasks right away; after completing a task, add follow-up tasks discovered during implementation
29
18
 
30
19
  ## When NOT to Use
31
20
  - Trivial single-step tasks and simple Q&A — just do the work
32
21
 
33
22
  ## Actions
34
- - create: add one pending task; subject (short, imperative, reviewable scope) and description (what done means: acceptance criteria or verification detail) are required
35
- - create_many: atomically add up to 20 pending tasks in input order; each item needs subject and description, and optional unique keys can be linked within the batch with blockedByKeys
36
- - update: change status or details, and manage dependencies via addBlockedBy/removeBlockedBy (what this task waits on) and addBlocks/removeBlocks (what waits on this task); dependencies are validated and cycle-checked
37
- - list: one-line summaries with unresolved blockers, optionally filtered by status, paged with limit/afterId, searched with query, or narrowed with unblockedOnly; get: one task in full; delete: tombstone an obsolete task and release its dependents; clear: requires confirm=true and the exact expectedCount, without reusing ids
38
- - Parameters that do not apply to the chosen action are rejected with guidance
23
+ - create: atomically add one or many pending tasks from the ordered items array (1 to 20 items); each item needs a short imperative subject and a description of what done means
24
+ - update: edit one task by id — subject, description, or status; all transitions and reopens are allowed
25
+ - list: show every remaining task with its description, active first
26
+ - delete: remove obsolete tasks by ids (1 to 20, duplicates ignored)
27
+ - The current list holds at most 20 tasks; parameters that do not apply to the chosen action are rejected
39
28
 
40
29
  ## Status Workflow
41
- pending -> in_progress -> completed; deleted is the only terminal state. Keep exactly one task in_progress (starting one demotes any other active task): mark it in_progress BEFORE starting the work, and completed only when implementation and verification are genuinely done — never with failing tests or partial work; reopen instead of duplicating. When blocked, do not fake completion: create a task for the blocker and link it with addBlockedBy.
30
+ pending -> in_progress -> completed. Keep exactly one task in_progress: marking one active demotes any other active task to pending. Mark a task in_progress BEFORE starting the work, and completed only when its description is satisfied and relevant checks pass; never with failing tests or partial work. Reopen instead of duplicating. When blocked, do not fake completion: return the task to pending, create a task for the blocker, and finish the blocker first.
42
31
 
43
32
  ## Examples
44
- {"action": "create", "subject": "Fix login redirect", "description": "Redirect lands on the dashboard; auth tests pass"}
45
- {"action": "create_many", "items": [{"key": "parser", "subject": "Wire parser", "description": "Parser handles config"}, {"subject": "Test parser", "description": "Parser tests pass", "blockedByKeys": ["parser"]}]}
46
- {"action": "update", "id": 2, "status": "in_progress", "activeForm": "fixing login redirect"}
47
- {"action": "update", "id": 1, "addBlocks": [2, 3]}
33
+ {"action": "create", "items": [{"subject": "Wire parser", "description": "Parser handles the config format"}, {"subject": "Test parser", "description": "Parser tests pass"}]}
34
+ {"action": "update", "id": 2, "status": "in_progress"}
35
+ {"action": "update", "id": 2, "status": "completed", "description": "Parser verified against config fixtures"}
36
+ {"action": "delete", "ids": [3]}
48
37
 
49
38
  ## Tips
50
39
  - list before create to avoid duplicates; prefer working in id order — earlier tasks usually set up context for later ones
51
- - Use dependencies only for real ordering constraints, and delete obsolete tasks promptly so their dependents are released`;
40
+ - delete obsolete tasks promptly so the list stays short and accurate`;
52
41
  export const TODO_PROMPT_SNIPPET = "Track multi-step coding work with a small outcome-oriented task list";
53
42
  export const TODO_PROMPT_GUIDELINES = [
54
- "Use `todo` for work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift; list before creating to avoid duplicates, use create_many for a known batch of up to 20 tasks, and capture follow-up work discovered during implementation as new tasks.",
55
- "Mark the active `todo` task in_progress before starting work (exactly one at a time; the tool demotes any other active item) and completed immediately after verification — never while tests fail or work is partial; reopen instead of duplicating, and when blocked create a task for the blocker and link it with addBlockedBy.",
56
- "Keep the `todo` list short and outcome-oriented; prefer working in id order, use dependencies only for real prerequisites, and delete obsolete items promptly so their dependents are released. Clear only with confirm=true and the current expectedCount.",
43
+ "Use `todo` for work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift; list first when tasks may already exist, and create one or many tasks with the ordered items array.",
44
+ "Keep exactly one `todo` task in_progress: mark it in_progress before starting work and completed only after verification — never while tests fail or work is partial; reopen instead of duplicating, and when blocked leave the `todo` task pending and create a task for the blocker.",
45
+ "Keep the `todo` list short and outcome-oriented; prefer working in id order and delete obsolete `todo` items promptly.",
57
46
  ];
58
47
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/extensions/todo/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AACzC,MAAM,CAAC,MAAM,mBAAmB,GAAG,sBAAsB,CAAC;AAC1D,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAE9C,wEAAwE;AACxE,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AACjD,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC,oFAAoF;AACpF,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAChD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE9C,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;2HA2BsF,CAAC;AAE5H,MAAM,CAAC,MAAM,mBAAmB,GAAG,sEAAsE,CAAC;AAE1G,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACrC,wSAAwS;IACxS,qUAAqU;IACrU,6PAA6P;CAC7P,CAAC","sourcesContent":["/**\n * todo/constants.ts — tool identity, command name, input bounds, and prompt copy.\n */\n\nexport const TODO_TOOL_NAME = \"todo\";\nexport const TODO_TOOL_LABEL = \"Todo\";\nexport const TODOS_COMMAND_NAME = \"todos\";\n\n/** Max tasks shown in a single `list` tool result body (model-facing). */\nexport const LIST_DISPLAY_MAX_ITEMS = 50;\nexport const TODO_MAX_LIST_LIMIT = LIST_DISPLAY_MAX_ITEMS;\nexport const TODO_MAX_LIST_QUERY_LENGTH = 200;\n\n/** Input limits keep task snapshots and model-facing output bounded. */\nexport const TODO_MAX_BATCH_ITEMS = 20;\nexport const TODO_MAX_SUBJECT_LENGTH = 240;\nexport const TODO_MAX_DESCRIPTION_LENGTH = 4_000;\nexport const TODO_MAX_ACTIVE_FORM_LENGTH = 240;\nexport const TODO_MAX_OWNER_LENGTH = 160;\nexport const TODO_MAX_BATCH_KEY_LENGTH = 120;\nexport const TODO_MAX_BLOCKED_BY = 50;\n\n/** Metadata is JSON-like, deeply copied, and bounded independently of task text. */\nexport const TODO_MAX_METADATA_KEY_LENGTH = 160;\nexport const TODO_MAX_METADATA_DEPTH = 8;\nexport const TODO_MAX_METADATA_ENTRIES = 100;\nexport const TODO_MAX_METADATA_BYTES = 16_384;\n\nexport const TODO_TOOL_DESCRIPTION = `Manage the conversation's task list for multi-step coding work.\n\n## When to Use\n- Work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift\n- Capture new user requirements as tasks right away; after completing a task, add follow-up tasks discovered during implementation\n\n## When NOT to Use\n- Trivial single-step tasks and simple Q&A — just do the work\n\n## Actions\n- create: add one pending task; subject (short, imperative, reviewable scope) and description (what done means: acceptance criteria or verification detail) are required\n- create_many: atomically add up to 20 pending tasks in input order; each item needs subject and description, and optional unique keys can be linked within the batch with blockedByKeys\n- update: change status or details, and manage dependencies via addBlockedBy/removeBlockedBy (what this task waits on) and addBlocks/removeBlocks (what waits on this task); dependencies are validated and cycle-checked\n- list: one-line summaries with unresolved blockers, optionally filtered by status, paged with limit/afterId, searched with query, or narrowed with unblockedOnly; get: one task in full; delete: tombstone an obsolete task and release its dependents; clear: requires confirm=true and the exact expectedCount, without reusing ids\n- Parameters that do not apply to the chosen action are rejected with guidance\n\n## Status Workflow\npending -> in_progress -> completed; deleted is the only terminal state. Keep exactly one task in_progress (starting one demotes any other active task): mark it in_progress BEFORE starting the work, and completed only when implementation and verification are genuinely done — never with failing tests or partial work; reopen instead of duplicating. When blocked, do not fake completion: create a task for the blocker and link it with addBlockedBy.\n\n## Examples\n{\"action\": \"create\", \"subject\": \"Fix login redirect\", \"description\": \"Redirect lands on the dashboard; auth tests pass\"}\n{\"action\": \"create_many\", \"items\": [{\"key\": \"parser\", \"subject\": \"Wire parser\", \"description\": \"Parser handles config\"}, {\"subject\": \"Test parser\", \"description\": \"Parser tests pass\", \"blockedByKeys\": [\"parser\"]}]}\n{\"action\": \"update\", \"id\": 2, \"status\": \"in_progress\", \"activeForm\": \"fixing login redirect\"}\n{\"action\": \"update\", \"id\": 1, \"addBlocks\": [2, 3]}\n\n## Tips\n- list before create to avoid duplicates; prefer working in id order — earlier tasks usually set up context for later ones\n- Use dependencies only for real ordering constraints, and delete obsolete tasks promptly so their dependents are released`;\n\nexport const TODO_PROMPT_SNIPPET = \"Track multi-step coding work with a small outcome-oriented task list\";\n\nexport const TODO_PROMPT_GUIDELINES = [\n\t\"Use `todo` for work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift; list before creating to avoid duplicates, use create_many for a known batch of up to 20 tasks, and capture follow-up work discovered during implementation as new tasks.\",\n\t\"Mark the active `todo` task in_progress before starting work (exactly one at a time; the tool demotes any other active item) and completed immediately after verification — never while tests fail or work is partial; reopen instead of duplicating, and when blocked create a task for the blocker and link it with addBlockedBy.\",\n\t\"Keep the `todo` list short and outcome-oriented; prefer working in id order, use dependencies only for real prerequisites, and delete obsolete items promptly so their dependents are released. Clear only with confirm=true and the current expectedCount.\",\n];\n"]}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/extensions/todo/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,wEAAwE;AACxE,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAC3C,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;sEA2BiC,CAAC;AAEvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,sEAAsE,CAAC;AAE1G,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACrC,mOAAmO;IACnO,wRAAwR;IACxR,wHAAwH;CACxH,CAAC","sourcesContent":["/**\n * todo/constants.ts — tool identity, command name, input bounds, and prompt copy.\n */\n\nexport const TODO_TOOL_NAME = \"todo\";\nexport const TODO_TOOL_LABEL = \"Todo\";\nexport const TODOS_COMMAND_NAME = \"todos\";\n\n/** Hard capacity of the task list and of a single create/delete batch. */\nexport const TODO_MAX_ITEMS = 20;\nexport const TODO_MAX_BATCH_ITEMS = 20;\n\n/** Input limits keep task snapshots and model-facing output bounded. */\nexport const TODO_MAX_SUBJECT_LENGTH = 160;\nexport const TODO_MAX_DESCRIPTION_LENGTH = 500;\n\nexport const TODO_TOOL_DESCRIPTION = `Manage the conversation's task list for multi-step coding work.\n\n## When to Use\n- Work with three or more meaningful steps, a user-provided task list, or a long session where progress can drift\n- Capture new user requirements as tasks right away; after completing a task, add follow-up tasks discovered during implementation\n\n## When NOT to Use\n- Trivial single-step tasks and simple Q&A — just do the work\n\n## Actions\n- create: atomically add one or many pending tasks from the ordered items array (1 to 20 items); each item needs a short imperative subject and a description of what done means\n- update: edit one task by id — subject, description, or status; all transitions and reopens are allowed\n- list: show every remaining task with its description, active first\n- delete: remove obsolete tasks by ids (1 to 20, duplicates ignored)\n- The current list holds at most 20 tasks; parameters that do not apply to the chosen action are rejected\n\n## Status Workflow\npending -> in_progress -> completed. Keep exactly one task in_progress: marking one active demotes any other active task to pending. Mark a task in_progress BEFORE starting the work, and completed only when its description is satisfied and relevant checks pass; never with failing tests or partial work. Reopen instead of duplicating. When blocked, do not fake completion: return the task to pending, create a task for the blocker, and finish the blocker first.\n\n## Examples\n{\"action\": \"create\", \"items\": [{\"subject\": \"Wire parser\", \"description\": \"Parser handles the config format\"}, {\"subject\": \"Test parser\", \"description\": \"Parser tests pass\"}]}\n{\"action\": \"update\", \"id\": 2, \"status\": \"in_progress\"}\n{\"action\": \"update\", \"id\": 2, \"status\": \"completed\", \"description\": \"Parser verified against config fixtures\"}\n{\"action\": \"delete\", \"ids\": [3]}\n\n## Tips\n- list before create to avoid duplicates; prefer working in id order — earlier tasks usually set up context for later ones\n- delete obsolete tasks promptly so the list stays short and accurate`;\n\nexport const TODO_PROMPT_SNIPPET = \"Track multi-step coding work with a small outcome-oriented task list\";\n\nexport const TODO_PROMPT_GUIDELINES = [\n\t\"Use `todo` for work with three or more meaningful steps, user-provided task lists, or long sessions where progress can drift; list first when tasks may already exist, and create one or many tasks with the ordered items array.\",\n\t\"Keep exactly one `todo` task in_progress: mark it in_progress before starting work and completed only after verification — never while tests fail or work is partial; reopen instead of duplicating, and when blocked leave the `todo` task pending and create a task for the blocker.\",\n\t\"Keep the `todo` list short and outcome-oriented; prefer working in id order and delete obsolete `todo` items promptly.\",\n];\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAEN,KAAK,YAAY,EAGjB,MAAM,gCAAgC,CAAC;AAyCxC,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAuFnD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/todo/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAEN,KAAK,YAAY,EAGjB,MAAM,gCAAgC,CAAC;AA6BxC,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAwEnD"}