@di-code/coding-agent 0.1.2 → 0.1.4

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 (81) hide show
  1. package/README.md +499 -143
  2. package/dist/cli.d.ts +1 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +15 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/core/clipboard-image.d.ts +13 -0
  7. package/dist/core/clipboard-image.d.ts.map +1 -0
  8. package/dist/core/clipboard-image.js +99 -0
  9. package/dist/core/clipboard-image.js.map +1 -0
  10. package/dist/core/context-builder.d.ts.map +1 -1
  11. package/dist/core/context-builder.js +6 -2
  12. package/dist/core/context-builder.js.map +1 -1
  13. package/dist/core/image-input.d.ts +13 -0
  14. package/dist/core/image-input.d.ts.map +1 -0
  15. package/dist/core/image-input.js +147 -0
  16. package/dist/core/image-input.js.map +1 -0
  17. package/dist/core/session/session-storage.d.ts.map +1 -1
  18. package/dist/core/session/session-storage.js +1 -0
  19. package/dist/core/session/session-storage.js.map +1 -1
  20. package/dist/core/session.d.ts +19 -2
  21. package/dist/core/session.d.ts.map +1 -1
  22. package/dist/core/session.js +101 -4
  23. package/dist/core/session.js.map +1 -1
  24. package/dist/core/tools/bash.d.ts +2 -2
  25. package/dist/core/tools/bash.d.ts.map +1 -1
  26. package/dist/core/tools/bash.js.map +1 -1
  27. package/dist/core/tools/edit-diff.d.ts +25 -0
  28. package/dist/core/tools/edit-diff.d.ts.map +1 -0
  29. package/dist/core/tools/edit-diff.js +136 -0
  30. package/dist/core/tools/edit-diff.js.map +1 -0
  31. package/dist/core/tools/edit.d.ts +13 -4
  32. package/dist/core/tools/edit.d.ts.map +1 -1
  33. package/dist/core/tools/edit.js +64 -30
  34. package/dist/core/tools/edit.js.map +1 -1
  35. package/dist/core/tools/read.d.ts +2 -2
  36. package/dist/core/tools/read.d.ts.map +1 -1
  37. package/dist/core/tools/read.js.map +1 -1
  38. package/dist/core/tools/write.d.ts +2 -2
  39. package/dist/core/tools/write.d.ts.map +1 -1
  40. package/dist/core/tools/write.js.map +1 -1
  41. package/dist/entry.js +9 -2
  42. package/dist/entry.js.map +1 -1
  43. package/dist/main.d.ts +3 -1
  44. package/dist/main.d.ts.map +1 -1
  45. package/dist/main.js +42 -8
  46. package/dist/main.js.map +1 -1
  47. package/dist/modes/interactive-components.d.ts +3 -0
  48. package/dist/modes/interactive-components.d.ts.map +1 -1
  49. package/dist/modes/interactive-components.js +76 -25
  50. package/dist/modes/interactive-components.js.map +1 -1
  51. package/dist/modes/interactive-diff.d.ts +8 -0
  52. package/dist/modes/interactive-diff.d.ts.map +1 -0
  53. package/dist/modes/interactive-diff.js +78 -0
  54. package/dist/modes/interactive-diff.js.map +1 -0
  55. package/dist/modes/interactive-layout.d.ts +6 -1
  56. package/dist/modes/interactive-layout.d.ts.map +1 -1
  57. package/dist/modes/interactive-layout.js +21 -1
  58. package/dist/modes/interactive-layout.js.map +1 -1
  59. package/dist/modes/interactive-state.d.ts +17 -2
  60. package/dist/modes/interactive-state.d.ts.map +1 -1
  61. package/dist/modes/interactive-state.js +103 -3
  62. package/dist/modes/interactive-state.js.map +1 -1
  63. package/dist/modes/interactive.d.ts +18 -0
  64. package/dist/modes/interactive.d.ts.map +1 -1
  65. package/dist/modes/interactive.js +289 -24
  66. package/dist/modes/interactive.js.map +1 -1
  67. package/dist/provider-onboarding.d.ts +8 -1
  68. package/dist/provider-onboarding.d.ts.map +1 -1
  69. package/dist/provider-onboarding.js +53 -23
  70. package/dist/provider-onboarding.js.map +1 -1
  71. package/dist/rpc-entry.js +1 -1
  72. package/dist/rpc-entry.js.map +1 -1
  73. package/dist/startup.d.ts +11 -3
  74. package/dist/startup.d.ts.map +1 -1
  75. package/dist/startup.js +240 -84
  76. package/dist/startup.js.map +1 -1
  77. package/dist/utils/syntax-highlight.d.ts +2 -0
  78. package/dist/utils/syntax-highlight.d.ts.map +1 -0
  79. package/dist/utils/syntax-highlight.js +55 -0
  80. package/dist/utils/syntax-highlight.js.map +1 -0
  81. package/package.json +9 -4
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAuC,IAAI,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACnC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAeH,MAAM,sBAAsB,GAAoB;IAC/C,KAAK,CAAC,KAAK,CAAC,SAAS;QACpB,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO;QAChC,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;CACD,CAAC;AAEF,SAAS,cAAc,CAAC,MAA+B;IACtD,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,UAA4B,EAAE;IAClF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,sBAAsB,CAAC;IAEhE,OAAO;QACN,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,2EAA2E;QACxF,UAAU,EAAE,eAAe;QAC3B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM;YAC5C,cAAc,CAAC,MAAM,CAAC,CAAC;YACvB,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5E,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAEpF,OAAO,qBAAqB,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;gBACrD,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,MAAM,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC9C,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,MAAM,UAAU,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAC7D,cAAc,CAAC,MAAM,CAAC,CAAC;gBAEvB,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5D,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,KAAK,aAAa,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5F,CAAC,CAAC,CAAC;QACJ,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import { mkdir as fsMkdir, writeFile as fsWriteFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { AgentTool } from \"@di-code/agent\";\nimport { type Static, type ToolResultContent, Type } from \"@di-code/ai\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveAllowedMutationPath } from \"./path-boundary.ts\";\n\nexport const writeParameters = Type.Object({\n\tpath: Type.String({ minLength: 1 }),\n\tcontent: Type.String(),\n});\n\nexport type WriteParameters = Static<typeof writeParameters>;\n\nexport interface WriteOperations {\n\tmkdir(directory: string): Promise<void>;\n\twriteFile(filePath: string, content: string): Promise<void>;\n}\n\nexport interface WriteToolOptions {\n\treadonly operations?: WriteOperations;\n}\n\nexport type WriteTool = AgentTool<typeof writeParameters>;\n\nconst defaultWriteOperations: WriteOperations = {\n\tasync mkdir(directory) {\n\t\tawait fsMkdir(directory, { recursive: true });\n\t},\n\tasync writeFile(filePath, content) {\n\t\tawait fsWriteFile(filePath, content, \"utf8\");\n\t},\n};\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n}\n\nexport function createWriteTool(allowedRoot: string, options: WriteToolOptions = {}): WriteTool {\n\tconst operations = options.operations ?? defaultWriteOperations;\n\n\treturn {\n\t\tname: \"write\",\n\t\tdescription: \"Create or completely overwrite a UTF-8 text file inside the allowed root.\",\n\t\tparameters: writeParameters,\n\t\tasync execute(_toolCallId, parameters, signal): Promise<ToolResultContent[]> {\n\t\t\tthrowIfAborted(signal);\n\t\t\tif (parameters.path.length === 0) throw new Error(\"path must not be empty\");\n\t\t\tconst absolutePath = await resolveAllowedMutationPath(parameters.path, allowedRoot);\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait operations.mkdir(dirname(absolutePath));\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait operations.writeFile(absolutePath, parameters.content);\n\t\t\t\tthrowIfAborted(signal);\n\n\t\t\t\tconst bytes = Buffer.byteLength(parameters.content, \"utf8\");\n\t\t\t\treturn [{ type: \"text\", text: `Successfully wrote ${bytes} bytes to ${parameters.path}` }];\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAuC,IAAI,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACnC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAeH,MAAM,sBAAsB,GAAoB;IAC/C,KAAK,CAAC,KAAK,CAAC,SAAS;QACpB,MAAM,OAAO,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO;QAChC,MAAM,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;CACD,CAAC;AAEF,SAAS,cAAc,CAAC,MAA+B;IACtD,IAAI,MAAM,EAAE,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,UAA4B,EAAE;IAClF,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,sBAAsB,CAAC;IAEhE,OAAO;QACN,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,2EAA2E;QACxF,UAAU,EAAE,eAAe;QAC3B,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM;YAC5C,cAAc,CAAC,MAAM,CAAC,CAAC;YACvB,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5E,MAAM,YAAY,GAAG,MAAM,0BAA0B,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAEpF,OAAO,qBAAqB,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;gBACrD,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,MAAM,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC9C,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,MAAM,UAAU,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;gBAC7D,cAAc,CAAC,MAAM,CAAC,CAAC;gBAEvB,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC5D,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,KAAK,aAAa,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC5F,CAAC,CAAC,CAAC;QACJ,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import { mkdir as fsMkdir, writeFile as fsWriteFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { AgentTool } from \"@di-code/agent\";\nimport { type Static, type ToolResultContent, Type } from \"@di-code/ai\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveAllowedMutationPath } from \"./path-boundary.ts\";\n\nexport const writeParameters = Type.Object({\n\tpath: Type.String({ minLength: 1 }),\n\tcontent: Type.String(),\n});\n\nexport type WriteParameters = Static<typeof writeParameters>;\n\nexport interface WriteOperations {\n\tmkdir(directory: string): Promise<void>;\n\twriteFile(filePath: string, content: string): Promise<void>;\n}\n\nexport interface WriteToolOptions {\n\treadonly operations?: WriteOperations;\n}\n\nexport type WriteTool = AgentTool<typeof writeParameters, ToolResultContent[]>;\n\nconst defaultWriteOperations: WriteOperations = {\n\tasync mkdir(directory) {\n\t\tawait fsMkdir(directory, { recursive: true });\n\t},\n\tasync writeFile(filePath, content) {\n\t\tawait fsWriteFile(filePath, content, \"utf8\");\n\t},\n};\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n}\n\nexport function createWriteTool(allowedRoot: string, options: WriteToolOptions = {}): WriteTool {\n\tconst operations = options.operations ?? defaultWriteOperations;\n\n\treturn {\n\t\tname: \"write\",\n\t\tdescription: \"Create or completely overwrite a UTF-8 text file inside the allowed root.\",\n\t\tparameters: writeParameters,\n\t\tasync execute(_toolCallId, parameters, signal): Promise<ToolResultContent[]> {\n\t\t\tthrowIfAborted(signal);\n\t\t\tif (parameters.path.length === 0) throw new Error(\"path must not be empty\");\n\t\t\tconst absolutePath = await resolveAllowedMutationPath(parameters.path, allowedRoot);\n\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait operations.mkdir(dirname(absolutePath));\n\t\t\t\tthrowIfAborted(signal);\n\t\t\t\tawait operations.writeFile(absolutePath, parameters.content);\n\t\t\t\tthrowIfAborted(signal);\n\n\t\t\t\tconst bytes = Buffer.byteLength(parameters.content, \"utf8\");\n\t\t\t\treturn [{ type: \"text\", text: `Successfully wrote ${bytes} bytes to ${parameters.path}` }];\n\t\t\t});\n\t\t},\n\t};\n}\n"]}
package/dist/entry.js CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
2
4
  import { ProcessTerminal } from "@di-code/tui";
3
5
  import packageMetadata from "../package.json" with { type: "json" };
4
6
  import { runMain } from "./main.js";
@@ -11,10 +13,15 @@ try {
11
13
  createRuntime: (command) => {
12
14
  const isInteractiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY);
13
15
  if (shouldStartProviderOnboarding(command, isInteractiveTerminal, configuration)) {
14
- return runProviderOnboarding({ configuration, terminal: new ProcessTerminal() });
16
+ return runProviderOnboarding({
17
+ configuration,
18
+ terminal: new ProcessTerminal(),
19
+ agentDir: join(homedir(), ".di-code"),
20
+ });
15
21
  }
16
- return resolveStartupRuntime(configuration.environment, configuration.providers);
22
+ return resolveStartupRuntime(configuration.environment, configuration.providers, configuration.defaults);
17
23
  },
24
+ startupConfiguration: configuration,
18
25
  stdout: (text) => process.stdout.write(text),
19
26
  stderr: (text) => process.stderr.write(text),
20
27
  });
package/dist/entry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,eAAe,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAEnG,IAAI,CAAC;IACJ,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,QAAQ,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC3E,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE;YAC1B,MAAM,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnF,IAAI,6BAA6B,CAAC,OAAO,EAAE,qBAAqB,EAAE,aAAa,CAAC,EAAE,CAAC;gBAClF,OAAO,qBAAqB,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,eAAe,EAAE,EAAE,CAAC,CAAC;YAClF,CAAC;YACD,OAAO,qBAAqB,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;KAC5C,CAAC,CAAC;AACJ,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;IACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { ProcessTerminal } from \"@di-code/tui\";\nimport packageMetadata from \"../package.json\" with { type: \"json\" };\nimport { runMain } from \"./main.ts\";\nimport { runProviderOnboarding, shouldStartProviderOnboarding } from \"./provider-onboarding.ts\";\nimport { loadStartupConfiguration, resolveStartupArgs, resolveStartupRuntime } from \"./startup.ts\";\n\ntry {\n\tconst configuration = await loadStartupConfiguration(process.cwd());\n\tprocess.exitCode = await runMain(resolveStartupArgs(process.argv.slice(2)), {\n\t\tversion: packageMetadata.version,\n\t\tcreateRuntime: (command) => {\n\t\t\tconst isInteractiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY);\n\t\t\tif (shouldStartProviderOnboarding(command, isInteractiveTerminal, configuration)) {\n\t\t\t\treturn runProviderOnboarding({ configuration, terminal: new ProcessTerminal() });\n\t\t\t}\n\t\t\treturn resolveStartupRuntime(configuration.environment, configuration.providers);\n\t\t},\n\t\tstdout: (text) => process.stdout.write(text),\n\t\tstderr: (text) => process.stderr.write(text),\n\t});\n} catch (cause) {\n\tconst message = cause instanceof Error ? cause.message : \"Unknown startup error\";\n\tprocess.stderr.write(`${message}\\n`);\n\tprocess.exitCode = 1;\n}\n"]}
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,eAAe,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAEnG,IAAI,CAAC;IACJ,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,QAAQ,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC3E,OAAO,EAAE,eAAe,CAAC,OAAO;QAChC,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE;YAC1B,MAAM,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACnF,IAAI,6BAA6B,CAAC,OAAO,EAAE,qBAAqB,EAAE,aAAa,CAAC,EAAE,CAAC;gBAClF,OAAO,qBAAqB,CAAC;oBAC5B,aAAa;oBACb,QAAQ,EAAE,IAAI,eAAe,EAAE;oBAC/B,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC;iBACrC,CAAC,CAAC;YACJ,CAAC;YACD,OAAO,qBAAqB,CAAC,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC1G,CAAC;QACD,oBAAoB,EAAE,aAAa;QACnC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;KAC5C,CAAC,CAAC;AACJ,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;IACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { ProcessTerminal } from \"@di-code/tui\";\nimport packageMetadata from \"../package.json\" with { type: \"json\" };\nimport { runMain } from \"./main.ts\";\nimport { runProviderOnboarding, shouldStartProviderOnboarding } from \"./provider-onboarding.ts\";\nimport { loadStartupConfiguration, resolveStartupArgs, resolveStartupRuntime } from \"./startup.ts\";\n\ntry {\n\tconst configuration = await loadStartupConfiguration(process.cwd());\n\tprocess.exitCode = await runMain(resolveStartupArgs(process.argv.slice(2)), {\n\t\tversion: packageMetadata.version,\n\t\tcreateRuntime: (command) => {\n\t\t\tconst isInteractiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY);\n\t\t\tif (shouldStartProviderOnboarding(command, isInteractiveTerminal, configuration)) {\n\t\t\t\treturn runProviderOnboarding({\n\t\t\t\t\tconfiguration,\n\t\t\t\t\tterminal: new ProcessTerminal(),\n\t\t\t\t\tagentDir: join(homedir(), \".di-code\"),\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn resolveStartupRuntime(configuration.environment, configuration.providers, configuration.defaults);\n\t\t},\n\t\tstartupConfiguration: configuration,\n\t\tstdout: (text) => process.stdout.write(text),\n\t\tstderr: (text) => process.stderr.write(text),\n\t});\n} catch (cause) {\n\tconst message = cause instanceof Error ? cause.message : \"Unknown startup error\";\n\tprocess.stderr.write(`${message}\\n`);\n\tprocess.exitCode = 1;\n}\n"]}
package/dist/main.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { Model, Provider } from "@di-code/ai";
2
2
  import { type CliCommand } from "./cli.ts";
3
3
  import { SessionManager } from "./core/session/session-manager.ts";
4
4
  import { type PrintIo } from "./modes/print.ts";
5
+ import type { StartupConfiguration } from "./startup.ts";
5
6
  export interface MainRuntime {
6
7
  readonly provider: Provider;
7
8
  readonly model: Model;
@@ -13,8 +14,9 @@ export interface MainOptions extends PrintIo {
13
14
  }>) => MainRuntime | undefined | Promise<MainRuntime | undefined>;
14
15
  readonly allowedRoot?: string;
15
16
  readonly agentDir?: string;
17
+ readonly startupConfiguration?: StartupConfiguration;
16
18
  readonly now?: () => number;
17
19
  }
18
- export declare function formatSessionLabel(manager: SessionManager): string;
20
+ export declare function formatSessionLabel(manager: SessionManager, timeZone?: string): string;
19
21
  export declare function runMain(args: readonly string[], options: MainOptions): Promise<number>;
20
22
  //# sourceMappingURL=main.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,UAAU,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAMnE,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,kBAAkB,CAAC;AAI9D,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,CACvB,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,KACzC,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AA0ED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAmBlE;AAuCD,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAiJ5F"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,KAAK,UAAU,EAAgC,MAAM,UAAU,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAMnE,OAAO,EAAE,KAAK,OAAO,EAAgB,MAAM,kBAAkB,CAAC;AAG9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACtB;AAED,MAAM,WAAW,WAAY,SAAQ,OAAO;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,CACvB,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,KACzC,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAChE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IACrD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B;AAkGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAmBrF;AAuCD,wBAAsB,OAAO,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAyJ5F"}
package/dist/main.js CHANGED
@@ -4,6 +4,7 @@ import { homedir } from "node:os";
4
4
  import { basename, dirname, extname, join, resolve } from "node:path";
5
5
  import { ProcessTerminal, TUI } from "@di-code/tui";
6
6
  import { runCli } from "./cli.js";
7
+ import { loadImageInputs } from "./core/image-input.js";
7
8
  import { loadResources } from "./core/resources/loader.js";
8
9
  import { SessionManager } from "./core/session/session-manager.js";
9
10
  import { AgentSession } from "./core/session.js";
@@ -75,16 +76,41 @@ async function selectStartupSession(command, allowedRoot, now) {
75
76
  deferCreate: true,
76
77
  });
77
78
  }
78
- function formatSessionTimestamp(timestamp, fallback) {
79
+ function formatSessionTimestamp(timestamp, fallback, timeZone) {
79
80
  const date = new Date(timestamp);
80
- const isoTimestamp = Number.isNaN(date.getTime()) ? fallback : date.toISOString();
81
- return isoTimestamp.slice(0, 16).replace("T", " ");
81
+ if (Number.isNaN(date.getTime()))
82
+ return fallback;
83
+ try {
84
+ const parts = new Map(new Intl.DateTimeFormat("en-CA", {
85
+ timeZone: timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,
86
+ year: "numeric",
87
+ month: "2-digit",
88
+ day: "2-digit",
89
+ hour: "2-digit",
90
+ minute: "2-digit",
91
+ hourCycle: "h23",
92
+ })
93
+ .formatToParts(date)
94
+ .filter((part) => part.type !== "literal")
95
+ .map((part) => [part.type, part.value]));
96
+ const year = parts.get("year");
97
+ const month = parts.get("month");
98
+ const day = parts.get("day");
99
+ const hour = parts.get("hour");
100
+ const minute = parts.get("minute");
101
+ if (!year || !month || !day || !hour || !minute)
102
+ return fallback;
103
+ return `${year}-${month}-${day} ${hour}:${minute}`;
104
+ }
105
+ catch {
106
+ return fallback;
107
+ }
82
108
  }
83
- export function formatSessionLabel(manager) {
109
+ export function formatSessionLabel(manager, timeZone) {
84
110
  const firstUserEntry = manager.entries.find((entry) => entry.type === "message" && entry.message.role === "user");
85
111
  const fileName = basename(manager.filePath, extname(manager.filePath));
86
112
  if (firstUserEntry?.type !== "message" || firstUserEntry.message.role !== "user") {
87
- return `${fileName} (${formatSessionTimestamp(Date.parse(manager.header.timestamp), manager.header.timestamp)})`;
113
+ return `${fileName} (${formatSessionTimestamp(Date.parse(manager.header.timestamp), manager.header.timestamp, timeZone)})`;
88
114
  }
89
115
  const question = firstUserEntry.message.content
90
116
  .filter((content) => content.type === "text")
@@ -95,7 +121,7 @@ export function formatSessionLabel(manager) {
95
121
  const label = question.length > MAX_SESSION_QUESTION_LENGTH
96
122
  ? `${question.slice(0, MAX_SESSION_QUESTION_LENGTH - 3)}...`
97
123
  : question || fileName;
98
- const timestamp = formatSessionTimestamp(firstUserEntry.message.timestamp, firstUserEntry.timestamp);
124
+ const timestamp = formatSessionTimestamp(firstUserEntry.message.timestamp, firstUserEntry.timestamp, timeZone);
99
125
  return `${label} (${timestamp})`;
100
126
  }
101
127
  async function sessionChoices(sessionDirectory, currentFile, open) {
@@ -208,10 +234,15 @@ export async function runMain(args, options) {
208
234
  sessionManager: manager,
209
235
  extensionHost: extensions.host,
210
236
  });
237
+ const imagePaths = command.imagePaths ?? [];
238
+ const promptRunner = {
239
+ prompt: async (text) => session.promptWithImages(text, await loadImageInputs(imagePaths, allowedRoot)),
240
+ subscribe: session.subscribe.bind(session),
241
+ };
211
242
  if (command.mode === "json") {
212
243
  await extensions.host.emit({ type: "session_start", cwd: allowedRoot });
213
244
  try {
214
- return await runJsonMode(command.prompt, session, options);
245
+ return await runJsonMode(command.prompt, promptRunner, options);
215
246
  }
216
247
  finally {
217
248
  await extensions.host.emit({ type: "session_shutdown", reason: "user" });
@@ -224,6 +255,9 @@ export async function runMain(args, options) {
224
255
  session,
225
256
  tui,
226
257
  extensionHost: extensions.host,
258
+ ...(options.startupConfiguration
259
+ ? { providerOnboarding: { configuration: options.startupConfiguration, agentDir } }
260
+ : {}),
227
261
  sessions: [
228
262
  {
229
263
  id: "new-session",
@@ -269,7 +303,7 @@ export async function runMain(args, options) {
269
303
  }
270
304
  await extensions.host.emit({ type: "session_start", cwd: allowedRoot });
271
305
  try {
272
- return await runPrintMode(command.prompt, session, options);
306
+ return await runPrintMode(command.prompt, promptRunner, options);
273
307
  }
274
308
  finally {
275
309
  await extensions.host.emit({ type: "session_shutdown", reason: "user" });
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { access, readdir, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, extname, join, resolve } from \"node:path\";\nimport type { Model, Provider } from \"@di-code/ai\";\nimport { ProcessTerminal, TUI } from \"@di-code/tui\";\nimport { type CliCommand, type CliDependencies, runCli } from \"./cli.ts\";\nimport { loadResources } from \"./core/resources/loader.ts\";\nimport { SessionManager } from \"./core/session/session-manager.ts\";\nimport { AgentSession } from \"./core/session.ts\";\nimport { buildSystemPrompt } from \"./core/system-prompt.ts\";\nimport { ProjectTrustManager } from \"./extensions/trust.ts\";\nimport { InteractiveMode } from \"./modes/interactive.ts\";\nimport { runJsonMode } from \"./modes/json.ts\";\nimport { type PrintIo, runPrintMode } from \"./modes/print.ts\";\nimport { loadPlugins } from \"./plugins/loader.ts\";\nimport { PluginManager } from \"./plugins/manager.ts\";\n\nexport interface MainRuntime {\n\treadonly provider: Provider;\n\treadonly model: Model;\n}\n\nexport interface MainOptions extends PrintIo {\n\treadonly version: string;\n\treadonly createRuntime: (\n\t\tcommand: Extract<CliCommand, { kind: \"run\" }>,\n\t) => MainRuntime | undefined | Promise<MainRuntime | undefined>;\n\treadonly allowedRoot?: string;\n\treadonly agentDir?: string;\n\treadonly now?: () => number;\n}\n\nconst DEFAULT_SESSION_DIRECTORY = join(\".di-code\", \"sessions\");\nconst MAX_SESSION_QUESTION_LENGTH = 72;\n\nasync function openOrCreateSession(filePath: string, cwd: string, now: () => number): Promise<SessionManager> {\n\ttry {\n\t\tawait access(filePath);\n\t\treturn await SessionManager.open(filePath, { now });\n\t} catch (cause) {\n\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t\treturn SessionManager.create({ filePath, cwd, now, deferCreate: true });\n\t}\n}\n\nfunction newSessionPath(sessionDirectory: string, now: () => number): string {\n\treturn join(sessionDirectory, `session-${now()}-${randomUUID().slice(0, 8)}.jsonl`);\n}\n\nasync function mostRecentSessionPath(sessionDirectory: string): Promise<string | undefined> {\n\tlet names: string[];\n\ttry {\n\t\tnames = (await readdir(sessionDirectory, { withFileTypes: true }))\n\t\t\t.filter((entry) => entry.isFile() && extname(entry.name) === \".jsonl\")\n\t\t\t.map((entry) => entry.name);\n\t} catch (cause) {\n\t\tif (cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\") return undefined;\n\t\tthrow cause;\n\t}\n\n\tconst candidates = await Promise.all(\n\t\tnames.map(async (name) => {\n\t\t\tconst filePath = join(sessionDirectory, name);\n\t\t\ttry {\n\t\t\t\treturn { filePath, modifiedAt: (await stat(filePath)).mtimeMs };\n\t\t\t} catch (cause) {\n\t\t\t\tif (cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\") return undefined;\n\t\t\t\tthrow cause;\n\t\t\t}\n\t\t}),\n\t);\n\treturn candidates\n\t\t.filter((candidate): candidate is { filePath: string; modifiedAt: number } => candidate !== undefined)\n\t\t.sort((left, right) => right.modifiedAt - left.modifiedAt || right.filePath.localeCompare(left.filePath))[0]\n\t\t?.filePath;\n}\n\nasync function selectStartupSession(\n\tcommand: Extract<CliCommand, { kind: \"run\" }>,\n\tallowedRoot: string,\n\tnow: () => number,\n): Promise<SessionManager> {\n\tconst sessionDirectory = resolve(allowedRoot, DEFAULT_SESSION_DIRECTORY);\n\tif (command.sessionPath !== undefined) {\n\t\treturn openOrCreateSession(resolve(allowedRoot, command.sessionPath), allowedRoot, now);\n\t}\n\tif (command.continueSession) {\n\t\tconst recentPath = await mostRecentSessionPath(sessionDirectory);\n\t\tif (recentPath !== undefined) return SessionManager.open(recentPath, { now });\n\t}\n\treturn SessionManager.create({\n\t\tfilePath: newSessionPath(sessionDirectory, now),\n\t\tcwd: allowedRoot,\n\t\tnow,\n\t\tdeferCreate: true,\n\t});\n}\n\nfunction formatSessionTimestamp(timestamp: number, fallback: string): string {\n\tconst date = new Date(timestamp);\n\tconst isoTimestamp = Number.isNaN(date.getTime()) ? fallback : date.toISOString();\n\treturn isoTimestamp.slice(0, 16).replace(\"T\", \" \");\n}\n\nexport function formatSessionLabel(manager: SessionManager): string {\n\tconst firstUserEntry = manager.entries.find((entry) => entry.type === \"message\" && entry.message.role === \"user\");\n\tconst fileName = basename(manager.filePath, extname(manager.filePath));\n\tif (firstUserEntry?.type !== \"message\" || firstUserEntry.message.role !== \"user\") {\n\t\treturn `${fileName} (${formatSessionTimestamp(Date.parse(manager.header.timestamp), manager.header.timestamp)})`;\n\t}\n\n\tconst question = firstUserEntry.message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\tconst label =\n\t\tquestion.length > MAX_SESSION_QUESTION_LENGTH\n\t\t\t? `${question.slice(0, MAX_SESSION_QUESTION_LENGTH - 3)}...`\n\t\t\t: question || fileName;\n\tconst timestamp = formatSessionTimestamp(firstUserEntry.message.timestamp, firstUserEntry.timestamp);\n\treturn `${label} (${timestamp})`;\n}\n\nasync function sessionChoices(\n\tsessionDirectory: string,\n\tcurrentFile: string,\n\topen: (filePath: string) => Promise<AgentSession>,\n): Promise<readonly { id: string; label: string; description: string; open: () => Promise<AgentSession> }[]> {\n\tlet names: string[] = [];\n\ttry {\n\t\tnames = (await readdir(sessionDirectory, { withFileTypes: true }))\n\t\t\t.filter((entry) => entry.isFile() && extname(entry.name) === \".jsonl\")\n\t\t\t.map((entry) => entry.name)\n\t\t\t.sort();\n\t} catch (cause) {\n\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t}\n\n\treturn Promise.all(\n\t\tnames\n\t\t\t.filter((name) => resolve(sessionDirectory, name) !== resolve(currentFile))\n\t\t\t.map(async (name) => {\n\t\t\t\tconst filePath = join(sessionDirectory, name);\n\t\t\t\tconst id = basename(name, extname(name));\n\t\t\t\tlet label = id;\n\t\t\t\ttry {\n\t\t\t\t\tlabel = formatSessionLabel(await SessionManager.open(filePath));\n\t\t\t\t} catch {\n\t\t\t\t\t// Keep damaged sessions selectable so opening one can report the detailed load error.\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tid,\n\t\t\t\t\tlabel,\n\t\t\t\t\tdescription: filePath,\n\t\t\t\t\topen: () => open(filePath),\n\t\t\t\t};\n\t\t\t}),\n\t);\n}\n\nexport async function runMain(args: readonly string[], options: MainOptions): Promise<number> {\n\tconst dependencies: CliDependencies = {\n\t\tstdout: options.stdout,\n\t\tstderr: options.stderr,\n\t\tversion: options.version,\n\t\tplugin: async (command) => {\n\t\t\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\t\t\tconst manager = new PluginManager({ agentDir });\n\t\t\ttry {\n\t\t\t\tswitch (command.action) {\n\t\t\t\t\tcase \"list\":\n\t\t\t\t\t\tfor (const plugin of await manager.list())\n\t\t\t\t\t\t\toptions.stdout(`${plugin.id}\\t${plugin.enabled ? \"enabled\" : \"disabled\"}\\t${plugin.manifest.version}\\n`);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"install\": {\n\t\t\t\t\t\tconst plugin = await manager.install(command.argument as string);\n\t\t\t\t\t\toptions.stdout(`Installed ${plugin.id}\\n`);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"enable\":\n\t\t\t\t\t\tawait manager.enable(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"disable\":\n\t\t\t\t\t\tawait manager.disable(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"update\":\n\t\t\t\t\t\tawait manager.update(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tawait manager.remove(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t} catch (cause) {\n\t\t\t\toptions.stderr(`${cause instanceof Error ? cause.message : String(cause)}\\n`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t},\n\t\trun: async (command) => {\n\t\t\tconst allowedRoot = resolve(options.allowedRoot ?? process.cwd());\n\t\t\tconst now = options.now ?? Date.now;\n\t\t\tconst runtime = await options.createRuntime(command);\n\t\t\tif (runtime === undefined) return 0;\n\t\t\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\t\t\tconst trustManager = new ProjectTrustManager(join(agentDir, \"trust.json\"));\n\t\t\tif (command.projectTrust !== undefined) await trustManager.set(allowedRoot, command.projectTrust);\n\t\t\tconst resources = await loadResources({\n\t\t\t\tcwd: allowedRoot,\n\t\t\t\tagentDir,\n\t\t\t\tprojectTrusted: (await trustManager.get(allowedRoot)) === true,\n\t\t\t\tnoSkills: command.noSkills,\n\t\t\t\tnoContextFiles: command.noContextFiles,\n\t\t\t\tskillPaths: command.skillPaths,\n\t\t\t});\n\t\t\tconst extensions = await loadPlugins({\n\t\t\t\tcwd: allowedRoot,\n\t\t\t\tagentDir,\n\t\t\t\ttrustManager,\n\t\t\t\tmode: command.mode,\n\t\t\t});\n\t\t\tfor (const diagnostic of extensions.diagnostics) {\n\t\t\t\toptions.stderr(\n\t\t\t\t\t`${JSON.stringify({ type: \"plugin_diagnostic\", pluginId: diagnostic.pluginId, stage: diagnostic.stage, sourcePath: diagnostic.sourcePath, severity: diagnostic.severity, message: diagnostic.message })}\\n`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst systemPrompt = buildSystemPrompt({ cwd: allowedRoot, ...resources });\n\t\t\tconst manager = await selectStartupSession(command, allowedRoot, now);\n\t\t\tconst sessionFile = manager.filePath;\n\t\t\tconst session = new AgentSession({\n\t\t\t\tallowedRoot,\n\t\t\t\tprovider: runtime.provider,\n\t\t\t\tmodel: runtime.model,\n\t\t\t\tsystemPrompt,\n\t\t\t\tskills: resources.skills,\n\t\t\t\tnow: options.now,\n\t\t\t\tsessionManager: manager,\n\t\t\t\textensionHost: extensions.host,\n\t\t\t});\n\t\t\tif (command.mode === \"json\") {\n\t\t\t\tawait extensions.host.emit({ type: \"session_start\", cwd: allowedRoot });\n\t\t\t\ttry {\n\t\t\t\t\treturn await runJsonMode(command.prompt, session, options);\n\t\t\t\t} finally {\n\t\t\t\t\tawait extensions.host.emit({ type: \"session_shutdown\", reason: \"user\" });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (command.mode === \"interactive\") {\n\t\t\t\tconst terminal = new ProcessTerminal();\n\t\t\t\tconst tui = new TUI(terminal);\n\t\t\t\tconst mode = new InteractiveMode({\n\t\t\t\t\tsession,\n\t\t\t\t\ttui,\n\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\tsessions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"new-session\",\n\t\t\t\t\t\t\tlabel: \"New session\",\n\t\t\t\t\t\t\tdescription: \"Start a new persistent conversation.\",\n\t\t\t\t\t\t\topen: async () => {\n\t\t\t\t\t\t\t\tconst filePath = newSessionPath(dirname(sessionFile), now);\n\t\t\t\t\t\t\t\tconst nextManager = await SessionManager.create({\n\t\t\t\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\t\t\t\tcwd: allowedRoot,\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\tdeferCreate: true,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn new AgentSession({\n\t\t\t\t\t\t\t\t\tallowedRoot,\n\t\t\t\t\t\t\t\t\tprovider: runtime.provider,\n\t\t\t\t\t\t\t\t\tmodel: runtime.model,\n\t\t\t\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\t\t\t\tskills: resources.skills,\n\t\t\t\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\t\t\t\tsessionManager: nextManager,\n\t\t\t\t\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...(await sessionChoices(dirname(sessionFile), sessionFile, async (filePath) => {\n\t\t\t\t\t\t\tconst nextManager = await SessionManager.open(filePath, { now });\n\t\t\t\t\t\t\treturn new AgentSession({\n\t\t\t\t\t\t\t\tallowedRoot,\n\t\t\t\t\t\t\t\tprovider: runtime.provider,\n\t\t\t\t\t\t\t\tmodel: runtime.model,\n\t\t\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\t\t\tskills: resources.skills,\n\t\t\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\t\t\tsessionManager: nextManager,\n\t\t\t\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t})),\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tmode.start(command.prompt);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tawait extensions.host.emit({ type: \"session_start\", cwd: allowedRoot });\n\t\t\ttry {\n\t\t\t\treturn await runPrintMode(command.prompt, session, options);\n\t\t\t} finally {\n\t\t\t\tawait extensions.host.emit({ type: \"session_shutdown\", reason: \"user\" });\n\t\t\t}\n\t\t},\n\t};\n\n\treturn runCli(args, dependencies);\n}\n"]}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { access, readdir, stat } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, extname, join, resolve } from \"node:path\";\nimport type { Model, Provider } from \"@di-code/ai\";\nimport { ProcessTerminal, TUI } from \"@di-code/tui\";\nimport { type CliCommand, type CliDependencies, runCli } from \"./cli.ts\";\nimport { loadImageInputs } from \"./core/image-input.ts\";\nimport { loadResources } from \"./core/resources/loader.ts\";\nimport { SessionManager } from \"./core/session/session-manager.ts\";\nimport { AgentSession } from \"./core/session.ts\";\nimport { buildSystemPrompt } from \"./core/system-prompt.ts\";\nimport { ProjectTrustManager } from \"./extensions/trust.ts\";\nimport { InteractiveMode } from \"./modes/interactive.ts\";\nimport { runJsonMode } from \"./modes/json.ts\";\nimport { type PrintIo, runPrintMode } from \"./modes/print.ts\";\nimport { loadPlugins } from \"./plugins/loader.ts\";\nimport { PluginManager } from \"./plugins/manager.ts\";\nimport type { StartupConfiguration } from \"./startup.ts\";\n\nexport interface MainRuntime {\n\treadonly provider: Provider;\n\treadonly model: Model;\n}\n\nexport interface MainOptions extends PrintIo {\n\treadonly version: string;\n\treadonly createRuntime: (\n\t\tcommand: Extract<CliCommand, { kind: \"run\" }>,\n\t) => MainRuntime | undefined | Promise<MainRuntime | undefined>;\n\treadonly allowedRoot?: string;\n\treadonly agentDir?: string;\n\treadonly startupConfiguration?: StartupConfiguration;\n\treadonly now?: () => number;\n}\n\nconst DEFAULT_SESSION_DIRECTORY = join(\".di-code\", \"sessions\");\nconst MAX_SESSION_QUESTION_LENGTH = 72;\n\nasync function openOrCreateSession(filePath: string, cwd: string, now: () => number): Promise<SessionManager> {\n\ttry {\n\t\tawait access(filePath);\n\t\treturn await SessionManager.open(filePath, { now });\n\t} catch (cause) {\n\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t\treturn SessionManager.create({ filePath, cwd, now, deferCreate: true });\n\t}\n}\n\nfunction newSessionPath(sessionDirectory: string, now: () => number): string {\n\treturn join(sessionDirectory, `session-${now()}-${randomUUID().slice(0, 8)}.jsonl`);\n}\n\nasync function mostRecentSessionPath(sessionDirectory: string): Promise<string | undefined> {\n\tlet names: string[];\n\ttry {\n\t\tnames = (await readdir(sessionDirectory, { withFileTypes: true }))\n\t\t\t.filter((entry) => entry.isFile() && extname(entry.name) === \".jsonl\")\n\t\t\t.map((entry) => entry.name);\n\t} catch (cause) {\n\t\tif (cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\") return undefined;\n\t\tthrow cause;\n\t}\n\n\tconst candidates = await Promise.all(\n\t\tnames.map(async (name) => {\n\t\t\tconst filePath = join(sessionDirectory, name);\n\t\t\ttry {\n\t\t\t\treturn { filePath, modifiedAt: (await stat(filePath)).mtimeMs };\n\t\t\t} catch (cause) {\n\t\t\t\tif (cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\") return undefined;\n\t\t\t\tthrow cause;\n\t\t\t}\n\t\t}),\n\t);\n\treturn candidates\n\t\t.filter((candidate): candidate is { filePath: string; modifiedAt: number } => candidate !== undefined)\n\t\t.sort((left, right) => right.modifiedAt - left.modifiedAt || right.filePath.localeCompare(left.filePath))[0]\n\t\t?.filePath;\n}\n\nasync function selectStartupSession(\n\tcommand: Extract<CliCommand, { kind: \"run\" }>,\n\tallowedRoot: string,\n\tnow: () => number,\n): Promise<SessionManager> {\n\tconst sessionDirectory = resolve(allowedRoot, DEFAULT_SESSION_DIRECTORY);\n\tif (command.sessionPath !== undefined) {\n\t\treturn openOrCreateSession(resolve(allowedRoot, command.sessionPath), allowedRoot, now);\n\t}\n\tif (command.continueSession) {\n\t\tconst recentPath = await mostRecentSessionPath(sessionDirectory);\n\t\tif (recentPath !== undefined) return SessionManager.open(recentPath, { now });\n\t}\n\treturn SessionManager.create({\n\t\tfilePath: newSessionPath(sessionDirectory, now),\n\t\tcwd: allowedRoot,\n\t\tnow,\n\t\tdeferCreate: true,\n\t});\n}\n\nfunction formatSessionTimestamp(timestamp: number, fallback: string, timeZone?: string): string {\n\tconst date = new Date(timestamp);\n\tif (Number.isNaN(date.getTime())) return fallback;\n\ttry {\n\t\tconst parts = new Map(\n\t\t\tnew Intl.DateTimeFormat(\"en-CA\", {\n\t\t\t\ttimeZone: timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n\t\t\t\tyear: \"numeric\",\n\t\t\t\tmonth: \"2-digit\",\n\t\t\t\tday: \"2-digit\",\n\t\t\t\thour: \"2-digit\",\n\t\t\t\tminute: \"2-digit\",\n\t\t\t\thourCycle: \"h23\",\n\t\t\t})\n\t\t\t\t.formatToParts(date)\n\t\t\t\t.filter((part) => part.type !== \"literal\")\n\t\t\t\t.map((part) => [part.type, part.value]),\n\t\t);\n\t\tconst year = parts.get(\"year\");\n\t\tconst month = parts.get(\"month\");\n\t\tconst day = parts.get(\"day\");\n\t\tconst hour = parts.get(\"hour\");\n\t\tconst minute = parts.get(\"minute\");\n\t\tif (!year || !month || !day || !hour || !minute) return fallback;\n\t\treturn `${year}-${month}-${day} ${hour}:${minute}`;\n\t} catch {\n\t\treturn fallback;\n\t}\n}\n\nexport function formatSessionLabel(manager: SessionManager, timeZone?: string): string {\n\tconst firstUserEntry = manager.entries.find((entry) => entry.type === \"message\" && entry.message.role === \"user\");\n\tconst fileName = basename(manager.filePath, extname(manager.filePath));\n\tif (firstUserEntry?.type !== \"message\" || firstUserEntry.message.role !== \"user\") {\n\t\treturn `${fileName} (${formatSessionTimestamp(Date.parse(manager.header.timestamp), manager.header.timestamp, timeZone)})`;\n\t}\n\n\tconst question = firstUserEntry.message.content\n\t\t.filter((content) => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n\tconst label =\n\t\tquestion.length > MAX_SESSION_QUESTION_LENGTH\n\t\t\t? `${question.slice(0, MAX_SESSION_QUESTION_LENGTH - 3)}...`\n\t\t\t: question || fileName;\n\tconst timestamp = formatSessionTimestamp(firstUserEntry.message.timestamp, firstUserEntry.timestamp, timeZone);\n\treturn `${label} (${timestamp})`;\n}\n\nasync function sessionChoices(\n\tsessionDirectory: string,\n\tcurrentFile: string,\n\topen: (filePath: string) => Promise<AgentSession>,\n): Promise<readonly { id: string; label: string; description: string; open: () => Promise<AgentSession> }[]> {\n\tlet names: string[] = [];\n\ttry {\n\t\tnames = (await readdir(sessionDirectory, { withFileTypes: true }))\n\t\t\t.filter((entry) => entry.isFile() && extname(entry.name) === \".jsonl\")\n\t\t\t.map((entry) => entry.name)\n\t\t\t.sort();\n\t} catch (cause) {\n\t\tif (!(cause instanceof Error && \"code\" in cause && cause.code === \"ENOENT\")) throw cause;\n\t}\n\n\treturn Promise.all(\n\t\tnames\n\t\t\t.filter((name) => resolve(sessionDirectory, name) !== resolve(currentFile))\n\t\t\t.map(async (name) => {\n\t\t\t\tconst filePath = join(sessionDirectory, name);\n\t\t\t\tconst id = basename(name, extname(name));\n\t\t\t\tlet label = id;\n\t\t\t\ttry {\n\t\t\t\t\tlabel = formatSessionLabel(await SessionManager.open(filePath));\n\t\t\t\t} catch {\n\t\t\t\t\t// Keep damaged sessions selectable so opening one can report the detailed load error.\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tid,\n\t\t\t\t\tlabel,\n\t\t\t\t\tdescription: filePath,\n\t\t\t\t\topen: () => open(filePath),\n\t\t\t\t};\n\t\t\t}),\n\t);\n}\n\nexport async function runMain(args: readonly string[], options: MainOptions): Promise<number> {\n\tconst dependencies: CliDependencies = {\n\t\tstdout: options.stdout,\n\t\tstderr: options.stderr,\n\t\tversion: options.version,\n\t\tplugin: async (command) => {\n\t\t\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\t\t\tconst manager = new PluginManager({ agentDir });\n\t\t\ttry {\n\t\t\t\tswitch (command.action) {\n\t\t\t\t\tcase \"list\":\n\t\t\t\t\t\tfor (const plugin of await manager.list())\n\t\t\t\t\t\t\toptions.stdout(`${plugin.id}\\t${plugin.enabled ? \"enabled\" : \"disabled\"}\\t${plugin.manifest.version}\\n`);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"install\": {\n\t\t\t\t\t\tconst plugin = await manager.install(command.argument as string);\n\t\t\t\t\t\toptions.stdout(`Installed ${plugin.id}\\n`);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\t\t\t\t\tcase \"enable\":\n\t\t\t\t\t\tawait manager.enable(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"disable\":\n\t\t\t\t\t\tawait manager.disable(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"update\":\n\t\t\t\t\t\tawait manager.update(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\tcase \"remove\":\n\t\t\t\t\t\tawait manager.remove(command.argument as string);\n\t\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t} catch (cause) {\n\t\t\t\toptions.stderr(`${cause instanceof Error ? cause.message : String(cause)}\\n`);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t},\n\t\trun: async (command) => {\n\t\t\tconst allowedRoot = resolve(options.allowedRoot ?? process.cwd());\n\t\t\tconst now = options.now ?? Date.now;\n\t\t\tconst runtime = await options.createRuntime(command);\n\t\t\tif (runtime === undefined) return 0;\n\t\t\tconst agentDir = resolve(options.agentDir ?? join(homedir(), \".di-code\"));\n\t\t\tconst trustManager = new ProjectTrustManager(join(agentDir, \"trust.json\"));\n\t\t\tif (command.projectTrust !== undefined) await trustManager.set(allowedRoot, command.projectTrust);\n\t\t\tconst resources = await loadResources({\n\t\t\t\tcwd: allowedRoot,\n\t\t\t\tagentDir,\n\t\t\t\tprojectTrusted: (await trustManager.get(allowedRoot)) === true,\n\t\t\t\tnoSkills: command.noSkills,\n\t\t\t\tnoContextFiles: command.noContextFiles,\n\t\t\t\tskillPaths: command.skillPaths,\n\t\t\t});\n\t\t\tconst extensions = await loadPlugins({\n\t\t\t\tcwd: allowedRoot,\n\t\t\t\tagentDir,\n\t\t\t\ttrustManager,\n\t\t\t\tmode: command.mode,\n\t\t\t});\n\t\t\tfor (const diagnostic of extensions.diagnostics) {\n\t\t\t\toptions.stderr(\n\t\t\t\t\t`${JSON.stringify({ type: \"plugin_diagnostic\", pluginId: diagnostic.pluginId, stage: diagnostic.stage, sourcePath: diagnostic.sourcePath, severity: diagnostic.severity, message: diagnostic.message })}\\n`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst systemPrompt = buildSystemPrompt({ cwd: allowedRoot, ...resources });\n\t\t\tconst manager = await selectStartupSession(command, allowedRoot, now);\n\t\t\tconst sessionFile = manager.filePath;\n\t\t\tconst session = new AgentSession({\n\t\t\t\tallowedRoot,\n\t\t\t\tprovider: runtime.provider,\n\t\t\t\tmodel: runtime.model,\n\t\t\t\tsystemPrompt,\n\t\t\t\tskills: resources.skills,\n\t\t\t\tnow: options.now,\n\t\t\t\tsessionManager: manager,\n\t\t\t\textensionHost: extensions.host,\n\t\t\t});\n\t\t\tconst imagePaths = command.imagePaths ?? [];\n\t\t\tconst promptRunner = {\n\t\t\t\tprompt: async (text: string) => session.promptWithImages(text, await loadImageInputs(imagePaths, allowedRoot)),\n\t\t\t\tsubscribe: session.subscribe.bind(session),\n\t\t\t};\n\t\t\tif (command.mode === \"json\") {\n\t\t\t\tawait extensions.host.emit({ type: \"session_start\", cwd: allowedRoot });\n\t\t\t\ttry {\n\t\t\t\t\treturn await runJsonMode(command.prompt, promptRunner, options);\n\t\t\t\t} finally {\n\t\t\t\t\tawait extensions.host.emit({ type: \"session_shutdown\", reason: \"user\" });\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (command.mode === \"interactive\") {\n\t\t\t\tconst terminal = new ProcessTerminal();\n\t\t\t\tconst tui = new TUI(terminal);\n\t\t\t\tconst mode = new InteractiveMode({\n\t\t\t\t\tsession,\n\t\t\t\t\ttui,\n\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\t...(options.startupConfiguration\n\t\t\t\t\t\t? { providerOnboarding: { configuration: options.startupConfiguration, agentDir } }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tsessions: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tid: \"new-session\",\n\t\t\t\t\t\t\tlabel: \"New session\",\n\t\t\t\t\t\t\tdescription: \"Start a new persistent conversation.\",\n\t\t\t\t\t\t\topen: async () => {\n\t\t\t\t\t\t\t\tconst filePath = newSessionPath(dirname(sessionFile), now);\n\t\t\t\t\t\t\t\tconst nextManager = await SessionManager.create({\n\t\t\t\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\t\t\t\tcwd: allowedRoot,\n\t\t\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t\t\t\tdeferCreate: true,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn new AgentSession({\n\t\t\t\t\t\t\t\t\tallowedRoot,\n\t\t\t\t\t\t\t\t\tprovider: runtime.provider,\n\t\t\t\t\t\t\t\t\tmodel: runtime.model,\n\t\t\t\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\t\t\t\tskills: resources.skills,\n\t\t\t\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\t\t\t\tsessionManager: nextManager,\n\t\t\t\t\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...(await sessionChoices(dirname(sessionFile), sessionFile, async (filePath) => {\n\t\t\t\t\t\t\tconst nextManager = await SessionManager.open(filePath, { now });\n\t\t\t\t\t\t\treturn new AgentSession({\n\t\t\t\t\t\t\t\tallowedRoot,\n\t\t\t\t\t\t\t\tprovider: runtime.provider,\n\t\t\t\t\t\t\t\tmodel: runtime.model,\n\t\t\t\t\t\t\t\tsystemPrompt,\n\t\t\t\t\t\t\t\tskills: resources.skills,\n\t\t\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\t\t\tsessionManager: nextManager,\n\t\t\t\t\t\t\t\textensionHost: extensions.host,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t})),\n\t\t\t\t\t],\n\t\t\t\t});\n\t\t\t\tmode.start(command.prompt);\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tawait extensions.host.emit({ type: \"session_start\", cwd: allowedRoot });\n\t\t\ttry {\n\t\t\t\treturn await runPrintMode(command.prompt, promptRunner, options);\n\t\t\t} finally {\n\t\t\t\tawait extensions.host.emit({ type: \"session_shutdown\", reason: \"user\" });\n\t\t\t}\n\t\t},\n\t};\n\n\treturn runCli(args, dependencies);\n}\n"]}
@@ -3,6 +3,7 @@ import type { InteractiveState } from "./interactive-state.ts";
3
3
  export interface InteractiveViewState extends InteractiveState {
4
4
  readonly model: string;
5
5
  readonly theme: "dark" | "light";
6
+ readonly pasteImageShortcut?: string;
6
7
  }
7
8
  export declare class InteractiveHeader implements Component {
8
9
  private readonly readState;
@@ -34,8 +35,10 @@ export interface AutocompleteMenuState {
34
35
  }
35
36
  export declare class AutocompleteMenu implements Component {
36
37
  private readonly readState;
38
+ private readonly box;
37
39
  constructor(readState: () => AutocompleteMenuState);
38
40
  invalidate(): void;
39
41
  render(width: number): string[];
42
+ private renderItems;
40
43
  }
41
44
  //# sourceMappingURL=interactive-components.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactive-components.d.ts","sourceRoot":"","sources":["../../src/modes/interactive-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEhE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AA2DD,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAW/B;AAED,qBAAa,eAAgB,YAAW,SAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA4D/B;AAED,qBAAa,mBAAoB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAS/B;AAED,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkB/B;AAQD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,gBAAiB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;gBAE5C,SAAS,EAAE,MAAM,qBAAqB;IAIlD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAQ/B"}
1
+ {"version":3,"file":"interactive-components.d.ts","sourceRoot":"","sources":["../../src/modes/interactive-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAiB,MAAM,cAAc,CAAC;AAI/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,oBAAqB,SAAQ,gBAAgB;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACrC;AAwFD,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAW/B;AAED,qBAAa,eAAgB,YAAW,SAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CA4E/B;AAED,qBAAa,mBAAoB,YAAW,SAAS;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAM/B;AAED,qBAAa,iBAAkB,YAAW,SAAS;IAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6B;gBAE3C,SAAS,EAAE,MAAM,oBAAoB;IAIjD,UAAU,IAAI,IAAI;IAElB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkB/B;AAQD,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,gBAAiB,YAAW,SAAS;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;IACxD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;gBAEd,SAAS,EAAE,MAAM,qBAAqB;IAWlD,UAAU,IAAI,IAAI;IAIlB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAI/B,OAAO,CAAC,WAAW;CAanB"}
@@ -1,4 +1,6 @@
1
- import { Markdown, Text, truncateToWidth, visibleWidth } from "@di-code/tui";
1
+ import { Box, Markdown, Text, truncateToWidth, visibleWidth } from "@di-code/tui";
2
+ import { highlightCode } from "../utils/syntax-highlight.js";
3
+ import { renderDiff } from "./interactive-diff.js";
2
4
  const RESET = "\x1b[0m";
3
5
  const BOLD = "\x1b[1m";
4
6
  const MAX_VISIBLE_TOOL_ITEMS = 6;
@@ -11,6 +13,7 @@ function paletteFor(theme) {
11
13
  dim: "\x1b[38;5;242m",
12
14
  error: "\x1b[38;5;160m",
13
15
  success: "\x1b[38;5;28m",
16
+ userBackground: "\x1b[48;2;239;246;255m",
14
17
  warning: "\x1b[38;5;130m",
15
18
  }
16
19
  : {
@@ -19,12 +22,36 @@ function paletteFor(theme) {
19
22
  dim: "\x1b[38;5;245m",
20
23
  error: "\x1b[38;5;210m",
21
24
  success: "\x1b[38;5;114m",
25
+ userBackground: "\x1b[48;2;31;39;50m",
22
26
  warning: "\x1b[38;5;222m",
23
27
  };
24
28
  }
25
29
  function paint(color, text, bold = false) {
26
30
  return `${color}${bold ? BOLD : ""}${text}${RESET}`;
27
31
  }
32
+ function paintBackground(background, text) {
33
+ return `${background}${text}${RESET}`;
34
+ }
35
+ function markdownThemeFor(colors) {
36
+ return {
37
+ heading: (text) => paint(colors.assistant, text, true),
38
+ link: (text) => paint(colors.accent, text),
39
+ linkUrl: (text) => paint(colors.dim, text),
40
+ code: (text) => paint(colors.warning, text),
41
+ codeBlock: (text) => paint(colors.assistant, text),
42
+ codeBlockBorder: (text) => paint(colors.dim, text),
43
+ quote: (text) => paint(colors.dim, text),
44
+ quoteBorder: (text) => paint(colors.dim, text),
45
+ hr: (text) => paint(colors.dim, text),
46
+ listBullet: (text) => paint(colors.accent, text),
47
+ bold: (text) => paint(colors.assistant, text, true),
48
+ italic: (text) => `\x1b[3m${text}${RESET}`,
49
+ strikethrough: (text) => `\x1b[9m${text}${RESET}`,
50
+ underline: (text) => `\x1b[4m${text}${RESET}`,
51
+ highlightCode: (code, language) => (language ? highlightCode(code, language) : undefined) ??
52
+ code.split("\n").map((line) => paint(colors.assistant, line)),
53
+ };
54
+ }
28
55
  function renderLine(text, width) {
29
56
  return new Text(truncateToWidth(text, width, "")).render(width);
30
57
  }
@@ -73,18 +100,33 @@ export class InteractiveChat {
73
100
  const state = this.readState();
74
101
  const lines = [];
75
102
  const colors = paletteFor(state.theme);
103
+ const markdownTheme = markdownThemeFor(colors);
76
104
  for (const [index, message] of state.messageItems.entries()) {
77
105
  if (index > 0)
78
106
  lines.push(" ");
79
- if (message.role === "user") {
80
- lines.push(...renderLine(` ${paint(colors.accent, "You", true)}`, width));
81
- lines.push(...new Text(` ${message.text}`).render(width));
107
+ if (message.role === "file_change") {
108
+ lines.push(...renderLine(paint(colors.dim, `${message.kind === "edit" ? "Edited" : "Wrote"} ${message.path}`, true), width));
109
+ if (message.diff) {
110
+ for (const line of renderDiff(message.diff, colors))
111
+ lines.push(...renderLine(line, width));
112
+ }
113
+ else {
114
+ for (const line of message.removed)
115
+ lines.push(...renderLine(paint(colors.error, `- ${line}`), width));
116
+ for (const line of message.added)
117
+ lines.push(...renderLine(paint(colors.success, `+ ${line}`), width));
118
+ }
119
+ }
120
+ else if (message.role === "user") {
121
+ lines.push(...new Text(message.text, 2, 1).render(width).map((line) => paintBackground(colors.userBackground, line)));
82
122
  }
83
123
  else {
84
- lines.push(...renderLine(` ${paint(colors.assistant, "Assistant", true)}`, width));
85
- lines.push(...new Markdown(message.text, { paddingX: 4 }).render(width));
124
+ lines.push(...new Markdown(message.text, { paddingX: 2, theme: markdownTheme }).render(width));
86
125
  }
87
126
  }
127
+ const hasProcess = state.processItems.length > 0 || (state.busy && !state.streamingText);
128
+ if (hasProcess && lines.length > 0)
129
+ lines.push(" ");
88
130
  const toolCount = state.processItems.filter((item) => item.type === "tool").length;
89
131
  const hiddenToolItems = Math.max(0, toolCount - MAX_VISIBLE_TOOL_ITEMS);
90
132
  let skippedToolItems = 0;
@@ -107,21 +149,22 @@ export class InteractiveChat {
107
149
  const color = item.status === "error" ? colors.error : item.status === "done" ? colors.success : colors.warning;
108
150
  lines.push(...renderLine(` ${paint(color, marker)} ${paint(colors.dim, command)}`, width));
109
151
  }
110
- if (state.busy && !state.processItems.some((item) => item.type === "thinking")) {
152
+ if (state.busy && !state.streamingText && !state.processItems.some((item) => item.type === "thinking")) {
111
153
  const frame = SPINNER_FRAMES[state.spinnerFrame % SPINNER_FRAMES.length] ?? SPINNER_FRAMES[0];
112
154
  lines.push(...renderLine(` ${paint(colors.accent, `${frame} Thinking`)}`, width));
113
155
  }
156
+ if (hasProcess)
157
+ lines.push(" ");
114
158
  if (state.streamingText) {
115
- if (lines.length > 0)
159
+ if (lines.length > 0 && lines.at(-1) !== " ")
116
160
  lines.push(" ");
117
- lines.push(...renderLine(` ${paint(colors.assistant, "Assistant", true)}`, width));
118
- lines.push(...new Markdown(state.streamingText, { paddingX: 4 }).render(width));
161
+ lines.push(...new Markdown(state.streamingText, { paddingX: 2, theme: markdownTheme }).render(width));
119
162
  }
120
163
  const hasActivity = state.status || state.queue.length > 0 || state.error;
121
164
  if (hasActivity) {
122
165
  if (lines.length > 0)
123
166
  lines.push(" ");
124
- lines.push(...renderLine(` ${paint(colors.dim, "ACTIVITY", true)}`, width));
167
+ lines.push(...renderLine(paint(colors.dim, "Activity", true), width));
125
168
  if (state.status)
126
169
  lines.push(...renderLine(` ${paint(colors.dim, state.status)}`, width));
127
170
  if (state.queue.length > 0) {
@@ -145,11 +188,8 @@ export class InteractiveComposer {
145
188
  render(width) {
146
189
  const state = this.readState();
147
190
  const colors = paletteFor(state.theme);
148
- const copy = width >= 56 ? "COMPOSE / commands Tab complete" : "COMPOSE / commands";
149
- return [
150
- ...renderLine(paint(colors.dim, "-".repeat(Math.max(0, width))), width),
151
- ...renderLine(paint(colors.dim, copy), width),
152
- ];
191
+ const copy = width >= 56 ? "/ commands Tab complete" : "/ commands";
192
+ return renderLine(paint(colors.dim, copy), width);
153
193
  }
154
194
  }
155
195
  export class InteractiveFooter {
@@ -166,12 +206,11 @@ export class InteractiveFooter {
166
206
  const context = paint(colors.dim, `${state.messageItems.length} messages ctx ${formatTokenCount(state.usage.estimatedContextTokens)}/${formatTokenCount(state.usage.contextWindow)} total ${formatTokenCount(state.usage.totalTokens)} tok`);
167
207
  const right = paint(colors.dim, `${state.model} ${state.theme}`);
168
208
  const status = width >= 60 ? alignEnds(`${left} ${context}`, right, width) : `${left} ${right}`;
169
- const hints = width >= 60 ? "Enter send Esc cancel Ctrl+O model Ctrl+L session" : "Enter send Ctrl+O model";
170
- return [
171
- ...renderLine(paint(colors.dim, "-".repeat(Math.max(0, width))), width),
172
- ...renderLine(status, width),
173
- ...renderLine(paint(colors.dim, hints), width),
174
- ];
209
+ const pasteImageShortcut = state.pasteImageShortcut ?? (process.platform === "win32" ? "Alt+V" : "Ctrl+V");
210
+ const hints = width >= 60
211
+ ? `Enter send ${pasteImageShortcut} paste image Shift+Tab thinking Esc cancel Ctrl+O model`
212
+ : `Enter send ${pasteImageShortcut} image`;
213
+ return [...renderLine(status, width), ...renderLine(paint(colors.dim, hints), width)];
175
214
  }
176
215
  }
177
216
  function formatTokenCount(value) {
@@ -183,14 +222,26 @@ function formatTokenCount(value) {
183
222
  }
184
223
  export class AutocompleteMenu {
185
224
  readState;
225
+ box;
186
226
  constructor(readState) {
187
227
  this.readState = readState;
228
+ this.box = new Box({
229
+ invalidate: () => { },
230
+ render: (width) => this.renderItems(width),
231
+ }, { border: "rounded", padding: 1, title: "Suggestions" });
232
+ }
233
+ invalidate() {
234
+ this.box.invalidate();
188
235
  }
189
- invalidate() { }
190
236
  render(width) {
237
+ return this.box.render(width);
238
+ }
239
+ renderItems(width) {
191
240
  const state = this.readState();
192
- return state.items.slice(0, 6).flatMap((item, index) => {
193
- const prefix = index === state.index ? "> " : " ";
241
+ const maxVisible = 6;
242
+ const start = Math.min(Math.max(0, state.index - Math.floor(maxVisible / 2)), Math.max(0, state.items.length - maxVisible));
243
+ return state.items.slice(start, start + maxVisible).flatMap((item, offset) => {
244
+ const prefix = start + offset === state.index ? "> " : " ";
194
245
  const description = item.description ? ` - ${item.description}` : "";
195
246
  return new Text(`${prefix}${item.label}${description}`).render(width);
196
247
  });