@di-code/coding-agent 0.1.1 → 0.1.2

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 (80) hide show
  1. package/dist/cli.d.ts +11 -0
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +59 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/core/resources/index.d.ts +3 -0
  6. package/dist/core/resources/index.d.ts.map +1 -0
  7. package/dist/core/resources/index.js +2 -0
  8. package/dist/core/resources/index.js.map +1 -0
  9. package/dist/core/resources/loader.d.ts +8 -0
  10. package/dist/core/resources/loader.d.ts.map +1 -0
  11. package/dist/core/resources/loader.js +174 -0
  12. package/dist/core/resources/loader.js.map +1 -0
  13. package/dist/core/resources/skills.d.ts +10 -0
  14. package/dist/core/resources/skills.d.ts.map +1 -0
  15. package/dist/core/resources/skills.js +167 -0
  16. package/dist/core/resources/skills.js.map +1 -0
  17. package/dist/core/resources/types.d.ts +41 -0
  18. package/dist/core/resources/types.d.ts.map +1 -0
  19. package/dist/core/resources/types.js +2 -0
  20. package/dist/core/resources/types.js.map +1 -0
  21. package/dist/core/session.d.ts +7 -0
  22. package/dist/core/session.d.ts.map +1 -1
  23. package/dist/core/session.js +23 -3
  24. package/dist/core/session.js.map +1 -1
  25. package/dist/core/skill-command.d.ts +3 -0
  26. package/dist/core/skill-command.d.ts.map +1 -0
  27. package/dist/core/skill-command.js +34 -0
  28. package/dist/core/skill-command.js.map +1 -0
  29. package/dist/core/system-prompt.d.ts +6 -0
  30. package/dist/core/system-prompt.d.ts.map +1 -0
  31. package/dist/core/system-prompt.js +57 -0
  32. package/dist/core/system-prompt.js.map +1 -0
  33. package/dist/extensions/runtime.d.ts +7 -4
  34. package/dist/extensions/runtime.d.ts.map +1 -1
  35. package/dist/extensions/runtime.js +45 -10
  36. package/dist/extensions/runtime.js.map +1 -1
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +3 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/main.d.ts +1 -0
  42. package/dist/main.d.ts.map +1 -1
  43. package/dist/main.js +85 -2
  44. package/dist/main.js.map +1 -1
  45. package/dist/modes/interactive-components.d.ts.map +1 -1
  46. package/dist/modes/interactive-components.js +4 -0
  47. package/dist/modes/interactive-components.js.map +1 -1
  48. package/dist/modes/interactive-state.js +1 -1
  49. package/dist/modes/interactive-state.js.map +1 -1
  50. package/dist/modes/interactive.d.ts +4 -0
  51. package/dist/modes/interactive.d.ts.map +1 -1
  52. package/dist/modes/interactive.js +26 -5
  53. package/dist/modes/interactive.js.map +1 -1
  54. package/dist/plugins/index.d.ts +5 -0
  55. package/dist/plugins/index.d.ts.map +1 -0
  56. package/dist/plugins/index.js +5 -0
  57. package/dist/plugins/index.js.map +1 -0
  58. package/dist/plugins/loader.d.ts +18 -0
  59. package/dist/plugins/loader.d.ts.map +1 -0
  60. package/dist/plugins/loader.js +92 -0
  61. package/dist/plugins/loader.js.map +1 -0
  62. package/dist/plugins/manager.d.ts +23 -0
  63. package/dist/plugins/manager.d.ts.map +1 -0
  64. package/dist/plugins/manager.js +152 -0
  65. package/dist/plugins/manager.js.map +1 -0
  66. package/dist/plugins/manifest.d.ts +7 -0
  67. package/dist/plugins/manifest.d.ts.map +1 -0
  68. package/dist/plugins/manifest.js +116 -0
  69. package/dist/plugins/manifest.js.map +1 -0
  70. package/dist/plugins/types.d.ts +41 -0
  71. package/dist/plugins/types.d.ts.map +1 -0
  72. package/dist/plugins/types.js +2 -0
  73. package/dist/plugins/types.js.map +1 -0
  74. package/dist/provider-onboarding.d.ts.map +1 -1
  75. package/dist/provider-onboarding.js +13 -1
  76. package/dist/provider-onboarding.js.map +1 -1
  77. package/dist/startup.d.ts.map +1 -1
  78. package/dist/startup.js +37 -15
  79. package/dist/startup.js.map +1 -1
  80. package/package.json +15 -4
@@ -1,5 +1,6 @@
1
1
  import { type TUI } from "@di-code/tui";
2
2
  import type { AgentSession, AgentSessionEvent } from "../core/session.ts";
3
+ import type { ExtensionHost } from "../extensions/runtime.ts";
3
4
  export type { AgentSessionEvent };
4
5
  export type { InteractiveMessage, InteractiveProcessItem, InteractiveState } from "./interactive-state.ts";
5
6
  export { InteractiveProjection } from "./interactive-state.ts";
@@ -8,6 +9,7 @@ export interface InteractiveModeOptions {
8
9
  readonly tui: TUI;
9
10
  readonly onExit?: () => void;
10
11
  readonly sessions?: readonly InteractiveSessionChoice[];
12
+ readonly extensionHost?: ExtensionHost;
11
13
  }
12
14
  export interface InteractiveSessionChoice {
13
15
  readonly id: string;
@@ -22,6 +24,7 @@ export declare class InteractiveMode {
22
24
  private session;
23
25
  private readonly tui;
24
26
  private readonly sessionChoices;
27
+ private readonly extensionHost?;
25
28
  private unsubscribeSession?;
26
29
  private sessionSwitching;
27
30
  private promptInFlight;
@@ -35,6 +38,7 @@ export declare class InteractiveMode {
35
38
  private overlay?;
36
39
  private autocompleteOverlay?;
37
40
  private spinnerTimer?;
41
+ private shutdownEmitted;
38
42
  constructor(options: InteractiveModeOptions);
39
43
  start(initialPrompt?: string): void;
40
44
  stop(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/modes/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,EAON,KAAK,GAAG,EACR,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAY1E,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC3G,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACxD;AAED,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7C;AAED,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsC;IACrE,OAAO,CAAC,kBAAkB,CAAC,CAAa;IACxC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAa;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,mBAAmB,CAAC,CAAgB;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAiC;gBAE1C,OAAO,EAAE,sBAAsB;IAkD3C,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAkBnC,IAAI,IAAI,IAAI;IAcZ,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,yBAAyB;IAoBjC,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;YASZ,aAAa;YA4Bb,MAAM;IAgDpB,OAAO,CAAC,kBAAkB;IAsC1B,OAAO,CAAC,WAAW;YAKL,mBAAmB;CAmBjC"}
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/modes/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,EAON,KAAK,GAAG,EACR,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAY9D,YAAY,EAAE,iBAAiB,EAAE,CAAC;AAClC,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC3G,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAC;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;CACvC;AAED,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,IAAI,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CAC7C;AAED,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;IAC1D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsC;IACrE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAC/C,OAAO,CAAC,kBAAkB,CAAC,CAAa;IACxC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAC,CAAkB;IACtC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAa;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,mBAAmB,CAAC,CAAgB;IAC5C,OAAO,CAAC,YAAY,CAAC,CAAiC;IACtD,OAAO,CAAC,eAAe,CAAS;gBAEpB,OAAO,EAAE,sBAAsB;IAoD3C,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAoBnC,IAAI,IAAI,IAAI;IAkBZ,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,mBAAmB;IA6B3B,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,yBAAyB;IAoBjC,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,OAAO;IAKf,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,kBAAkB;YASZ,aAAa;YA4Bb,MAAM;IAgDpB,OAAO,CAAC,kBAAkB;IAiD1B,OAAO,CAAC,WAAW;YAKL,mBAAmB;CAmBjC"}
@@ -10,6 +10,7 @@ export class InteractiveMode {
10
10
  session;
11
11
  tui;
12
12
  sessionChoices;
13
+ extensionHost;
13
14
  unsubscribeSession;
14
15
  sessionSwitching = false;
15
16
  promptInFlight = false;
@@ -23,11 +24,13 @@ export class InteractiveMode {
23
24
  overlay;
24
25
  autocompleteOverlay;
25
26
  spinnerTimer;
27
+ shutdownEmitted = false;
26
28
  constructor(options) {
27
29
  this.session = options.session;
28
30
  this.tui = options.tui;
29
31
  this.onExit = options.onExit;
30
32
  this.sessionChoices = [...(options.sessions ?? [])];
33
+ this.extensionHost = options.extensionHost;
31
34
  const commands = [
32
35
  { name: "help", description: "Show interactive commands" },
33
36
  { name: "clear", description: "Clear visible messages" },
@@ -39,9 +42,10 @@ export class InteractiveMode {
39
42
  { name: "usage", description: "Show token and cost usage" },
40
43
  { name: "retry", description: "Retry the last failed prompt" },
41
44
  ];
45
+ const allCommands = [...commands, ...(this.extensionHost?.listCommands() ?? [])];
42
46
  const autocomplete = {
43
- getSuggestions: (context, autocompleteOptions) => new CombinedAutocompleteProvider(commands, this.session.allowedRoot).getSuggestions(context, autocompleteOptions),
44
- applyCompletion: (context, item, prefix) => new CombinedAutocompleteProvider(commands, this.session.allowedRoot).applyCompletion(context, item, prefix),
47
+ getSuggestions: (context, autocompleteOptions) => new CombinedAutocompleteProvider(allCommands, this.session.allowedRoot).getSuggestions(context, autocompleteOptions),
48
+ applyCompletion: (context, item, prefix) => new CombinedAutocompleteProvider(allCommands, this.session.allowedRoot).applyCompletion(context, item, prefix),
45
49
  };
46
50
  this.editor = new Editor({
47
51
  maxHeight: 3,
@@ -71,6 +75,8 @@ export class InteractiveMode {
71
75
  if (this.started)
72
76
  throw new Error("Interactive mode is already started");
73
77
  this.started = true;
78
+ this.shutdownEmitted = false;
79
+ void this.extensionHost?.emit({ type: "session_start", cwd: this.session.allowedRoot });
74
80
  this.projection.replaceTranscript(this.session.transcript);
75
81
  this.projection.setUsage(this.session.usage);
76
82
  this.subscribeToSession();
@@ -100,6 +106,10 @@ export class InteractiveMode {
100
106
  this.unsubscribeSession?.();
101
107
  this.unsubscribeSession = undefined;
102
108
  this.tui.stop({ finalLines: this.root.renderTranscript(this.tui.columns) });
109
+ if (!this.shutdownEmitted) {
110
+ this.shutdownEmitted = true;
111
+ void this.extensionHost?.emit({ type: "session_shutdown", reason: "user" });
112
+ }
103
113
  }
104
114
  exit() {
105
115
  this.stop();
@@ -369,7 +379,10 @@ export class InteractiveMode {
369
379
  }
370
380
  }
371
381
  handleSlashCommand(input) {
372
- const command = input.slice(1).trim().split(/\s+/, 1)[0]?.toLowerCase();
382
+ const trimmed = input.slice(1).trim();
383
+ const [rawCommand = "", ...argParts] = trimmed.split(/\s+/);
384
+ const command = rawCommand.toLowerCase();
385
+ const args = argParts.join(" ");
373
386
  switch (command) {
374
387
  case "help":
375
388
  this.projection.setStatus("commands: /clear /model /session /theme /settings /compact /usage /retry");
@@ -402,8 +415,16 @@ export class InteractiveMode {
402
415
  else
403
416
  this.projection.setStatus("nothing to retry");
404
417
  break;
405
- default:
406
- this.projection.setError(`Unknown command: /${command ?? ""}`);
418
+ default: {
419
+ if (this.extensionHost?.listCommands().some((entry) => entry.name === command)) {
420
+ void this.extensionHost.runCommand(command, args).catch((cause) => {
421
+ this.projection.setError(cause instanceof Error ? cause.message : String(cause));
422
+ this.refresh();
423
+ });
424
+ break;
425
+ }
426
+ this.projection.setError(`Unknown command: /${command}`);
427
+ }
407
428
  }
408
429
  this.refresh();
409
430
  }
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/modes/interactive.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AutocompleteProvider,\n\tCombinedAutocompleteProvider,\n\tEditor,\n\ttype OverlayHandle,\n\tSelectList,\n\tSettingsList,\n\ttype TUI,\n} from \"@di-code/tui\";\nimport type { AgentSession, AgentSessionEvent } from \"../core/session.ts\";\nimport {\n\tAutocompleteMenu,\n\tInteractiveChat,\n\tInteractiveComposer,\n\tInteractiveFooter,\n\tInteractiveHeader,\n\ttype InteractiveViewState,\n} from \"./interactive-components.ts\";\nimport { InteractiveLayout } from \"./interactive-layout.ts\";\nimport { InteractiveProjection } from \"./interactive-state.ts\";\n\nexport type { AgentSessionEvent };\nexport type { InteractiveMessage, InteractiveProcessItem, InteractiveState } from \"./interactive-state.ts\";\nexport { InteractiveProjection } from \"./interactive-state.ts\";\n\nexport interface InteractiveModeOptions {\n\treadonly session: AgentSession;\n\treadonly tui: TUI;\n\treadonly onExit?: () => void;\n\treadonly sessions?: readonly InteractiveSessionChoice[];\n}\n\nexport interface InteractiveSessionChoice {\n\treadonly id: string;\n\treadonly label: string;\n\treadonly description?: string;\n\topen(): AgentSession | Promise<AgentSession>;\n}\n\nexport class InteractiveMode {\n\tprivate readonly projection = new InteractiveProjection();\n\tprivate readonly root: InteractiveLayout;\n\tprivate readonly editor: Editor;\n\tprivate session: AgentSession;\n\tprivate readonly tui: TUI;\n\tprivate readonly sessionChoices: readonly InteractiveSessionChoice[];\n\tprivate unsubscribeSession?: () => void;\n\tprivate sessionSwitching = false;\n\tprivate promptInFlight = false;\n\tprivate compactionInFlight = false;\n\tprivate activeAbort?: AbortController;\n\tprivate started = false;\n\tprivate lastFailedPrompt?: string;\n\tprivate queuedPrompts: string[] = [];\n\tprivate readonly onExit?: () => void;\n\tprivate theme: \"dark\" | \"light\" = \"dark\";\n\tprivate overlay?: OverlayHandle;\n\tprivate autocompleteOverlay?: OverlayHandle;\n\tprivate spinnerTimer?: ReturnType<typeof setInterval>;\n\n\tconstructor(options: InteractiveModeOptions) {\n\t\tthis.session = options.session;\n\t\tthis.tui = options.tui;\n\t\tthis.onExit = options.onExit;\n\t\tthis.sessionChoices = [...(options.sessions ?? [])];\n\t\tconst commands = [\n\t\t\t{ name: \"help\", description: \"Show interactive commands\" },\n\t\t\t{ name: \"clear\", description: \"Clear visible messages\" },\n\t\t\t{ name: \"model\", description: \"Open the model selector\" },\n\t\t\t{ name: \"session\", description: \"Open the session selector\" },\n\t\t\t{ name: \"theme\", description: \"Open the theme selector\" },\n\t\t\t{ name: \"settings\", description: \"Open the settings selector\" },\n\t\t\t{ name: \"compact\", description: \"Compact the persisted context now\" },\n\t\t\t{ name: \"usage\", description: \"Show token and cost usage\" },\n\t\t\t{ name: \"retry\", description: \"Retry the last failed prompt\" },\n\t\t] as const;\n\t\tconst autocomplete: AutocompleteProvider = {\n\t\t\tgetSuggestions: (context, autocompleteOptions) =>\n\t\t\t\tnew CombinedAutocompleteProvider(commands, this.session.allowedRoot).getSuggestions(\n\t\t\t\t\tcontext,\n\t\t\t\t\tautocompleteOptions,\n\t\t\t\t),\n\t\t\tapplyCompletion: (context, item, prefix) =>\n\t\t\t\tnew CombinedAutocompleteProvider(commands, this.session.allowedRoot).applyCompletion(context, item, prefix),\n\t\t};\n\t\tthis.editor = new Editor({\n\t\t\tmaxHeight: 3,\n\t\t\tautocomplete,\n\t\t});\n\t\tthis.editor.onSubmit = (text) => void this.submit(text);\n\t\tthis.editor.onEscape = () => this.activeAbort?.abort();\n\t\tthis.editor.onCommand = (data) => this.handleCommand(data);\n\t\tthis.editor.onInterrupt = () => this.exit();\n\t\tthis.editor.onAutocompleteChange = () => this.updateAutocompleteOverlay();\n\t\tconst readViewState = (): InteractiveViewState => ({\n\t\t\t...this.projection.state,\n\t\t\tmodel: this.session.modelId,\n\t\t\ttheme: this.theme,\n\t\t});\n\t\tthis.root = new InteractiveLayout({\n\t\t\theader: new InteractiveHeader(readViewState),\n\t\t\tchat: new InteractiveChat(readViewState),\n\t\t\tcomposer: new InteractiveComposer(readViewState),\n\t\t\teditor: this.editor,\n\t\t\tfooter: new InteractiveFooter(readViewState),\n\t\t});\n\t\tthis.tui.addChild(this.root);\n\t\tthis.tui.setFocus(this.editor);\n\t}\n\n\tstart(initialPrompt?: string): void {\n\t\tif (this.started) throw new Error(\"Interactive mode is already started\");\n\t\tthis.started = true;\n\t\tthis.projection.replaceTranscript(this.session.transcript);\n\t\tthis.projection.setUsage(this.session.usage);\n\t\tthis.subscribeToSession();\n\t\ttry {\n\t\t\tthis.tui.start();\n\t\t} catch (cause) {\n\t\t\tthis.started = false;\n\t\t\tthis.unsubscribeSession?.();\n\t\t\tthis.unsubscribeSession = undefined;\n\t\t\tthrow cause;\n\t\t}\n\t\tthis.startSpinnerTimer();\n\t\tif (initialPrompt?.trim()) void this.submit(initialPrompt);\n\t}\n\n\tstop(): void {\n\t\tif (!this.started && !this.unsubscribeSession) return;\n\t\tthis.started = false;\n\t\tthis.activeAbort?.abort();\n\t\tthis.activeAbort = undefined;\n\t\tthis.stopSpinnerTimer();\n\t\tthis.projection.clearTransientProcess();\n\t\tthis.closeOverlay();\n\t\tthis.closeAutocompleteOverlay();\n\t\tthis.unsubscribeSession?.();\n\t\tthis.unsubscribeSession = undefined;\n\t\tthis.tui.stop({ finalLines: this.root.renderTranscript(this.tui.columns) });\n\t}\n\n\tprivate exit(): void {\n\t\tthis.stop();\n\t\tthis.onExit?.();\n\t}\n\n\tprivate handleCommand(data: string): boolean {\n\t\tif (data === \"\\x14\") {\n\t\t\tthis.openThemeSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x13\") {\n\t\t\tthis.openSettingsSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x0f\") {\n\t\t\tthis.openModelSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x0c\") {\n\t\t\tthis.openSessionSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x12\" && this.lastFailedPrompt && !this.promptInFlight) {\n\t\t\tvoid this.submit(this.lastFailedPrompt, true);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate openThemeSelector(): void {\n\t\tconst list = new SelectList([\n\t\t\t{ value: \"dark\", label: \"Dark\", description: \"Dark terminal theme\" },\n\t\t\t{ value: \"light\", label: \"Light\", description: \"Light terminal theme\" },\n\t\t]);\n\t\tlist.onSelect = (item) => {\n\t\t\tthis.theme = item.value === \"light\" ? \"light\" : \"dark\";\n\t\t\tthis.projection.setStatus(`theme=${this.theme}`);\n\t\t\tthis.closeOverlay();\n\t\t\tthis.refresh();\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openModelSelector(): void {\n\t\tconst list = new SelectList(\n\t\t\tthis.session.availableModels.map((model) => ({\n\t\t\t\tvalue: model.id,\n\t\t\t\tlabel: model.name,\n\t\t\t\tdescription: `${model.provider} / ${model.id} / context ${model.contextWindow}`,\n\t\t\t})),\n\t\t);\n\t\tlist.onSelect = (item) => {\n\t\t\ttry {\n\t\t\t\tthis.session.setModel(item.value);\n\t\t\t\tthis.projection.setStatus(`model=${item.value}`);\n\t\t\t\tthis.closeOverlay();\n\t\t\t\tthis.refresh();\n\t\t\t} catch (cause) {\n\t\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t\t}\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openSessionSelector(): void {\n\t\tconst list = new SelectList([\n\t\t\t{\n\t\t\t\tvalue: \"__current__\",\n\t\t\t\tlabel: \"Current session\",\n\t\t\t\tdescription: this.session.sessionFile ?? \"In-memory session\",\n\t\t\t},\n\t\t\t...this.sessionChoices.map((choice) => ({\n\t\t\t\tvalue: choice.id,\n\t\t\t\tlabel: choice.label,\n\t\t\t\t...(choice.description ? { description: choice.description } : {}),\n\t\t\t})),\n\t\t]);\n\t\tlist.onSelect = (item) => {\n\t\t\tif (item.value === \"__current__\") {\n\t\t\t\tthis.projection.setStatus(\"session=current\");\n\t\t\t\tthis.closeOverlay();\n\t\t\t\tthis.refresh();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst choice = this.sessionChoices.find((candidate) => candidate.id === item.value);\n\t\t\tif (!choice) return;\n\t\t\tthis.closeOverlay();\n\t\t\tvoid this.switchSession(choice);\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openSettingsSelector(): void {\n\t\tconst list = new SettingsList([\n\t\t\t{\n\t\t\t\tid: \"compaction\",\n\t\t\t\tlabel: \"Context compaction\",\n\t\t\t\tcurrentValue: this.session.compactionEnabled ? \"on\" : \"off\",\n\t\t\t\tvalues: [\"on\", \"off\"],\n\t\t\t\tdescription: \"Summarize older persisted context before the model limit is reached.\",\n\t\t\t},\n\t\t]);\n\t\tlist.onChange = (id, value) => {\n\t\t\tif (id !== \"compaction\") return;\n\t\t\ttry {\n\t\t\t\tconst enabled = this.session.setCompactionEnabled(value === \"on\");\n\t\t\t\tlist.updateValue(id, enabled ? \"on\" : \"off\");\n\t\t\t\tthis.projection.setStatus(\n\t\t\t\t\tenabled === (value === \"on\")\n\t\t\t\t\t\t? `compaction=${enabled ? \"on\" : \"off\"}`\n\t\t\t\t\t\t: \"compaction unavailable without a persisted session\",\n\t\t\t\t);\n\t\t\t} catch (cause) {\n\t\t\t\tlist.updateValue(id, this.session.compactionEnabled ? \"on\" : \"off\");\n\t\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t\t\tthis.closeOverlay();\n\t\t\t}\n\t\t\tthis.refresh();\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate showOverlay(component: SelectList | SettingsList): void {\n\t\tthis.editor.cancelAutocomplete();\n\t\tthis.closeAutocompleteOverlay();\n\t\tthis.closeOverlay();\n\t\tthis.overlay = this.tui.showOverlay(component, {\n\t\t\twidth: \"70%\",\n\t\t\tmaxHeight: \"60%\",\n\t\t\tanchor: \"center\",\n\t\t\tmargin: 1,\n\t\t});\n\t}\n\n\tprivate closeOverlay(): void {\n\t\tthis.overlay?.hide();\n\t\tthis.overlay = undefined;\n\t}\n\n\tprivate updateAutocompleteOverlay(): void {\n\t\tthis.closeAutocompleteOverlay();\n\t\tif (!this.editor.isShowingAutocomplete()) {\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tconst menu = new AutocompleteMenu(() => ({\n\t\t\titems: this.editor.getAutocompleteItems(),\n\t\t\tindex: this.editor.getAutocompleteIndex(),\n\t\t}));\n\t\tthis.autocompleteOverlay = this.tui.showOverlay(menu, {\n\t\t\twidth: \"55%\",\n\t\t\tmaxHeight: 8,\n\t\t\tanchor: \"bottom-left\",\n\t\t\tmargin: 1,\n\t\t\tnonCapturing: true,\n\t\t});\n\t\tthis.refresh();\n\t}\n\n\tprivate closeAutocompleteOverlay(): void {\n\t\tthis.autocompleteOverlay?.hide();\n\t\tthis.autocompleteOverlay = undefined;\n\t}\n\n\tprivate refresh(): void {\n\t\tthis.root.invalidate();\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate startSpinnerTimer(): void {\n\t\tthis.stopSpinnerTimer();\n\t\tthis.spinnerTimer = setInterval(() => {\n\t\t\tif (this.projection.advanceSpinner()) this.refresh();\n\t\t}, 120);\n\t\tthis.spinnerTimer.unref?.();\n\t}\n\n\tprivate stopSpinnerTimer(): void {\n\t\tif (this.spinnerTimer) clearInterval(this.spinnerTimer);\n\t\tthis.spinnerTimer = undefined;\n\t}\n\n\tprivate subscribeToSession(): void {\n\t\tthis.unsubscribeSession?.();\n\t\tthis.unsubscribeSession = this.session.subscribeSession((event) => {\n\t\t\tif (!this.started) return;\n\t\t\tthis.projection.apply(event);\n\t\t\tthis.refresh();\n\t\t});\n\t}\n\n\tprivate async switchSession(choice: InteractiveSessionChoice): Promise<void> {\n\t\tif (this.promptInFlight || this.sessionSwitching) {\n\t\t\tthis.projection.setError(\"Cannot switch sessions while a prompt is running.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tthis.sessionSwitching = true;\n\t\tthis.projection.setStatus(`opening session=${choice.id}`);\n\t\tthis.refresh();\n\t\ttry {\n\t\t\tconst next = await choice.open();\n\t\t\tif (!this.started) return;\n\t\t\tthis.unsubscribeSession?.();\n\t\t\tthis.session = next;\n\t\t\tthis.queuedPrompts = [];\n\t\t\tthis.projection.setQueue([]);\n\t\t\tthis.projection.replaceTranscript(next.transcript);\n\t\t\tthis.projection.setUsage(next.usage);\n\t\t\tthis.projection.setStatus(`session=${choice.id}`);\n\t\t\tthis.subscribeToSession();\n\t\t} catch (cause) {\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.sessionSwitching = false;\n\t\t}\n\t\tthis.refresh();\n\t}\n\n\tprivate async submit(text: string, retry = false): Promise<void> {\n\t\tconst prompt = text.trim();\n\t\tif (prompt.length === 0 || !this.started) return;\n\t\tif (prompt.startsWith(\"/\")) {\n\t\t\tthis.editor.setValue(\"\");\n\t\t\tthis.handleSlashCommand(prompt);\n\t\t\treturn;\n\t\t}\n\t\tif (this.sessionSwitching) {\n\t\t\tthis.projection.setError(\"A session is opening; wait before submitting a prompt.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (this.compactionInFlight) {\n\t\t\tthis.projection.setError(\"A compaction is running; wait before submitting a prompt.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (this.promptInFlight) {\n\t\t\tthis.queuedPrompts.push(prompt);\n\t\t\tthis.projection.setQueue(this.queuedPrompts);\n\t\t\tthis.root.invalidate();\n\t\t\tthis.tui.requestRender();\n\t\t\treturn;\n\t\t}\n\t\tthis.promptInFlight = true;\n\t\tthis.activeAbort = new AbortController();\n\t\tthis.projection.setRetrying(retry);\n\t\tthis.editor.setValue(\"\");\n\t\ttry {\n\t\t\tconst result = await this.session.prompt(prompt, this.activeAbort.signal);\n\t\t\tif (result.stopReason === \"error\" || result.stopReason === \"aborted\") this.lastFailedPrompt = prompt;\n\t\t\telse this.lastFailedPrompt = undefined;\n\t\t} catch (cause) {\n\t\t\tthis.lastFailedPrompt = prompt;\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.promptInFlight = false;\n\t\t\tthis.activeAbort = undefined;\n\t\t\tthis.projection.setRetrying(false);\n\t\t\tconst next = this.queuedPrompts.shift();\n\t\t\tthis.projection.setQueue(this.queuedPrompts);\n\t\t\tthis.root.invalidate();\n\t\t\tthis.tui.requestRender();\n\t\t\tif (next && this.started) void this.submit(next);\n\t\t}\n\t}\n\n\tprivate handleSlashCommand(input: string): void {\n\t\tconst command = input.slice(1).trim().split(/\\s+/, 1)[0]?.toLowerCase();\n\t\tswitch (command) {\n\t\t\tcase \"help\":\n\t\t\t\tthis.projection.setStatus(\"commands: /clear /model /session /theme /settings /compact /usage /retry\");\n\t\t\t\tbreak;\n\t\t\tcase \"clear\":\n\t\t\t\tthis.projection.clearVisibleMessages();\n\t\t\t\tthis.projection.setStatus(\"visible messages cleared\");\n\t\t\t\tbreak;\n\t\t\tcase \"model\":\n\t\t\t\tthis.openModelSelector();\n\t\t\t\treturn;\n\t\t\tcase \"session\":\n\t\t\t\tthis.openSessionSelector();\n\t\t\t\treturn;\n\t\t\tcase \"theme\":\n\t\t\t\tthis.openThemeSelector();\n\t\t\t\treturn;\n\t\t\tcase \"settings\":\n\t\t\t\tthis.openSettingsSelector();\n\t\t\t\treturn;\n\t\t\tcase \"compact\":\n\t\t\t\tvoid this.runManualCompaction();\n\t\t\t\treturn;\n\t\t\tcase \"usage\":\n\t\t\t\tthis.projection.setStatus(this.formatUsage());\n\t\t\t\tbreak;\n\t\t\tcase \"retry\":\n\t\t\t\tif (this.lastFailedPrompt && !this.promptInFlight) void this.submit(this.lastFailedPrompt, true);\n\t\t\t\telse this.projection.setStatus(\"nothing to retry\");\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.projection.setError(`Unknown command: /${command ?? \"\"}`);\n\t\t}\n\t\tthis.refresh();\n\t}\n\n\tprivate formatUsage(): string {\n\t\tconst usage = this.session.usage;\n\t\treturn `usage: requests=${usage.requestCount} input=${usage.inputTokens} output=${usage.outputTokens} total=${usage.totalTokens} cost=$${usage.cost.total.toFixed(4)} context=${usage.estimatedContextTokens}/${usage.contextWindow}`;\n\t}\n\n\tprivate async runManualCompaction(): Promise<void> {\n\t\tif (this.promptInFlight || this.compactionInFlight) {\n\t\t\tthis.projection.setError(\"Cannot compact while a prompt is running.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tthis.compactionInFlight = true;\n\t\tthis.projection.setStatus(\"starting manual compaction\");\n\t\tthis.refresh();\n\t\ttry {\n\t\t\tawait this.session.compact();\n\t\t\tthis.projection.setStatus(\"manual compaction complete\");\n\t\t} catch (cause) {\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.compactionInFlight = false;\n\t\t\tthis.refresh();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/modes/interactive.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype AutocompleteProvider,\n\tCombinedAutocompleteProvider,\n\tEditor,\n\ttype OverlayHandle,\n\tSelectList,\n\tSettingsList,\n\ttype TUI,\n} from \"@di-code/tui\";\nimport type { AgentSession, AgentSessionEvent } from \"../core/session.ts\";\nimport type { ExtensionHost } from \"../extensions/runtime.ts\";\nimport {\n\tAutocompleteMenu,\n\tInteractiveChat,\n\tInteractiveComposer,\n\tInteractiveFooter,\n\tInteractiveHeader,\n\ttype InteractiveViewState,\n} from \"./interactive-components.ts\";\nimport { InteractiveLayout } from \"./interactive-layout.ts\";\nimport { InteractiveProjection } from \"./interactive-state.ts\";\n\nexport type { AgentSessionEvent };\nexport type { InteractiveMessage, InteractiveProcessItem, InteractiveState } from \"./interactive-state.ts\";\nexport { InteractiveProjection } from \"./interactive-state.ts\";\n\nexport interface InteractiveModeOptions {\n\treadonly session: AgentSession;\n\treadonly tui: TUI;\n\treadonly onExit?: () => void;\n\treadonly sessions?: readonly InteractiveSessionChoice[];\n\treadonly extensionHost?: ExtensionHost;\n}\n\nexport interface InteractiveSessionChoice {\n\treadonly id: string;\n\treadonly label: string;\n\treadonly description?: string;\n\topen(): AgentSession | Promise<AgentSession>;\n}\n\nexport class InteractiveMode {\n\tprivate readonly projection = new InteractiveProjection();\n\tprivate readonly root: InteractiveLayout;\n\tprivate readonly editor: Editor;\n\tprivate session: AgentSession;\n\tprivate readonly tui: TUI;\n\tprivate readonly sessionChoices: readonly InteractiveSessionChoice[];\n\tprivate readonly extensionHost?: ExtensionHost;\n\tprivate unsubscribeSession?: () => void;\n\tprivate sessionSwitching = false;\n\tprivate promptInFlight = false;\n\tprivate compactionInFlight = false;\n\tprivate activeAbort?: AbortController;\n\tprivate started = false;\n\tprivate lastFailedPrompt?: string;\n\tprivate queuedPrompts: string[] = [];\n\tprivate readonly onExit?: () => void;\n\tprivate theme: \"dark\" | \"light\" = \"dark\";\n\tprivate overlay?: OverlayHandle;\n\tprivate autocompleteOverlay?: OverlayHandle;\n\tprivate spinnerTimer?: ReturnType<typeof setInterval>;\n\tprivate shutdownEmitted = false;\n\n\tconstructor(options: InteractiveModeOptions) {\n\t\tthis.session = options.session;\n\t\tthis.tui = options.tui;\n\t\tthis.onExit = options.onExit;\n\t\tthis.sessionChoices = [...(options.sessions ?? [])];\n\t\tthis.extensionHost = options.extensionHost;\n\t\tconst commands = [\n\t\t\t{ name: \"help\", description: \"Show interactive commands\" },\n\t\t\t{ name: \"clear\", description: \"Clear visible messages\" },\n\t\t\t{ name: \"model\", description: \"Open the model selector\" },\n\t\t\t{ name: \"session\", description: \"Open the session selector\" },\n\t\t\t{ name: \"theme\", description: \"Open the theme selector\" },\n\t\t\t{ name: \"settings\", description: \"Open the settings selector\" },\n\t\t\t{ name: \"compact\", description: \"Compact the persisted context now\" },\n\t\t\t{ name: \"usage\", description: \"Show token and cost usage\" },\n\t\t\t{ name: \"retry\", description: \"Retry the last failed prompt\" },\n\t\t] as const;\n\t\tconst allCommands = [...commands, ...(this.extensionHost?.listCommands() ?? [])];\n\t\tconst autocomplete: AutocompleteProvider = {\n\t\t\tgetSuggestions: (context, autocompleteOptions) =>\n\t\t\t\tnew CombinedAutocompleteProvider(allCommands, this.session.allowedRoot).getSuggestions(\n\t\t\t\t\tcontext,\n\t\t\t\t\tautocompleteOptions,\n\t\t\t\t),\n\t\t\tapplyCompletion: (context, item, prefix) =>\n\t\t\t\tnew CombinedAutocompleteProvider(allCommands, this.session.allowedRoot).applyCompletion(context, item, prefix),\n\t\t};\n\t\tthis.editor = new Editor({\n\t\t\tmaxHeight: 3,\n\t\t\tautocomplete,\n\t\t});\n\t\tthis.editor.onSubmit = (text) => void this.submit(text);\n\t\tthis.editor.onEscape = () => this.activeAbort?.abort();\n\t\tthis.editor.onCommand = (data) => this.handleCommand(data);\n\t\tthis.editor.onInterrupt = () => this.exit();\n\t\tthis.editor.onAutocompleteChange = () => this.updateAutocompleteOverlay();\n\t\tconst readViewState = (): InteractiveViewState => ({\n\t\t\t...this.projection.state,\n\t\t\tmodel: this.session.modelId,\n\t\t\ttheme: this.theme,\n\t\t});\n\t\tthis.root = new InteractiveLayout({\n\t\t\theader: new InteractiveHeader(readViewState),\n\t\t\tchat: new InteractiveChat(readViewState),\n\t\t\tcomposer: new InteractiveComposer(readViewState),\n\t\t\teditor: this.editor,\n\t\t\tfooter: new InteractiveFooter(readViewState),\n\t\t});\n\t\tthis.tui.addChild(this.root);\n\t\tthis.tui.setFocus(this.editor);\n\t}\n\n\tstart(initialPrompt?: string): void {\n\t\tif (this.started) throw new Error(\"Interactive mode is already started\");\n\t\tthis.started = true;\n\t\tthis.shutdownEmitted = false;\n\t\tvoid this.extensionHost?.emit({ type: \"session_start\", cwd: this.session.allowedRoot });\n\t\tthis.projection.replaceTranscript(this.session.transcript);\n\t\tthis.projection.setUsage(this.session.usage);\n\t\tthis.subscribeToSession();\n\t\ttry {\n\t\t\tthis.tui.start();\n\t\t} catch (cause) {\n\t\t\tthis.started = false;\n\t\t\tthis.unsubscribeSession?.();\n\t\t\tthis.unsubscribeSession = undefined;\n\t\t\tthrow cause;\n\t\t}\n\t\tthis.startSpinnerTimer();\n\t\tif (initialPrompt?.trim()) void this.submit(initialPrompt);\n\t}\n\n\tstop(): void {\n\t\tif (!this.started && !this.unsubscribeSession) return;\n\t\tthis.started = false;\n\t\tthis.activeAbort?.abort();\n\t\tthis.activeAbort = undefined;\n\t\tthis.stopSpinnerTimer();\n\t\tthis.projection.clearTransientProcess();\n\t\tthis.closeOverlay();\n\t\tthis.closeAutocompleteOverlay();\n\t\tthis.unsubscribeSession?.();\n\t\tthis.unsubscribeSession = undefined;\n\t\tthis.tui.stop({ finalLines: this.root.renderTranscript(this.tui.columns) });\n\t\tif (!this.shutdownEmitted) {\n\t\t\tthis.shutdownEmitted = true;\n\t\t\tvoid this.extensionHost?.emit({ type: \"session_shutdown\", reason: \"user\" });\n\t\t}\n\t}\n\n\tprivate exit(): void {\n\t\tthis.stop();\n\t\tthis.onExit?.();\n\t}\n\n\tprivate handleCommand(data: string): boolean {\n\t\tif (data === \"\\x14\") {\n\t\t\tthis.openThemeSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x13\") {\n\t\t\tthis.openSettingsSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x0f\") {\n\t\t\tthis.openModelSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x0c\") {\n\t\t\tthis.openSessionSelector();\n\t\t\treturn true;\n\t\t}\n\t\tif (data === \"\\x12\" && this.lastFailedPrompt && !this.promptInFlight) {\n\t\t\tvoid this.submit(this.lastFailedPrompt, true);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate openThemeSelector(): void {\n\t\tconst list = new SelectList([\n\t\t\t{ value: \"dark\", label: \"Dark\", description: \"Dark terminal theme\" },\n\t\t\t{ value: \"light\", label: \"Light\", description: \"Light terminal theme\" },\n\t\t]);\n\t\tlist.onSelect = (item) => {\n\t\t\tthis.theme = item.value === \"light\" ? \"light\" : \"dark\";\n\t\t\tthis.projection.setStatus(`theme=${this.theme}`);\n\t\t\tthis.closeOverlay();\n\t\t\tthis.refresh();\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openModelSelector(): void {\n\t\tconst list = new SelectList(\n\t\t\tthis.session.availableModels.map((model) => ({\n\t\t\t\tvalue: model.id,\n\t\t\t\tlabel: model.name,\n\t\t\t\tdescription: `${model.provider} / ${model.id} / context ${model.contextWindow}`,\n\t\t\t})),\n\t\t);\n\t\tlist.onSelect = (item) => {\n\t\t\ttry {\n\t\t\t\tthis.session.setModel(item.value);\n\t\t\t\tthis.projection.setStatus(`model=${item.value}`);\n\t\t\t\tthis.closeOverlay();\n\t\t\t\tthis.refresh();\n\t\t\t} catch (cause) {\n\t\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t\t}\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openSessionSelector(): void {\n\t\tconst list = new SelectList([\n\t\t\t{\n\t\t\t\tvalue: \"__current__\",\n\t\t\t\tlabel: \"Current session\",\n\t\t\t\tdescription: this.session.sessionFile ?? \"In-memory session\",\n\t\t\t},\n\t\t\t...this.sessionChoices.map((choice) => ({\n\t\t\t\tvalue: choice.id,\n\t\t\t\tlabel: choice.label,\n\t\t\t\t...(choice.description ? { description: choice.description } : {}),\n\t\t\t})),\n\t\t]);\n\t\tlist.onSelect = (item) => {\n\t\t\tif (item.value === \"__current__\") {\n\t\t\t\tthis.projection.setStatus(\"session=current\");\n\t\t\t\tthis.closeOverlay();\n\t\t\t\tthis.refresh();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst choice = this.sessionChoices.find((candidate) => candidate.id === item.value);\n\t\t\tif (!choice) return;\n\t\t\tthis.closeOverlay();\n\t\t\tvoid this.switchSession(choice);\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate openSettingsSelector(): void {\n\t\tconst list = new SettingsList([\n\t\t\t{\n\t\t\t\tid: \"compaction\",\n\t\t\t\tlabel: \"Context compaction\",\n\t\t\t\tcurrentValue: this.session.compactionEnabled ? \"on\" : \"off\",\n\t\t\t\tvalues: [\"on\", \"off\"],\n\t\t\t\tdescription: \"Summarize older persisted context before the model limit is reached.\",\n\t\t\t},\n\t\t]);\n\t\tlist.onChange = (id, value) => {\n\t\t\tif (id !== \"compaction\") return;\n\t\t\ttry {\n\t\t\t\tconst enabled = this.session.setCompactionEnabled(value === \"on\");\n\t\t\t\tlist.updateValue(id, enabled ? \"on\" : \"off\");\n\t\t\t\tthis.projection.setStatus(\n\t\t\t\t\tenabled === (value === \"on\")\n\t\t\t\t\t\t? `compaction=${enabled ? \"on\" : \"off\"}`\n\t\t\t\t\t\t: \"compaction unavailable without a persisted session\",\n\t\t\t\t);\n\t\t\t} catch (cause) {\n\t\t\t\tlist.updateValue(id, this.session.compactionEnabled ? \"on\" : \"off\");\n\t\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t\t\tthis.closeOverlay();\n\t\t\t}\n\t\t\tthis.refresh();\n\t\t};\n\t\tlist.onCancel = () => this.closeOverlay();\n\t\tthis.showOverlay(list);\n\t}\n\n\tprivate showOverlay(component: SelectList | SettingsList): void {\n\t\tthis.editor.cancelAutocomplete();\n\t\tthis.closeAutocompleteOverlay();\n\t\tthis.closeOverlay();\n\t\tthis.overlay = this.tui.showOverlay(component, {\n\t\t\twidth: \"70%\",\n\t\t\tmaxHeight: \"60%\",\n\t\t\tanchor: \"center\",\n\t\t\tmargin: 1,\n\t\t});\n\t}\n\n\tprivate closeOverlay(): void {\n\t\tthis.overlay?.hide();\n\t\tthis.overlay = undefined;\n\t}\n\n\tprivate updateAutocompleteOverlay(): void {\n\t\tthis.closeAutocompleteOverlay();\n\t\tif (!this.editor.isShowingAutocomplete()) {\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tconst menu = new AutocompleteMenu(() => ({\n\t\t\titems: this.editor.getAutocompleteItems(),\n\t\t\tindex: this.editor.getAutocompleteIndex(),\n\t\t}));\n\t\tthis.autocompleteOverlay = this.tui.showOverlay(menu, {\n\t\t\twidth: \"55%\",\n\t\t\tmaxHeight: 8,\n\t\t\tanchor: \"bottom-left\",\n\t\t\tmargin: 1,\n\t\t\tnonCapturing: true,\n\t\t});\n\t\tthis.refresh();\n\t}\n\n\tprivate closeAutocompleteOverlay(): void {\n\t\tthis.autocompleteOverlay?.hide();\n\t\tthis.autocompleteOverlay = undefined;\n\t}\n\n\tprivate refresh(): void {\n\t\tthis.root.invalidate();\n\t\tthis.tui.requestRender();\n\t}\n\n\tprivate startSpinnerTimer(): void {\n\t\tthis.stopSpinnerTimer();\n\t\tthis.spinnerTimer = setInterval(() => {\n\t\t\tif (this.projection.advanceSpinner()) this.refresh();\n\t\t}, 120);\n\t\tthis.spinnerTimer.unref?.();\n\t}\n\n\tprivate stopSpinnerTimer(): void {\n\t\tif (this.spinnerTimer) clearInterval(this.spinnerTimer);\n\t\tthis.spinnerTimer = undefined;\n\t}\n\n\tprivate subscribeToSession(): void {\n\t\tthis.unsubscribeSession?.();\n\t\tthis.unsubscribeSession = this.session.subscribeSession((event) => {\n\t\t\tif (!this.started) return;\n\t\t\tthis.projection.apply(event);\n\t\t\tthis.refresh();\n\t\t});\n\t}\n\n\tprivate async switchSession(choice: InteractiveSessionChoice): Promise<void> {\n\t\tif (this.promptInFlight || this.sessionSwitching) {\n\t\t\tthis.projection.setError(\"Cannot switch sessions while a prompt is running.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tthis.sessionSwitching = true;\n\t\tthis.projection.setStatus(`opening session=${choice.id}`);\n\t\tthis.refresh();\n\t\ttry {\n\t\t\tconst next = await choice.open();\n\t\t\tif (!this.started) return;\n\t\t\tthis.unsubscribeSession?.();\n\t\t\tthis.session = next;\n\t\t\tthis.queuedPrompts = [];\n\t\t\tthis.projection.setQueue([]);\n\t\t\tthis.projection.replaceTranscript(next.transcript);\n\t\t\tthis.projection.setUsage(next.usage);\n\t\t\tthis.projection.setStatus(`session=${choice.id}`);\n\t\t\tthis.subscribeToSession();\n\t\t} catch (cause) {\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.sessionSwitching = false;\n\t\t}\n\t\tthis.refresh();\n\t}\n\n\tprivate async submit(text: string, retry = false): Promise<void> {\n\t\tconst prompt = text.trim();\n\t\tif (prompt.length === 0 || !this.started) return;\n\t\tif (prompt.startsWith(\"/\")) {\n\t\t\tthis.editor.setValue(\"\");\n\t\t\tthis.handleSlashCommand(prompt);\n\t\t\treturn;\n\t\t}\n\t\tif (this.sessionSwitching) {\n\t\t\tthis.projection.setError(\"A session is opening; wait before submitting a prompt.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (this.compactionInFlight) {\n\t\t\tthis.projection.setError(\"A compaction is running; wait before submitting a prompt.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tif (this.promptInFlight) {\n\t\t\tthis.queuedPrompts.push(prompt);\n\t\t\tthis.projection.setQueue(this.queuedPrompts);\n\t\t\tthis.root.invalidate();\n\t\t\tthis.tui.requestRender();\n\t\t\treturn;\n\t\t}\n\t\tthis.promptInFlight = true;\n\t\tthis.activeAbort = new AbortController();\n\t\tthis.projection.setRetrying(retry);\n\t\tthis.editor.setValue(\"\");\n\t\ttry {\n\t\t\tconst result = await this.session.prompt(prompt, this.activeAbort.signal);\n\t\t\tif (result.stopReason === \"error\" || result.stopReason === \"aborted\") this.lastFailedPrompt = prompt;\n\t\t\telse this.lastFailedPrompt = undefined;\n\t\t} catch (cause) {\n\t\t\tthis.lastFailedPrompt = prompt;\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.promptInFlight = false;\n\t\t\tthis.activeAbort = undefined;\n\t\t\tthis.projection.setRetrying(false);\n\t\t\tconst next = this.queuedPrompts.shift();\n\t\t\tthis.projection.setQueue(this.queuedPrompts);\n\t\t\tthis.root.invalidate();\n\t\t\tthis.tui.requestRender();\n\t\t\tif (next && this.started) void this.submit(next);\n\t\t}\n\t}\n\n\tprivate handleSlashCommand(input: string): void {\n\t\tconst trimmed = input.slice(1).trim();\n\t\tconst [rawCommand = \"\", ...argParts] = trimmed.split(/\\s+/);\n\t\tconst command = rawCommand.toLowerCase();\n\t\tconst args = argParts.join(\" \");\n\t\tswitch (command) {\n\t\t\tcase \"help\":\n\t\t\t\tthis.projection.setStatus(\"commands: /clear /model /session /theme /settings /compact /usage /retry\");\n\t\t\t\tbreak;\n\t\t\tcase \"clear\":\n\t\t\t\tthis.projection.clearVisibleMessages();\n\t\t\t\tthis.projection.setStatus(\"visible messages cleared\");\n\t\t\t\tbreak;\n\t\t\tcase \"model\":\n\t\t\t\tthis.openModelSelector();\n\t\t\t\treturn;\n\t\t\tcase \"session\":\n\t\t\t\tthis.openSessionSelector();\n\t\t\t\treturn;\n\t\t\tcase \"theme\":\n\t\t\t\tthis.openThemeSelector();\n\t\t\t\treturn;\n\t\t\tcase \"settings\":\n\t\t\t\tthis.openSettingsSelector();\n\t\t\t\treturn;\n\t\t\tcase \"compact\":\n\t\t\t\tvoid this.runManualCompaction();\n\t\t\t\treturn;\n\t\t\tcase \"usage\":\n\t\t\t\tthis.projection.setStatus(this.formatUsage());\n\t\t\t\tbreak;\n\t\t\tcase \"retry\":\n\t\t\t\tif (this.lastFailedPrompt && !this.promptInFlight) void this.submit(this.lastFailedPrompt, true);\n\t\t\t\telse this.projection.setStatus(\"nothing to retry\");\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (this.extensionHost?.listCommands().some((entry) => entry.name === command)) {\n\t\t\t\t\tvoid this.extensionHost.runCommand(command, args).catch((cause) => {\n\t\t\t\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t\t\t\t\tthis.refresh();\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tthis.projection.setError(`Unknown command: /${command}`);\n\t\t\t}\n\t\t}\n\t\tthis.refresh();\n\t}\n\n\tprivate formatUsage(): string {\n\t\tconst usage = this.session.usage;\n\t\treturn `usage: requests=${usage.requestCount} input=${usage.inputTokens} output=${usage.outputTokens} total=${usage.totalTokens} cost=$${usage.cost.total.toFixed(4)} context=${usage.estimatedContextTokens}/${usage.contextWindow}`;\n\t}\n\n\tprivate async runManualCompaction(): Promise<void> {\n\t\tif (this.promptInFlight || this.compactionInFlight) {\n\t\t\tthis.projection.setError(\"Cannot compact while a prompt is running.\");\n\t\t\tthis.refresh();\n\t\t\treturn;\n\t\t}\n\t\tthis.compactionInFlight = true;\n\t\tthis.projection.setStatus(\"starting manual compaction\");\n\t\tthis.refresh();\n\t\ttry {\n\t\t\tawait this.session.compact();\n\t\t\tthis.projection.setStatus(\"manual compaction complete\");\n\t\t} catch (cause) {\n\t\t\tthis.projection.setError(cause instanceof Error ? cause.message : String(cause));\n\t\t} finally {\n\t\t\tthis.compactionInFlight = false;\n\t\t\tthis.refresh();\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export * from "./loader.ts";
2
+ export * from "./manager.ts";
3
+ export * from "./manifest.ts";
4
+ export * from "./types.ts";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ export * from "./loader.js";
2
+ export * from "./manager.js";
3
+ export * from "./manifest.js";
4
+ export * from "./types.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC","sourcesContent":["export * from \"./loader.ts\";\nexport * from \"./manager.ts\";\nexport * from \"./manifest.ts\";\nexport * from \"./types.ts\";\n"]}
@@ -0,0 +1,18 @@
1
+ import { type ExtensionHost } from "../extensions/runtime.ts";
2
+ import type { ProjectTrustManager } from "../extensions/trust.ts";
3
+ import type { DiscoveredPlugin, PluginDiagnostic } from "./types.ts";
4
+ export interface PluginLoadOptions {
5
+ readonly cwd: string;
6
+ readonly agentDir?: string;
7
+ readonly projectTrusted?: boolean;
8
+ readonly trustManager?: ProjectTrustManager;
9
+ readonly mode?: "interactive" | "print" | "json";
10
+ readonly explicitPaths?: readonly string[];
11
+ }
12
+ export interface PluginLoadResult {
13
+ readonly host: ExtensionHost;
14
+ readonly loaded: readonly DiscoveredPlugin[];
15
+ readonly diagnostics: readonly PluginDiagnostic[];
16
+ }
17
+ export declare function loadPlugins(options: PluginLoadOptions): Promise<PluginLoadResult>;
18
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAkB,MAAM,0BAA0B,CAAC;AAC9E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAIlE,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAClD;AA0BD,wBAAsB,WAAW,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyDvF"}
@@ -0,0 +1,92 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readdir, readFile } from "node:fs/promises";
3
+ import { join, resolve } from "node:path";
4
+ import { createJiti } from "jiti";
5
+ import { loadExtensions } from "../extensions/runtime.js";
6
+ import { PluginManager } from "./manager.js";
7
+ import { readPackagePluginManifest, readPluginManifest, resolvePluginEntry } from "./manifest.js";
8
+ async function isPluginPackage(root) {
9
+ try {
10
+ const parsed = JSON.parse(await readFile(join(root, "package.json"), "utf8"));
11
+ return typeof parsed === "object" && parsed !== null && "diCode" in parsed;
12
+ }
13
+ catch {
14
+ return false;
15
+ }
16
+ }
17
+ async function discoverPluginRoots(cwd, agentDir, trusted) {
18
+ const roots = [...(trusted ? [join(cwd, ".di-code", "plugins")] : []), join(agentDir, "plugins", "installed")];
19
+ const result = [];
20
+ for (const root of roots) {
21
+ if (!existsSync(root))
22
+ continue;
23
+ for (const entry of await readdir(root, { withFileTypes: true })) {
24
+ if (!entry.isDirectory())
25
+ continue;
26
+ const pluginRoot = join(root, entry.name);
27
+ if (existsSync(join(pluginRoot, "plugin.json")) || (await isPluginPackage(pluginRoot)))
28
+ result.push(resolve(pluginRoot));
29
+ }
30
+ }
31
+ return result.sort((a, b) => a.localeCompare(b));
32
+ }
33
+ export async function loadPlugins(options) {
34
+ const cwd = resolve(options.cwd);
35
+ const agentDir = resolve(options.agentDir ?? join(cwd, ".di-code"));
36
+ const trusted = options.projectTrusted ?? (options.trustManager ? (await options.trustManager.get(cwd)) === true : false);
37
+ const extensionResult = await loadExtensions({
38
+ cwd,
39
+ projectTrusted: trusted,
40
+ trustManager: options.trustManager,
41
+ mode: options.mode,
42
+ paths: options.explicitPaths,
43
+ });
44
+ const diagnostics = extensionResult.diagnostics.map((diagnostic) => ({
45
+ sourcePath: diagnostic.path,
46
+ stage: diagnostic.stage,
47
+ severity: "error",
48
+ message: diagnostic.message,
49
+ }));
50
+ const enabledGlobal = new Set((await new PluginManager({ agentDir }).list()).filter((plugin) => plugin.enabled).map((plugin) => plugin.id));
51
+ const pluginRoots = await discoverPluginRoots(cwd, agentDir, trusted);
52
+ const loaded = [];
53
+ const jiti = createJiti(import.meta.url, { moduleCache: false });
54
+ for (const root of pluginRoots) {
55
+ const manifestPath = join(root, "plugin.json");
56
+ let manifest;
57
+ try {
58
+ manifest = await readPluginManifest(manifestPath).catch(async () => readPackagePluginManifest(root));
59
+ }
60
+ catch (cause) {
61
+ diagnostics.push({
62
+ sourcePath: manifestPath,
63
+ stage: "manifest",
64
+ severity: "error",
65
+ message: cause instanceof Error ? cause.message : String(cause),
66
+ });
67
+ continue;
68
+ }
69
+ const projectLocal = root.startsWith(resolve(cwd, ".di-code", "plugins"));
70
+ if (!projectLocal && !enabledGlobal.has(manifest.id))
71
+ continue;
72
+ try {
73
+ const entry = await resolvePluginEntry(root, manifest.entry);
74
+ const module = await jiti.import(entry);
75
+ if (typeof module.default !== "function")
76
+ throw new Error("plugin entry must export a default factory function");
77
+ await extensionResult.host.registerExtension(entry, module.default, manifest.id);
78
+ loaded.push({ manifest, root, sourcePath: manifestPath, projectLocal });
79
+ }
80
+ catch (cause) {
81
+ diagnostics.push({
82
+ pluginId: manifest.id,
83
+ sourcePath: manifestPath,
84
+ stage: "import",
85
+ severity: "error",
86
+ message: cause instanceof Error ? cause.message : String(cause),
87
+ });
88
+ }
89
+ }
90
+ return { host: extensionResult.host, loaded, diagnostics };
91
+ }
92
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/plugins/loader.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport { createJiti } from \"jiti\";\nimport { type ExtensionHost, loadExtensions } from \"../extensions/runtime.ts\";\nimport type { ProjectTrustManager } from \"../extensions/trust.ts\";\nimport type { ExtensionFactory } from \"../extensions/types.ts\";\nimport { PluginManager } from \"./manager.ts\";\nimport { readPackagePluginManifest, readPluginManifest, resolvePluginEntry } from \"./manifest.ts\";\nimport type { DiscoveredPlugin, PluginDiagnostic } from \"./types.ts\";\n\nexport interface PluginLoadOptions {\n\treadonly cwd: string;\n\treadonly agentDir?: string;\n\treadonly projectTrusted?: boolean;\n\treadonly trustManager?: ProjectTrustManager;\n\treadonly mode?: \"interactive\" | \"print\" | \"json\";\n\treadonly explicitPaths?: readonly string[];\n}\n\nexport interface PluginLoadResult {\n\treadonly host: ExtensionHost;\n\treadonly loaded: readonly DiscoveredPlugin[];\n\treadonly diagnostics: readonly PluginDiagnostic[];\n}\n\nasync function isPluginPackage(root: string): Promise<boolean> {\n\ttry {\n\t\tconst parsed: unknown = JSON.parse(await readFile(join(root, \"package.json\"), \"utf8\"));\n\t\treturn typeof parsed === \"object\" && parsed !== null && \"diCode\" in parsed;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function discoverPluginRoots(cwd: string, agentDir: string, trusted: boolean): Promise<string[]> {\n\tconst roots = [...(trusted ? [join(cwd, \".di-code\", \"plugins\")] : []), join(agentDir, \"plugins\", \"installed\")];\n\tconst result: string[] = [];\n\tfor (const root of roots) {\n\t\tif (!existsSync(root)) continue;\n\t\tfor (const entry of await readdir(root, { withFileTypes: true })) {\n\t\t\tif (!entry.isDirectory()) continue;\n\t\t\tconst pluginRoot = join(root, entry.name);\n\t\t\tif (existsSync(join(pluginRoot, \"plugin.json\")) || (await isPluginPackage(pluginRoot)))\n\t\t\t\tresult.push(resolve(pluginRoot));\n\t\t}\n\t}\n\treturn result.sort((a, b) => a.localeCompare(b));\n}\n\nexport async function loadPlugins(options: PluginLoadOptions): Promise<PluginLoadResult> {\n\tconst cwd = resolve(options.cwd);\n\tconst agentDir = resolve(options.agentDir ?? join(cwd, \".di-code\"));\n\tconst trusted =\n\t\toptions.projectTrusted ?? (options.trustManager ? (await options.trustManager.get(cwd)) === true : false);\n\tconst extensionResult = await loadExtensions({\n\t\tcwd,\n\t\tprojectTrusted: trusted,\n\t\ttrustManager: options.trustManager,\n\t\tmode: options.mode,\n\t\tpaths: options.explicitPaths,\n\t});\n\tconst diagnostics: PluginDiagnostic[] = extensionResult.diagnostics.map((diagnostic) => ({\n\t\tsourcePath: diagnostic.path,\n\t\tstage: diagnostic.stage,\n\t\tseverity: \"error\",\n\t\tmessage: diagnostic.message,\n\t}));\n\tconst enabledGlobal = new Set(\n\t\t(await new PluginManager({ agentDir }).list()).filter((plugin) => plugin.enabled).map((plugin) => plugin.id),\n\t);\n\tconst pluginRoots = await discoverPluginRoots(cwd, agentDir, trusted);\n\tconst loaded: DiscoveredPlugin[] = [];\n\tconst jiti = createJiti(import.meta.url, { moduleCache: false });\n\tfor (const root of pluginRoots) {\n\t\tconst manifestPath = join(root, \"plugin.json\");\n\t\tlet manifest: Awaited<ReturnType<typeof readPluginManifest>>;\n\t\ttry {\n\t\t\tmanifest = await readPluginManifest(manifestPath).catch(async () => readPackagePluginManifest(root));\n\t\t} catch (cause) {\n\t\t\tdiagnostics.push({\n\t\t\t\tsourcePath: manifestPath,\n\t\t\t\tstage: \"manifest\",\n\t\t\t\tseverity: \"error\",\n\t\t\t\tmessage: cause instanceof Error ? cause.message : String(cause),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst projectLocal = root.startsWith(resolve(cwd, \".di-code\", \"plugins\"));\n\t\tif (!projectLocal && !enabledGlobal.has(manifest.id)) continue;\n\t\ttry {\n\t\t\tconst entry = await resolvePluginEntry(root, manifest.entry);\n\t\t\tconst module = await jiti.import<{ default?: unknown }>(entry);\n\t\t\tif (typeof module.default !== \"function\") throw new Error(\"plugin entry must export a default factory function\");\n\t\t\tawait extensionResult.host.registerExtension(entry, module.default as ExtensionFactory, manifest.id);\n\t\t\tloaded.push({ manifest, root, sourcePath: manifestPath, projectLocal });\n\t\t} catch (cause) {\n\t\t\tdiagnostics.push({\n\t\t\t\tpluginId: manifest.id,\n\t\t\t\tsourcePath: manifestPath,\n\t\t\t\tstage: \"import\",\n\t\t\t\tseverity: \"error\",\n\t\t\t\tmessage: cause instanceof Error ? cause.message : String(cause),\n\t\t\t});\n\t\t}\n\t}\n\treturn { host: extensionResult.host, loaded, diagnostics };\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import type { ManagedPlugin } from "./types.ts";
2
+ export interface PluginManagerOptions {
3
+ readonly agentDir: string;
4
+ readonly now?: () => Date;
5
+ }
6
+ export declare class PluginManager {
7
+ private readonly registryPath;
8
+ private readonly installRoot;
9
+ private readonly now;
10
+ constructor(options: PluginManagerOptions);
11
+ list(): Promise<readonly ManagedPlugin[]>;
12
+ enable(id: string): Promise<ManagedPlugin>;
13
+ disable(id: string): Promise<ManagedPlugin>;
14
+ remove(id: string): Promise<void>;
15
+ installLocal(sourcePath: string): Promise<ManagedPlugin>;
16
+ install(source: string): Promise<ManagedPlugin>;
17
+ update(id: string): Promise<ManagedPlugin>;
18
+ private installCopied;
19
+ private setEnabled;
20
+ private readRegistry;
21
+ private writeRegistry;
22
+ }
23
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,YAAY,CAAC;AAEhE,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAgBD,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;gBACrB,OAAO,EAAE,oBAAoB;IAKnC,IAAI,IAAI,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC;IAGzC,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAG1C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAG3C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASjC,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAuBxD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAwB/C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;YAMlC,aAAa;YAuBb,UAAU;YASV,YAAY;YAQZ,aAAa;CAM3B"}
@@ -0,0 +1,152 @@
1
+ import { spawn } from "node:child_process";
2
+ import { cp, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
+ import { readPackagePluginManifest, readPluginManifest } from "./manifest.js";
5
+ function emptyRegistry() {
6
+ return { version: 1, plugins: {} };
7
+ }
8
+ function isRegistry(value) {
9
+ if (typeof value !== "object" || value === null)
10
+ return false;
11
+ const candidate = value;
12
+ return candidate.version === 1 && typeof candidate.plugins === "object" && candidate.plugins !== null;
13
+ }
14
+ function assertManagedPath(target, root) {
15
+ const child = relative(resolve(root), resolve(target));
16
+ if (!child || child.startsWith("..") || isAbsolute(child))
17
+ throw new Error("plugin path is outside the managed install directory");
18
+ }
19
+ export class PluginManager {
20
+ registryPath;
21
+ installRoot;
22
+ now;
23
+ constructor(options) {
24
+ this.registryPath = resolve(options.agentDir, "plugins", "registry.json");
25
+ this.installRoot = resolve(options.agentDir, "plugins", "installed");
26
+ this.now = options.now ?? (() => new Date());
27
+ }
28
+ async list() {
29
+ return Object.values((await this.readRegistry()).plugins).sort((a, b) => a.id.localeCompare(b.id));
30
+ }
31
+ async enable(id) {
32
+ return this.setEnabled(id, true);
33
+ }
34
+ async disable(id) {
35
+ return this.setEnabled(id, false);
36
+ }
37
+ async remove(id) {
38
+ const registry = await this.readRegistry();
39
+ const plugin = registry.plugins[id];
40
+ if (!plugin)
41
+ throw new Error(`Unknown plugin: ${id}`);
42
+ assertManagedPath(plugin.installedPath, this.installRoot);
43
+ await rm(plugin.installedPath, { recursive: true, force: true });
44
+ delete registry.plugins[id];
45
+ await this.writeRegistry(registry);
46
+ }
47
+ async installLocal(sourcePath) {
48
+ const source = resolve(sourcePath);
49
+ const manifest = await readPluginManifest(join(source, "plugin.json")).catch(() => readPackagePluginManifest(source));
50
+ const destination = resolve(this.installRoot, manifest.id);
51
+ assertManagedPath(destination, this.installRoot);
52
+ await mkdir(this.installRoot, { recursive: true });
53
+ await rm(destination, { recursive: true, force: true });
54
+ await cp(source, destination, { recursive: true, force: false, errorOnExist: false });
55
+ const plugin = {
56
+ id: manifest.id,
57
+ source,
58
+ installedPath: destination,
59
+ enabled: true,
60
+ installedAt: this.now().toISOString(),
61
+ manifest,
62
+ };
63
+ const registry = await this.readRegistry();
64
+ registry.plugins[plugin.id] = plugin;
65
+ await this.writeRegistry(registry);
66
+ return plugin;
67
+ }
68
+ async install(source) {
69
+ if (!source.startsWith("npm:") && !source.startsWith("git:"))
70
+ return this.installLocal(source);
71
+ const staging = resolve(this.installRoot, `.staging-${process.pid}-${Date.now()}`);
72
+ await mkdir(staging, { recursive: true });
73
+ try {
74
+ if (source.startsWith("npm:")) {
75
+ await runCommand("npm", ["install", "--ignore-scripts", "--prefix", staging, source.slice(4)], this.installRoot);
76
+ const modules = join(staging, "node_modules");
77
+ const packageName = source.slice(4).replace(/@[^@]+$/, "");
78
+ const sourceRoot = join(modules, packageName);
79
+ return await this.installCopied(sourceRoot, source, staging);
80
+ }
81
+ await rm(staging, { recursive: true, force: true });
82
+ await runCommand("git", ["clone", "--depth", "1", source.slice(4), staging], this.installRoot);
83
+ return await this.installCopied(staging, source, staging);
84
+ }
85
+ catch (cause) {
86
+ await rm(staging, { recursive: true, force: true });
87
+ throw cause;
88
+ }
89
+ }
90
+ async update(id) {
91
+ const plugin = (await this.readRegistry()).plugins[id];
92
+ if (!plugin)
93
+ throw new Error(`Unknown plugin: ${id}`);
94
+ const updated = await this.install(plugin.source);
95
+ return plugin.enabled ? updated : this.disable(updated.id);
96
+ }
97
+ async installCopied(sourceRoot, source, temporaryRoot) {
98
+ const manifest = await readPluginManifest(join(sourceRoot, "plugin.json")).catch(() => readPackagePluginManifest(sourceRoot));
99
+ const destination = resolve(this.installRoot, manifest.id);
100
+ assertManagedPath(destination, this.installRoot);
101
+ await mkdir(this.installRoot, { recursive: true });
102
+ await rm(destination, { recursive: true, force: true });
103
+ await cp(sourceRoot, destination, { recursive: true, force: false, errorOnExist: false });
104
+ if (resolve(temporaryRoot) !== resolve(sourceRoot))
105
+ await rm(temporaryRoot, { recursive: true, force: true });
106
+ const plugin = {
107
+ id: manifest.id,
108
+ source,
109
+ installedPath: destination,
110
+ enabled: true,
111
+ installedAt: this.now().toISOString(),
112
+ manifest,
113
+ };
114
+ const registry = await this.readRegistry();
115
+ registry.plugins[plugin.id] = plugin;
116
+ await this.writeRegistry(registry);
117
+ return plugin;
118
+ }
119
+ async setEnabled(id, enabled) {
120
+ const registry = await this.readRegistry();
121
+ const plugin = registry.plugins[id];
122
+ if (!plugin)
123
+ throw new Error(`Unknown plugin: ${id}`);
124
+ const next = { ...plugin, enabled };
125
+ registry.plugins[id] = next;
126
+ await this.writeRegistry(registry);
127
+ return next;
128
+ }
129
+ async readRegistry() {
130
+ try {
131
+ const value = JSON.parse(await readFile(this.registryPath, "utf8"));
132
+ return isRegistry(value) ? { version: 1, plugins: { ...value.plugins } } : emptyRegistry();
133
+ }
134
+ catch {
135
+ return emptyRegistry();
136
+ }
137
+ }
138
+ async writeRegistry(registry) {
139
+ await mkdir(dirname(this.registryPath), { recursive: true });
140
+ const temporary = `${this.registryPath}.tmp-${process.pid}`;
141
+ await writeFile(temporary, `${JSON.stringify(registry, null, 2)}\n`, "utf8");
142
+ await rename(temporary, this.registryPath);
143
+ }
144
+ }
145
+ async function runCommand(command, args, cwd) {
146
+ await new Promise((resolveResult, reject) => {
147
+ const child = spawn(command, [...args], { cwd, stdio: "ignore" });
148
+ child.once("error", reject);
149
+ child.once("close", (code) => code === 0 ? resolveResult() : reject(new Error(`${command} plugin install failed`)));
150
+ });
151
+ }
152
+ //# sourceMappingURL=manager.js.map