@agimon-ai/doompi-file-edit 0.0.1-alpha.2 → 0.0.1-alpha.21

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 +15 -15
  2. package/dist/adapters/pi/extension.cjs +2 -0
  3. package/dist/adapters/pi/extension.cjs.map +1 -0
  4. package/dist/{extension.d.cts → adapters/pi/extension.d.cts} +1 -1
  5. package/dist/adapters/pi/extension.d.cts.map +1 -0
  6. package/dist/{extension.d.mts → adapters/pi/extension.d.mts} +1 -1
  7. package/dist/adapters/pi/extension.d.mts.map +1 -0
  8. package/dist/adapters/pi/extension.mjs +2 -0
  9. package/dist/adapters/pi/extension.mjs.map +1 -0
  10. package/dist/adapters/process/commandLine.cjs.map +1 -0
  11. package/dist/adapters/process/commandLine.mjs.map +1 -0
  12. package/dist/container/index.cjs +1 -1
  13. package/dist/container/index.cjs.map +1 -1
  14. package/dist/container/index.mjs +1 -1
  15. package/dist/container/index.mjs.map +1 -1
  16. package/dist/extensions/doom.cjs +1 -1
  17. package/dist/extensions/doom.cjs.map +1 -1
  18. package/dist/extensions/doom.mjs +1 -1
  19. package/dist/extensions/doom.mjs.map +1 -1
  20. package/dist/extensions/pi.cjs +1 -1
  21. package/dist/extensions/pi.d.cts +1 -1
  22. package/dist/extensions/pi.d.mts +1 -1
  23. package/dist/extensions/pi.mjs +1 -1
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.d.cts +3 -3
  26. package/dist/index.d.mts +3 -3
  27. package/dist/index.mjs +1 -1
  28. package/dist/services/EditTracker/EditTracker.cjs +1 -1
  29. package/dist/services/EditTracker/EditTracker.cjs.map +1 -1
  30. package/dist/services/EditTracker/EditTracker.mjs +1 -1
  31. package/dist/services/EditTracker/EditTracker.mjs.map +1 -1
  32. package/dist/services/EditorConfigService/EditorConfigService.cjs +1 -1
  33. package/dist/services/EditorConfigService/EditorConfigService.cjs.map +1 -1
  34. package/dist/services/EditorConfigService/EditorConfigService.mjs +1 -1
  35. package/dist/services/EditorConfigService/EditorConfigService.mjs.map +1 -1
  36. package/dist/services/EditorLauncher/EditorLauncher.cjs +1 -1
  37. package/dist/services/EditorLauncher/EditorLauncher.cjs.map +1 -1
  38. package/dist/services/EditorLauncher/EditorLauncher.mjs +1 -1
  39. package/dist/services/EditorLauncher/EditorLauncher.mjs.map +1 -1
  40. package/dist/services/FileEditPaths/FileEditPaths.cjs +1 -1
  41. package/dist/services/FileEditPaths/FileEditPaths.cjs.map +1 -1
  42. package/dist/services/FileEditPaths/FileEditPaths.mjs +1 -1
  43. package/dist/services/FileEditWorkflow/FileEditWorkflow.cjs +1 -1
  44. package/dist/services/FileEditWorkflow/FileEditWorkflow.cjs.map +1 -1
  45. package/dist/services/FileEditWorkflow/FileEditWorkflow.mjs +1 -1
  46. package/dist/services/FileEditWorkflow/FileEditWorkflow.mjs.map +1 -1
  47. package/dist/services/GitDiffService/GitDiffService.cjs.map +1 -1
  48. package/dist/services/GitDiffService/GitDiffService.mjs.map +1 -1
  49. package/dist/services/TimelineStore/TimelineStore.cjs.map +1 -1
  50. package/dist/services/TimelineStore/TimelineStore.mjs.map +1 -1
  51. package/dist/{domain.d.cts → services/fileEdit/domain.d.cts} +1 -1
  52. package/dist/services/fileEdit/domain.d.cts.map +1 -0
  53. package/dist/{domain.d.mts → services/fileEdit/domain.d.mts} +1 -1
  54. package/dist/services/fileEdit/domain.d.mts.map +1 -0
  55. package/dist/tui/fileEditOverlay.cjs.map +1 -1
  56. package/dist/tui/fileEditOverlay.mjs.map +1 -1
  57. package/dist/{types.cjs → types/index.cjs} +1 -1
  58. package/dist/types/index.cjs.map +1 -0
  59. package/dist/{types.d.cts → types/index.d.cts} +2 -2
  60. package/dist/types/index.d.cts.map +1 -0
  61. package/dist/{types.d.mts → types/index.d.mts} +2 -2
  62. package/dist/types/index.d.mts.map +1 -0
  63. package/dist/{types.mjs → types/index.mjs} +1 -1
  64. package/dist/types/index.mjs.map +1 -0
  65. package/package.json +17 -10
  66. package/dist/commandLine.cjs.map +0 -1
  67. package/dist/commandLine.mjs.map +0 -1
  68. package/dist/domain.d.cts.map +0 -1
  69. package/dist/domain.d.mts.map +0 -1
  70. package/dist/extension.cjs +0 -2
  71. package/dist/extension.cjs.map +0 -1
  72. package/dist/extension.d.cts.map +0 -1
  73. package/dist/extension.d.mts.map +0 -1
  74. package/dist/extension.mjs +0 -2
  75. package/dist/extension.mjs.map +0 -1
  76. package/dist/types.cjs.map +0 -1
  77. package/dist/types.d.cts.map +0 -1
  78. package/dist/types.d.mts.map +0 -1
  79. package/dist/types.mjs.map +0 -1
  80. /package/dist/{commandLine.cjs → adapters/process/commandLine.cjs} +0 -0
  81. /package/dist/{commandLine.mjs → adapters/process/commandLine.mjs} +0 -0
package/README.md CHANGED
@@ -1,12 +1,13 @@
1
1
  # @agimon-ai/doompi-file-edit
2
2
 
3
- Pi session file edit timeline and external editor overlay.
3
+ **Every edit in the session, in one place.**
4
4
 
5
- A timeline of every file the session edited, plus an external editor handoff.
5
+ This package keeps a timeline of files the current Pi session changed and opens them in an
6
+ external editor when the terminal view is not enough. It is the answer to "what did the
7
+ agent touch?" without asking the transcript to remember every write.
6
8
 
7
- Part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi), a coding agent that loads
8
- only the skills and tools you name. This package is composed by Doompi and is not usually
9
- installed on its own.
9
+ This is part of [Doompi](https://www.npmjs.com/package/@agimon-ai/doompi). Most users get
10
+ it with the distribution.
10
11
 
11
12
  ## Install
12
13
 
@@ -16,22 +17,21 @@ npm install @agimon-ai/doompi-file-edit
16
17
 
17
18
  ## How it loads
18
19
 
19
- Doompi loads this unconditionally. It is core, not a layer, so it does not appear in
20
- `.doom/modes.yaml`: making it optional would only create broken configurations.
21
-
22
- Extension entry: `@agimon-ai/doompi-file-edit/extensions/doom`
20
+ Doompi loads the edit timeline as core. It is not a layer and does not appear in
21
+ `.doom/modes.yaml`. The bare package name follows its Pi manifest and selects the Doom
22
+ adapter; explicit `/extensions/pi` and `/extensions/doom` subpaths remain available.
23
23
 
24
24
  ## Leader
25
25
 
26
- `SPC e f` opens session edits, once the extension is loaded.
26
+ `SPC e f` opens the files edited by the current session.
27
27
 
28
28
  ## Entry points
29
29
 
30
- | Import |
31
- | --------------------------------------------- |
32
- | `@agimon-ai/doompi-file-edit` |
33
- | `@agimon-ai/doompi-file-edit/extensions/pi` |
34
- | `@agimon-ai/doompi-file-edit/extensions/doom` |
30
+ | Import | Purpose |
31
+ | --------------------------------------------- | --------------------- |
32
+ | `@agimon-ai/doompi-file-edit` | Library API |
33
+ | `@agimon-ai/doompi-file-edit/extensions/pi` | Standalone Pi adapter |
34
+ | `@agimon-ai/doompi-file-edit/extensions/doom` | Doompi adapter |
35
35
 
36
36
  ## License
37
37
 
@@ -0,0 +1,2 @@
1
+ const e=require("../../types/index.cjs"),t=require("../../container/index.cjs");let n=require("@agimon-ai/doompi-extension-contracts/child-process"),r=require("@agimon-ai/doompi-telemetry");const i=`file-edits`,a={source:`@agimon-ai/doompi-file-edit`,bindings:[{id:`editor.files`,path:[{key:`e`,label:`extension`,order:50},{key:`f`,label:`files`,detail:`session edits`}],command:{name:i}}]};function o(a){let o=t.createFileEditContainer(),s=o.get(e.FILE_EDIT_TYPES.Paths),c=o.get(e.FILE_EDIT_TYPES.TimelineStore),l=o.get(e.FILE_EDIT_TYPES.EditTracker),u=o.get(e.FILE_EDIT_TYPES.Workflow),d=(0,r.createDoomTelemetry)({serviceName:`doom-file-edit`,packageName:`@agimon-ai/doompi-file-edit`,env:process.env,enableLogs:!0,enableTraces:!0}),f=new Map;a.registerCommand(i,{description:`Review files edited in this session`,handler:async(e,t)=>{if(!t.hasUI){t.ui.notify(`/file-edits requires interactive mode`,`error`);return}await u.open(t)}}),a.on(`session_start`,async(e,t)=>{let n=s.sessionKey(t.sessionManager.getSessionId());c.initialize(s.timelinePath(t.cwd,n)),d.recordEvent(`doom_file_edit.timeline_started`,{outcome:`initialized`})}),a.on(`tool_execution_start`,async(e,t)=>{f.set(e.toolCallId,Date.now()),await l.start(e.toolCallId,e.toolName,e.args,t.cwd),d.recordEvent(`doom_file_edit.edit_started`,{"tool.name":e.toolName})}),a.on(`tool_execution_end`,async e=>{let t=f.get(e.toolCallId);f.delete(e.toolCallId),await l.end(e.toolCallId,e.isError),d.recordEvent(`doom_file_edit.edit_finished`,{"tool.name":e.toolName,"tool.result.error":e.isError,...t===void 0?{}:{duration_ms:Date.now()-t},outcome:e.isError?`failed`:`completed`})}),a.on(`session_shutdown`,async()=>{process.env[n.SUBAGENT_CHILD_ENV]||await c.clear(),await d.recordEvent(`doom_file_edit.timeline_finished`,{outcome:`closed`}),await d.shutdown()})}exports.FILE_EDIT_LEADER_CONTRIBUTION=a,exports.fileEditExtension=o;
2
+ //# sourceMappingURL=extension.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.cjs","names":["createFileEditContainer","FILE_EDIT_TYPES","createDoomTelemetry","SUBAGENT_CHILD_ENV"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { createFileEditContainer } from '../../container/index.ts';\nimport type { IEditTracker } from '../../services/EditTracker/types.ts';\nimport type { IFileEditPaths } from '../../services/FileEditPaths/types.ts';\nimport type { IFileEditWorkflow } from '../../services/FileEditWorkflow/types.ts';\nimport type { ITimelineStore } from '../../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\n\nconst FILES_COMMAND = 'file-edits';\n\nexport const FILE_EDIT_LEADER_CONTRIBUTION = {\n source: '@agimon-ai/doompi-file-edit',\n bindings: [\n {\n id: 'editor.files',\n path: [\n { key: 'e', label: 'extension', order: 50 },\n { key: 'f', label: 'files', detail: 'session edits' },\n ],\n command: { name: FILES_COMMAND },\n },\n ],\n} as const;\n\nexport function fileEditExtension(pi: ExtensionAPI): void {\n const container = createFileEditContainer();\n const paths = container.get<IFileEditPaths>(FILE_EDIT_TYPES.Paths);\n const timeline = container.get<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore);\n const tracker = container.get<IEditTracker>(FILE_EDIT_TYPES.EditTracker);\n const workflow = container.get<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow);\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: 'doom-file-edit',\n packageName: '@agimon-ai/doompi-file-edit',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const toolStartedAt = new Map<string, number>();\n\n pi.registerCommand(FILES_COMMAND, {\n description: 'Review files edited in this session',\n handler: async (_args, ctx) => {\n if (!ctx.hasUI) {\n ctx.ui.notify('/file-edits requires interactive mode', 'error');\n return;\n }\n await workflow.open(ctx);\n },\n });\n\n pi.on('session_start', async (_event, ctx) => {\n const sessionKey = paths.sessionKey(ctx.sessionManager.getSessionId());\n timeline.initialize(paths.timelinePath(ctx.cwd, sessionKey));\n void telemetry.recordEvent('doom_file_edit.timeline_started', { outcome: 'initialized' });\n });\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n await tracker.start(event.toolCallId, event.toolName, event.args, ctx.cwd);\n void telemetry.recordEvent('doom_file_edit.edit_started', { 'tool.name': event.toolName });\n });\n pi.on('tool_execution_end', async (event) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n await tracker.end(event.toolCallId, event.isError);\n void telemetry.recordEvent('doom_file_edit.edit_finished', {\n 'tool.name': event.toolName,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { duration_ms: Date.now() - startedAt }),\n outcome: event.isError ? 'failed' : 'completed',\n });\n });\n pi.on('session_shutdown', async () => {\n if (!process.env[SUBAGENT_CHILD_ENV]) await timeline.clear();\n await telemetry.recordEvent('doom_file_edit.timeline_finished', { outcome: 'closed' });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"8LAUA,MAAM,EAAgB,aAET,EAAgC,CAC3C,OAAQ,8BACR,SAAU,CACR,CACE,GAAI,eACJ,KAAM,CACJ,CAAE,IAAK,IAAK,MAAO,YAAa,MAAO,EAAG,EAC1C,CAAE,IAAK,IAAK,MAAO,QAAS,OAAQ,eAAgB,CACtD,EACA,QAAS,CAAE,KAAM,CAAc,CACjC,CACF,CACF,EAEA,SAAgB,EAAkB,EAAwB,CACxD,IAAM,EAAYA,EAAAA,wBAAwB,EACpC,EAAQ,EAAU,IAAoBC,EAAAA,gBAAgB,KAAK,EAC3D,EAAW,EAAU,IAAoBA,EAAAA,gBAAgB,aAAa,EACtE,EAAU,EAAU,IAAkBA,EAAAA,gBAAgB,WAAW,EACjE,EAAW,EAAU,IAAuBA,EAAAA,gBAAgB,QAAQ,EACpE,GAAA,EAA2BC,EAAAA,oBAAAA,CAAoB,CACnD,YAAa,iBACb,YAAa,8BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,EAAgB,IAAI,IAE1B,EAAG,gBAAgB,EAAe,CAChC,YAAa,sCACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,GAAI,CAAC,EAAI,MAAO,CACd,EAAI,GAAG,OAAO,wCAAyC,OAAO,EAC9D,MACF,CACA,MAAM,EAAS,KAAK,CAAG,CACzB,CACF,CAAC,EAED,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,IAAM,EAAa,EAAM,WAAW,EAAI,eAAe,aAAa,CAAC,EACrE,EAAS,WAAW,EAAM,aAAa,EAAI,IAAK,CAAU,CAAC,EAC3D,EAAe,YAAY,kCAAmC,CAAE,QAAS,aAAc,CAAC,CAC1F,CAAC,EACD,EAAG,GAAG,uBAAwB,MAAO,EAAO,IAAQ,CAClD,EAAc,IAAI,EAAM,WAAY,KAAK,IAAI,CAAC,EAC9C,MAAM,EAAQ,MAAM,EAAM,WAAY,EAAM,SAAU,EAAM,KAAM,EAAI,GAAG,EACzE,EAAe,YAAY,8BAA+B,CAAE,YAAa,EAAM,QAAS,CAAC,CAC3F,CAAC,EACD,EAAG,GAAG,qBAAsB,KAAO,IAAU,CAC3C,IAAM,EAAY,EAAc,IAAI,EAAM,UAAU,EACpD,EAAc,OAAO,EAAM,UAAU,EACrC,MAAM,EAAQ,IAAI,EAAM,WAAY,EAAM,OAAO,EACjD,EAAe,YAAY,+BAAgC,CACzD,YAAa,EAAM,SACnB,oBAAqB,EAAM,QAC3B,GAAI,IAAc,IAAA,GAAY,CAAC,EAAI,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,EACzE,QAAS,EAAM,QAAU,SAAW,WACtC,CAAC,CACH,CAAC,EACD,EAAG,GAAG,mBAAoB,SAAY,CAC/B,QAAQ,IAAIC,EAAAA,qBAAqB,MAAM,EAAS,MAAM,EAC3D,MAAM,EAAU,YAAY,mCAAoC,CAAE,QAAS,QAAS,CAAC,EACrF,MAAM,EAAU,SAAS,CAC3B,CAAC,CACH"}
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- //#region src/extension.d.ts
2
+ //#region src/adapters/pi/extension.d.ts
3
3
  declare function fileEditExtension(pi: ExtensionAPI): void;
4
4
  //#endregion
5
5
  export { fileEditExtension };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;iBA0BgB,kBAAkB,IAAI"}
@@ -1,5 +1,5 @@
1
1
  import { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- //#region src/extension.d.ts
2
+ //#region src/adapters/pi/extension.d.ts
3
3
  declare function fileEditExtension(pi: ExtensionAPI): void;
4
4
  //#endregion
5
5
  export { fileEditExtension };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;iBA0BgB,kBAAkB,IAAI"}
@@ -0,0 +1,2 @@
1
+ import{FILE_EDIT_TYPES as e}from"../../types/index.mjs";import{createFileEditContainer as t}from"../../container/index.mjs";import{SUBAGENT_CHILD_ENV as n}from"@agimon-ai/doompi-extension-contracts/child-process";import{createDoomTelemetry as r}from"@agimon-ai/doompi-telemetry";const i=`file-edits`,a={source:`@agimon-ai/doompi-file-edit`,bindings:[{id:`editor.files`,path:[{key:`e`,label:`extension`,order:50},{key:`f`,label:`files`,detail:`session edits`}],command:{name:i}}]};function o(a){let o=t(),s=o.get(e.Paths),c=o.get(e.TimelineStore),l=o.get(e.EditTracker),u=o.get(e.Workflow),d=r({serviceName:`doom-file-edit`,packageName:`@agimon-ai/doompi-file-edit`,env:process.env,enableLogs:!0,enableTraces:!0}),f=new Map;a.registerCommand(i,{description:`Review files edited in this session`,handler:async(e,t)=>{if(!t.hasUI){t.ui.notify(`/file-edits requires interactive mode`,`error`);return}await u.open(t)}}),a.on(`session_start`,async(e,t)=>{let n=s.sessionKey(t.sessionManager.getSessionId());c.initialize(s.timelinePath(t.cwd,n)),d.recordEvent(`doom_file_edit.timeline_started`,{outcome:`initialized`})}),a.on(`tool_execution_start`,async(e,t)=>{f.set(e.toolCallId,Date.now()),await l.start(e.toolCallId,e.toolName,e.args,t.cwd),d.recordEvent(`doom_file_edit.edit_started`,{"tool.name":e.toolName})}),a.on(`tool_execution_end`,async e=>{let t=f.get(e.toolCallId);f.delete(e.toolCallId),await l.end(e.toolCallId,e.isError),d.recordEvent(`doom_file_edit.edit_finished`,{"tool.name":e.toolName,"tool.result.error":e.isError,...t===void 0?{}:{duration_ms:Date.now()-t},outcome:e.isError?`failed`:`completed`})}),a.on(`session_shutdown`,async()=>{process.env[n]||await c.clear(),await d.recordEvent(`doom_file_edit.timeline_finished`,{outcome:`closed`}),await d.shutdown()})}export{a as FILE_EDIT_LEADER_CONTRIBUTION,o as fileEditExtension};
2
+ //# sourceMappingURL=extension.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.mjs","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { createFileEditContainer } from '../../container/index.ts';\nimport type { IEditTracker } from '../../services/EditTracker/types.ts';\nimport type { IFileEditPaths } from '../../services/FileEditPaths/types.ts';\nimport type { IFileEditWorkflow } from '../../services/FileEditWorkflow/types.ts';\nimport type { ITimelineStore } from '../../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\n\nconst FILES_COMMAND = 'file-edits';\n\nexport const FILE_EDIT_LEADER_CONTRIBUTION = {\n source: '@agimon-ai/doompi-file-edit',\n bindings: [\n {\n id: 'editor.files',\n path: [\n { key: 'e', label: 'extension', order: 50 },\n { key: 'f', label: 'files', detail: 'session edits' },\n ],\n command: { name: FILES_COMMAND },\n },\n ],\n} as const;\n\nexport function fileEditExtension(pi: ExtensionAPI): void {\n const container = createFileEditContainer();\n const paths = container.get<IFileEditPaths>(FILE_EDIT_TYPES.Paths);\n const timeline = container.get<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore);\n const tracker = container.get<IEditTracker>(FILE_EDIT_TYPES.EditTracker);\n const workflow = container.get<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow);\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: 'doom-file-edit',\n packageName: '@agimon-ai/doompi-file-edit',\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const toolStartedAt = new Map<string, number>();\n\n pi.registerCommand(FILES_COMMAND, {\n description: 'Review files edited in this session',\n handler: async (_args, ctx) => {\n if (!ctx.hasUI) {\n ctx.ui.notify('/file-edits requires interactive mode', 'error');\n return;\n }\n await workflow.open(ctx);\n },\n });\n\n pi.on('session_start', async (_event, ctx) => {\n const sessionKey = paths.sessionKey(ctx.sessionManager.getSessionId());\n timeline.initialize(paths.timelinePath(ctx.cwd, sessionKey));\n void telemetry.recordEvent('doom_file_edit.timeline_started', { outcome: 'initialized' });\n });\n pi.on('tool_execution_start', async (event, ctx) => {\n toolStartedAt.set(event.toolCallId, Date.now());\n await tracker.start(event.toolCallId, event.toolName, event.args, ctx.cwd);\n void telemetry.recordEvent('doom_file_edit.edit_started', { 'tool.name': event.toolName });\n });\n pi.on('tool_execution_end', async (event) => {\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n await tracker.end(event.toolCallId, event.isError);\n void telemetry.recordEvent('doom_file_edit.edit_finished', {\n 'tool.name': event.toolName,\n 'tool.result.error': event.isError,\n ...(startedAt === undefined ? {} : { duration_ms: Date.now() - startedAt }),\n outcome: event.isError ? 'failed' : 'completed',\n });\n });\n pi.on('session_shutdown', async () => {\n if (!process.env[SUBAGENT_CHILD_ENV]) await timeline.clear();\n await telemetry.recordEvent('doom_file_edit.timeline_finished', { outcome: 'closed' });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"uRAUA,MAAM,EAAgB,aAET,EAAgC,CAC3C,OAAQ,8BACR,SAAU,CACR,CACE,GAAI,eACJ,KAAM,CACJ,CAAE,IAAK,IAAK,MAAO,YAAa,MAAO,EAAG,EAC1C,CAAE,IAAK,IAAK,MAAO,QAAS,OAAQ,eAAgB,CACtD,EACA,QAAS,CAAE,KAAM,CAAc,CACjC,CACF,CACF,EAEA,SAAgB,EAAkB,EAAwB,CACxD,IAAM,EAAY,EAAwB,EACpC,EAAQ,EAAU,IAAoB,EAAgB,KAAK,EAC3D,EAAW,EAAU,IAAoB,EAAgB,aAAa,EACtE,EAAU,EAAU,IAAkB,EAAgB,WAAW,EACjE,EAAW,EAAU,IAAuB,EAAgB,QAAQ,EACpE,EAA2B,EAAoB,CACnD,YAAa,iBACb,YAAa,8BACb,IAAK,QAAQ,IACb,WAAY,GACZ,aAAc,EAChB,CAAC,EACK,EAAgB,IAAI,IAE1B,EAAG,gBAAgB,EAAe,CAChC,YAAa,sCACb,QAAS,MAAO,EAAO,IAAQ,CAC7B,GAAI,CAAC,EAAI,MAAO,CACd,EAAI,GAAG,OAAO,wCAAyC,OAAO,EAC9D,MACF,CACA,MAAM,EAAS,KAAK,CAAG,CACzB,CACF,CAAC,EAED,EAAG,GAAG,gBAAiB,MAAO,EAAQ,IAAQ,CAC5C,IAAM,EAAa,EAAM,WAAW,EAAI,eAAe,aAAa,CAAC,EACrE,EAAS,WAAW,EAAM,aAAa,EAAI,IAAK,CAAU,CAAC,EAC3D,EAAe,YAAY,kCAAmC,CAAE,QAAS,aAAc,CAAC,CAC1F,CAAC,EACD,EAAG,GAAG,uBAAwB,MAAO,EAAO,IAAQ,CAClD,EAAc,IAAI,EAAM,WAAY,KAAK,IAAI,CAAC,EAC9C,MAAM,EAAQ,MAAM,EAAM,WAAY,EAAM,SAAU,EAAM,KAAM,EAAI,GAAG,EACzE,EAAe,YAAY,8BAA+B,CAAE,YAAa,EAAM,QAAS,CAAC,CAC3F,CAAC,EACD,EAAG,GAAG,qBAAsB,KAAO,IAAU,CAC3C,IAAM,EAAY,EAAc,IAAI,EAAM,UAAU,EACpD,EAAc,OAAO,EAAM,UAAU,EACrC,MAAM,EAAQ,IAAI,EAAM,WAAY,EAAM,OAAO,EACjD,EAAe,YAAY,+BAAgC,CACzD,YAAa,EAAM,SACnB,oBAAqB,EAAM,QAC3B,GAAI,IAAc,IAAA,GAAY,CAAC,EAAI,CAAE,YAAa,KAAK,IAAI,EAAI,CAAU,EACzE,QAAS,EAAM,QAAU,SAAW,WACtC,CAAC,CACH,CAAC,EACD,EAAG,GAAG,mBAAoB,SAAY,CAC/B,QAAQ,IAAI,IAAqB,MAAM,EAAS,MAAM,EAC3D,MAAM,EAAU,YAAY,mCAAoC,CAAE,QAAS,QAAS,CAAC,EACrF,MAAM,EAAU,SAAS,CAC3B,CAAC,CACH"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandLine.cjs","names":[],"sources":["../../../src/adapters/process/commandLine.ts"],"sourcesContent":["export function splitCommandLine(template: string): string[] {\n const result: string[] = [];\n let current = '';\n let quote: 'single' | 'double' | undefined;\n let escaped = false;\n for (const character of template.trim()) {\n if (escaped) {\n current += character;\n escaped = false;\n } else if (character === '\\\\' && quote !== 'single') {\n escaped = true;\n } else if (character === \"'\" && quote !== 'double') {\n quote = quote === 'single' ? undefined : 'single';\n } else if (character === '\"' && quote !== 'single') {\n quote = quote === 'double' ? undefined : 'double';\n } else if (/\\s/u.test(character) && quote === undefined) {\n if (current) result.push(current);\n current = '';\n } else {\n current += character;\n }\n }\n if (escaped) current += '\\\\';\n if (quote !== undefined) throw new Error('Editor command has an unterminated quote');\n if (current) result.push(current);\n if (result.length === 0) throw new Error('Editor command must not be empty');\n return result;\n}\n\nexport function validateEditorTemplate(template: string): void {\n for (const match of template.matchAll(/\\{([^}]+)\\}/gu)) {\n if (match[1] !== 'file' && match[1] !== 'line') {\n throw new Error(`Unsupported editor placeholder: {${match[1]}}`);\n }\n }\n splitCommandLine(template);\n}\n\nexport function expandEditorTemplate(template: string, file: string, line: number): string[] {\n validateEditorTemplate(template);\n const hasFile = template.includes('{file}');\n const values = splitCommandLine(template).map((part) =>\n part.replaceAll('{file}', file).replaceAll('{line}', String(line)),\n );\n if (!hasFile) values.push(file);\n return values;\n}\n"],"mappings":"AAAA,SAAgB,EAAiB,EAA4B,CAC3D,IAAM,EAAmB,CAAC,EACtB,EAAU,GACV,EACA,EAAU,GACd,IAAK,IAAM,KAAa,EAAS,KAAK,EAChC,GACF,GAAW,EACX,EAAU,IACD,IAAc,MAAQ,IAAU,SACzC,EAAU,GACD,IAAc,KAAO,IAAU,SACxC,EAAQ,IAAU,SAAW,IAAA,GAAY,SAChC,IAAc,KAAO,IAAU,SACxC,EAAQ,IAAU,SAAW,IAAA,GAAY,SAChC,MAAM,KAAK,CAAS,GAAK,IAAU,IAAA,IACxC,GAAS,EAAO,KAAK,CAAO,EAChC,EAAU,IAEV,GAAW,EAIf,GADI,IAAS,GAAW,MACpB,IAAU,IAAA,GAAW,MAAU,MAAM,0CAA0C,EAEnF,GADI,GAAS,EAAO,KAAK,CAAO,EAC5B,EAAO,SAAW,EAAG,MAAU,MAAM,kCAAkC,EAC3E,OAAO,CACT,CAEA,SAAgB,EAAuB,EAAwB,CAC7D,IAAK,IAAM,KAAS,EAAS,SAAS,eAAe,EACnD,GAAI,EAAM,KAAO,QAAU,EAAM,KAAO,OACtC,MAAU,MAAM,oCAAoC,EAAM,GAAG,EAAE,EAGnE,EAAiB,CAAQ,CAC3B,CAEA,SAAgB,EAAqB,EAAkB,EAAc,EAAwB,CAC3F,EAAuB,CAAQ,EAC/B,IAAM,EAAU,EAAS,SAAS,QAAQ,EACpC,EAAS,EAAiB,CAAQ,CAAC,CAAC,IAAK,GAC7C,EAAK,WAAW,SAAU,CAAI,CAAC,CAAC,WAAW,SAAU,OAAO,CAAI,CAAC,CACnE,EAEA,OADK,GAAS,EAAO,KAAK,CAAI,EACvB,CACT"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandLine.mjs","names":[],"sources":["../../../src/adapters/process/commandLine.ts"],"sourcesContent":["export function splitCommandLine(template: string): string[] {\n const result: string[] = [];\n let current = '';\n let quote: 'single' | 'double' | undefined;\n let escaped = false;\n for (const character of template.trim()) {\n if (escaped) {\n current += character;\n escaped = false;\n } else if (character === '\\\\' && quote !== 'single') {\n escaped = true;\n } else if (character === \"'\" && quote !== 'double') {\n quote = quote === 'single' ? undefined : 'single';\n } else if (character === '\"' && quote !== 'single') {\n quote = quote === 'double' ? undefined : 'double';\n } else if (/\\s/u.test(character) && quote === undefined) {\n if (current) result.push(current);\n current = '';\n } else {\n current += character;\n }\n }\n if (escaped) current += '\\\\';\n if (quote !== undefined) throw new Error('Editor command has an unterminated quote');\n if (current) result.push(current);\n if (result.length === 0) throw new Error('Editor command must not be empty');\n return result;\n}\n\nexport function validateEditorTemplate(template: string): void {\n for (const match of template.matchAll(/\\{([^}]+)\\}/gu)) {\n if (match[1] !== 'file' && match[1] !== 'line') {\n throw new Error(`Unsupported editor placeholder: {${match[1]}}`);\n }\n }\n splitCommandLine(template);\n}\n\nexport function expandEditorTemplate(template: string, file: string, line: number): string[] {\n validateEditorTemplate(template);\n const hasFile = template.includes('{file}');\n const values = splitCommandLine(template).map((part) =>\n part.replaceAll('{file}', file).replaceAll('{line}', String(line)),\n );\n if (!hasFile) values.push(file);\n return values;\n}\n"],"mappings":"AAAA,SAAgB,EAAiB,EAA4B,CAC3D,IAAM,EAAmB,CAAC,EACtB,EAAU,GACV,EACA,EAAU,GACd,IAAK,IAAM,KAAa,EAAS,KAAK,EAChC,GACF,GAAW,EACX,EAAU,IACD,IAAc,MAAQ,IAAU,SACzC,EAAU,GACD,IAAc,KAAO,IAAU,SACxC,EAAQ,IAAU,SAAW,IAAA,GAAY,SAChC,IAAc,KAAO,IAAU,SACxC,EAAQ,IAAU,SAAW,IAAA,GAAY,SAChC,MAAM,KAAK,CAAS,GAAK,IAAU,IAAA,IACxC,GAAS,EAAO,KAAK,CAAO,EAChC,EAAU,IAEV,GAAW,EAIf,GADI,IAAS,GAAW,MACpB,IAAU,IAAA,GAAW,MAAU,MAAM,0CAA0C,EAEnF,GADI,GAAS,EAAO,KAAK,CAAO,EAC5B,EAAO,SAAW,EAAG,MAAU,MAAM,kCAAkC,EAC3E,OAAO,CACT,CAEA,SAAgB,EAAuB,EAAwB,CAC7D,IAAK,IAAM,KAAS,EAAS,SAAS,eAAe,EACnD,GAAI,EAAM,KAAO,QAAU,EAAM,KAAO,OACtC,MAAU,MAAM,oCAAoC,EAAM,GAAG,EAAE,EAGnE,EAAiB,CAAQ,CAC3B,CAEA,SAAgB,EAAqB,EAAkB,EAAc,EAAwB,CAC3F,EAAuB,CAAQ,EAC/B,IAAM,EAAU,EAAS,SAAS,QAAQ,EACpC,EAAS,EAAiB,CAAQ,CAAC,CAAC,IAAK,GAC7C,EAAK,WAAW,SAAU,CAAI,CAAC,CAAC,WAAW,SAAU,OAAO,CAAI,CAAC,CACnE,EAEA,OADK,GAAS,EAAO,KAAK,CAAI,EACvB,CACT"}
@@ -1,2 +1,2 @@
1
- const e=require("../types.cjs"),t=require("../services/EditTracker/EditTracker.cjs"),n=require("../services/EditorConfigService/EditorConfigService.cjs"),r=require("../services/EditorLauncher/EditorLauncher.cjs"),i=require("../services/FileEditPaths/FileEditPaths.cjs"),a=require("../services/FileEditWorkflow/FileEditWorkflow.cjs"),o=require("../services/GitDiffService/GitDiffService.cjs"),s=require("../services/TimelineStore/TimelineStore.cjs");let c=require("inversify");require("reflect-metadata/lite");function l(){let l=new c.Container;return l.bind(e.FILE_EDIT_TYPES.Paths).to(i.FileEditPaths).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.TimelineStore).to(s.TimelineStore).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.GitDiffService).to(o.GitDiffService).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.EditTracker).to(t.EditTracker).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.EditorConfigService).to(n.EditorConfigService).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.EditorLauncher).to(r.EditorLauncher).inSingletonScope(),l.bind(e.FILE_EDIT_TYPES.Workflow).to(a.FileEditWorkflow).inSingletonScope(),l}exports.createFileEditContainer=l;
1
+ const e=require("../services/EditorConfigService/EditorConfigService.cjs"),t=require("../types/index.cjs"),n=require("../services/EditorLauncher/EditorLauncher.cjs"),r=require("../services/EditTracker/EditTracker.cjs"),i=require("../services/FileEditPaths/FileEditPaths.cjs"),a=require("../services/FileEditWorkflow/FileEditWorkflow.cjs"),o=require("../services/GitDiffService/GitDiffService.cjs"),s=require("../services/TimelineStore/TimelineStore.cjs");let c=require("inversify");require("reflect-metadata/lite");function l(){let l=new c.Container;return l.bind(t.FILE_EDIT_TYPES.Paths).to(i.FileEditPaths).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.TimelineStore).to(s.TimelineStore).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.GitDiffService).to(o.GitDiffService).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.EditTracker).to(r.EditTracker).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.EditorConfigService).to(e.EditorConfigService).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.EditorLauncher).to(n.EditorLauncher).inSingletonScope(),l.bind(t.FILE_EDIT_TYPES.Workflow).to(a.FileEditWorkflow).inSingletonScope(),l}exports.createFileEditContainer=l;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Container","FILE_EDIT_TYPES","FileEditPaths","TimelineStore","GitDiffService","EditTracker","EditorConfigService","EditorLauncher","FileEditWorkflow"],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { EditTracker } from '../services/EditTracker/EditTracker.ts';\nimport type { IEditTracker } from '../services/EditTracker/types.ts';\nimport { EditorConfigService } from '../services/EditorConfigService/EditorConfigService.ts';\nimport type { IEditorConfigService } from '../services/EditorConfigService/types.ts';\nimport { EditorLauncher } from '../services/EditorLauncher/EditorLauncher.ts';\nimport type { IEditorLauncher } from '../services/EditorLauncher/types.ts';\nimport { FileEditPaths } from '../services/FileEditPaths/FileEditPaths.ts';\nimport type { IFileEditPaths } from '../services/FileEditPaths/types.ts';\nimport { FileEditWorkflow } from '../services/FileEditWorkflow/FileEditWorkflow.ts';\nimport type { IFileEditWorkflow } from '../services/FileEditWorkflow/types.ts';\nimport { GitDiffService } from '../services/GitDiffService/GitDiffService.ts';\nimport type { IGitDiffService } from '../services/GitDiffService/types.ts';\nimport { TimelineStore } from '../services/TimelineStore/TimelineStore.ts';\nimport type { ITimelineStore } from '../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../types.ts';\n\nexport function createFileEditContainer(): Container {\n const container = new Container();\n container.bind<IFileEditPaths>(FILE_EDIT_TYPES.Paths).to(FileEditPaths).inSingletonScope();\n container.bind<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore).to(TimelineStore).inSingletonScope();\n container.bind<IGitDiffService>(FILE_EDIT_TYPES.GitDiffService).to(GitDiffService).inSingletonScope();\n container.bind<IEditTracker>(FILE_EDIT_TYPES.EditTracker).to(EditTracker).inSingletonScope();\n container.bind<IEditorConfigService>(FILE_EDIT_TYPES.EditorConfigService).to(EditorConfigService).inSingletonScope();\n container.bind<IEditorLauncher>(FILE_EDIT_TYPES.EditorLauncher).to(EditorLauncher).inSingletonScope();\n container.bind<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow).to(FileEditWorkflow).inSingletonScope();\n return container;\n}\n"],"mappings":"6fAkBA,SAAgB,GAAqC,CACnD,IAAM,EAAY,IAAIA,EAAAA,UAQtB,OAPA,EAAU,KAAqBC,EAAAA,gBAAgB,KAAK,CAAC,CAAC,GAAGC,EAAAA,aAAa,CAAC,CAAC,iBAAiB,EACzF,EAAU,KAAqBD,EAAAA,gBAAgB,aAAa,CAAC,CAAC,GAAGE,EAAAA,aAAa,CAAC,CAAC,iBAAiB,EACjG,EAAU,KAAsBF,EAAAA,gBAAgB,cAAc,CAAC,CAAC,GAAGG,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAmBH,EAAAA,gBAAgB,WAAW,CAAC,CAAC,GAAGI,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EAC3F,EAAU,KAA2BJ,EAAAA,gBAAgB,mBAAmB,CAAC,CAAC,GAAGK,EAAAA,mBAAmB,CAAC,CAAC,iBAAiB,EACnH,EAAU,KAAsBL,EAAAA,gBAAgB,cAAc,CAAC,CAAC,GAAGM,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAwBN,EAAAA,gBAAgB,QAAQ,CAAC,CAAC,GAAGO,EAAAA,gBAAgB,CAAC,CAAC,iBAAiB,EAC3F,CACT"}
1
+ {"version":3,"file":"index.cjs","names":["Container","FILE_EDIT_TYPES","FileEditPaths","TimelineStore","GitDiffService","EditTracker","EditorConfigService","EditorLauncher","FileEditWorkflow"],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { EditorConfigService } from '../services/EditorConfigService/EditorConfigService.ts';\nimport type { IEditorConfigService } from '../services/EditorConfigService/types.ts';\nimport { EditorLauncher } from '../services/EditorLauncher/EditorLauncher.ts';\nimport type { IEditorLauncher } from '../services/EditorLauncher/types.ts';\nimport { EditTracker } from '../services/EditTracker/EditTracker.ts';\nimport type { IEditTracker } from '../services/EditTracker/types.ts';\nimport { FileEditPaths } from '../services/FileEditPaths/FileEditPaths.ts';\nimport type { IFileEditPaths } from '../services/FileEditPaths/types.ts';\nimport { FileEditWorkflow } from '../services/FileEditWorkflow/FileEditWorkflow.ts';\nimport type { IFileEditWorkflow } from '../services/FileEditWorkflow/types.ts';\nimport { GitDiffService } from '../services/GitDiffService/GitDiffService.ts';\nimport type { IGitDiffService } from '../services/GitDiffService/types.ts';\nimport { TimelineStore } from '../services/TimelineStore/TimelineStore.ts';\nimport type { ITimelineStore } from '../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../types/index.ts';\n\nexport function createFileEditContainer(): Container {\n const container = new Container();\n container.bind<IFileEditPaths>(FILE_EDIT_TYPES.Paths).to(FileEditPaths).inSingletonScope();\n container.bind<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore).to(TimelineStore).inSingletonScope();\n container.bind<IGitDiffService>(FILE_EDIT_TYPES.GitDiffService).to(GitDiffService).inSingletonScope();\n container.bind<IEditTracker>(FILE_EDIT_TYPES.EditTracker).to(EditTracker).inSingletonScope();\n container.bind<IEditorConfigService>(FILE_EDIT_TYPES.EditorConfigService).to(EditorConfigService).inSingletonScope();\n container.bind<IEditorLauncher>(FILE_EDIT_TYPES.EditorLauncher).to(EditorLauncher).inSingletonScope();\n container.bind<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow).to(FileEditWorkflow).inSingletonScope();\n return container;\n}\n"],"mappings":"mgBAkBA,SAAgB,GAAqC,CACnD,IAAM,EAAY,IAAIA,EAAAA,UAQtB,OAPA,EAAU,KAAqBC,EAAAA,gBAAgB,KAAK,CAAC,CAAC,GAAGC,EAAAA,aAAa,CAAC,CAAC,iBAAiB,EACzF,EAAU,KAAqBD,EAAAA,gBAAgB,aAAa,CAAC,CAAC,GAAGE,EAAAA,aAAa,CAAC,CAAC,iBAAiB,EACjG,EAAU,KAAsBF,EAAAA,gBAAgB,cAAc,CAAC,CAAC,GAAGG,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAmBH,EAAAA,gBAAgB,WAAW,CAAC,CAAC,GAAGI,EAAAA,WAAW,CAAC,CAAC,iBAAiB,EAC3F,EAAU,KAA2BJ,EAAAA,gBAAgB,mBAAmB,CAAC,CAAC,GAAGK,EAAAA,mBAAmB,CAAC,CAAC,iBAAiB,EACnH,EAAU,KAAsBL,EAAAA,gBAAgB,cAAc,CAAC,CAAC,GAAGM,EAAAA,cAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAwBN,EAAAA,gBAAgB,QAAQ,CAAC,CAAC,GAAGO,EAAAA,gBAAgB,CAAC,CAAC,iBAAiB,EAC3F,CACT"}
@@ -1,2 +1,2 @@
1
- import{FILE_EDIT_TYPES as e}from"../types.mjs";import{EditTracker as t}from"../services/EditTracker/EditTracker.mjs";import{EditorConfigService as n}from"../services/EditorConfigService/EditorConfigService.mjs";import{EditorLauncher as r}from"../services/EditorLauncher/EditorLauncher.mjs";import{FileEditPaths as i}from"../services/FileEditPaths/FileEditPaths.mjs";import{FileEditWorkflow as a}from"../services/FileEditWorkflow/FileEditWorkflow.mjs";import{GitDiffService as o}from"../services/GitDiffService/GitDiffService.mjs";import{TimelineStore as s}from"../services/TimelineStore/TimelineStore.mjs";import{Container as c}from"inversify";import"reflect-metadata/lite";function l(){let l=new c;return l.bind(e.Paths).to(i).inSingletonScope(),l.bind(e.TimelineStore).to(s).inSingletonScope(),l.bind(e.GitDiffService).to(o).inSingletonScope(),l.bind(e.EditTracker).to(t).inSingletonScope(),l.bind(e.EditorConfigService).to(n).inSingletonScope(),l.bind(e.EditorLauncher).to(r).inSingletonScope(),l.bind(e.Workflow).to(a).inSingletonScope(),l}export{l as createFileEditContainer};
1
+ import{EditorConfigService as e}from"../services/EditorConfigService/EditorConfigService.mjs";import{FILE_EDIT_TYPES as t}from"../types/index.mjs";import{EditorLauncher as n}from"../services/EditorLauncher/EditorLauncher.mjs";import{EditTracker as r}from"../services/EditTracker/EditTracker.mjs";import{FileEditPaths as i}from"../services/FileEditPaths/FileEditPaths.mjs";import{FileEditWorkflow as a}from"../services/FileEditWorkflow/FileEditWorkflow.mjs";import{GitDiffService as o}from"../services/GitDiffService/GitDiffService.mjs";import{TimelineStore as s}from"../services/TimelineStore/TimelineStore.mjs";import{Container as c}from"inversify";import"reflect-metadata/lite";function l(){let l=new c;return l.bind(t.Paths).to(i).inSingletonScope(),l.bind(t.TimelineStore).to(s).inSingletonScope(),l.bind(t.GitDiffService).to(o).inSingletonScope(),l.bind(t.EditTracker).to(r).inSingletonScope(),l.bind(t.EditorConfigService).to(e).inSingletonScope(),l.bind(t.EditorLauncher).to(n).inSingletonScope(),l.bind(t.Workflow).to(a).inSingletonScope(),l}export{l as createFileEditContainer};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { EditTracker } from '../services/EditTracker/EditTracker.ts';\nimport type { IEditTracker } from '../services/EditTracker/types.ts';\nimport { EditorConfigService } from '../services/EditorConfigService/EditorConfigService.ts';\nimport type { IEditorConfigService } from '../services/EditorConfigService/types.ts';\nimport { EditorLauncher } from '../services/EditorLauncher/EditorLauncher.ts';\nimport type { IEditorLauncher } from '../services/EditorLauncher/types.ts';\nimport { FileEditPaths } from '../services/FileEditPaths/FileEditPaths.ts';\nimport type { IFileEditPaths } from '../services/FileEditPaths/types.ts';\nimport { FileEditWorkflow } from '../services/FileEditWorkflow/FileEditWorkflow.ts';\nimport type { IFileEditWorkflow } from '../services/FileEditWorkflow/types.ts';\nimport { GitDiffService } from '../services/GitDiffService/GitDiffService.ts';\nimport type { IGitDiffService } from '../services/GitDiffService/types.ts';\nimport { TimelineStore } from '../services/TimelineStore/TimelineStore.ts';\nimport type { ITimelineStore } from '../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../types.ts';\n\nexport function createFileEditContainer(): Container {\n const container = new Container();\n container.bind<IFileEditPaths>(FILE_EDIT_TYPES.Paths).to(FileEditPaths).inSingletonScope();\n container.bind<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore).to(TimelineStore).inSingletonScope();\n container.bind<IGitDiffService>(FILE_EDIT_TYPES.GitDiffService).to(GitDiffService).inSingletonScope();\n container.bind<IEditTracker>(FILE_EDIT_TYPES.EditTracker).to(EditTracker).inSingletonScope();\n container.bind<IEditorConfigService>(FILE_EDIT_TYPES.EditorConfigService).to(EditorConfigService).inSingletonScope();\n container.bind<IEditorLauncher>(FILE_EDIT_TYPES.EditorLauncher).to(EditorLauncher).inSingletonScope();\n container.bind<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow).to(FileEditWorkflow).inSingletonScope();\n return container;\n}\n"],"mappings":"kqBAkBA,SAAgB,GAAqC,CACnD,IAAM,EAAY,IAAI,EAQtB,OAPA,EAAU,KAAqB,EAAgB,KAAK,CAAC,CAAC,GAAG,CAAa,CAAC,CAAC,iBAAiB,EACzF,EAAU,KAAqB,EAAgB,aAAa,CAAC,CAAC,GAAG,CAAa,CAAC,CAAC,iBAAiB,EACjG,EAAU,KAAsB,EAAgB,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAmB,EAAgB,WAAW,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EAC3F,EAAU,KAA2B,EAAgB,mBAAmB,CAAC,CAAC,GAAG,CAAmB,CAAC,CAAC,iBAAiB,EACnH,EAAU,KAAsB,EAAgB,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAwB,EAAgB,QAAQ,CAAC,CAAC,GAAG,CAAgB,CAAC,CAAC,iBAAiB,EAC3F,CACT"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/container/index.ts"],"sourcesContent":["import { Container } from 'inversify';\nimport 'reflect-metadata/lite';\nimport { EditorConfigService } from '../services/EditorConfigService/EditorConfigService.ts';\nimport type { IEditorConfigService } from '../services/EditorConfigService/types.ts';\nimport { EditorLauncher } from '../services/EditorLauncher/EditorLauncher.ts';\nimport type { IEditorLauncher } from '../services/EditorLauncher/types.ts';\nimport { EditTracker } from '../services/EditTracker/EditTracker.ts';\nimport type { IEditTracker } from '../services/EditTracker/types.ts';\nimport { FileEditPaths } from '../services/FileEditPaths/FileEditPaths.ts';\nimport type { IFileEditPaths } from '../services/FileEditPaths/types.ts';\nimport { FileEditWorkflow } from '../services/FileEditWorkflow/FileEditWorkflow.ts';\nimport type { IFileEditWorkflow } from '../services/FileEditWorkflow/types.ts';\nimport { GitDiffService } from '../services/GitDiffService/GitDiffService.ts';\nimport type { IGitDiffService } from '../services/GitDiffService/types.ts';\nimport { TimelineStore } from '../services/TimelineStore/TimelineStore.ts';\nimport type { ITimelineStore } from '../services/TimelineStore/types.ts';\nimport { FILE_EDIT_TYPES } from '../types/index.ts';\n\nexport function createFileEditContainer(): Container {\n const container = new Container();\n container.bind<IFileEditPaths>(FILE_EDIT_TYPES.Paths).to(FileEditPaths).inSingletonScope();\n container.bind<ITimelineStore>(FILE_EDIT_TYPES.TimelineStore).to(TimelineStore).inSingletonScope();\n container.bind<IGitDiffService>(FILE_EDIT_TYPES.GitDiffService).to(GitDiffService).inSingletonScope();\n container.bind<IEditTracker>(FILE_EDIT_TYPES.EditTracker).to(EditTracker).inSingletonScope();\n container.bind<IEditorConfigService>(FILE_EDIT_TYPES.EditorConfigService).to(EditorConfigService).inSingletonScope();\n container.bind<IEditorLauncher>(FILE_EDIT_TYPES.EditorLauncher).to(EditorLauncher).inSingletonScope();\n container.bind<IFileEditWorkflow>(FILE_EDIT_TYPES.Workflow).to(FileEditWorkflow).inSingletonScope();\n return container;\n}\n"],"mappings":"wqBAkBA,SAAgB,GAAqC,CACnD,IAAM,EAAY,IAAI,EAQtB,OAPA,EAAU,KAAqB,EAAgB,KAAK,CAAC,CAAC,GAAG,CAAa,CAAC,CAAC,iBAAiB,EACzF,EAAU,KAAqB,EAAgB,aAAa,CAAC,CAAC,GAAG,CAAa,CAAC,CAAC,iBAAiB,EACjG,EAAU,KAAsB,EAAgB,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAmB,EAAgB,WAAW,CAAC,CAAC,GAAG,CAAW,CAAC,CAAC,iBAAiB,EAC3F,EAAU,KAA2B,EAAgB,mBAAmB,CAAC,CAAC,GAAG,CAAmB,CAAC,CAAC,iBAAiB,EACnH,EAAU,KAAsB,EAAgB,cAAc,CAAC,CAAC,GAAG,CAAc,CAAC,CAAC,iBAAiB,EACpG,EAAU,KAAwB,EAAgB,QAAQ,CAAC,CAAC,GAAG,CAAgB,CAAC,CAAC,iBAAiB,EAC3F,CACT"}
@@ -1,2 +1,2 @@
1
- Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../extension.cjs");let t=require("@agimon-ai/doompi-ui/leader");function n(n){e.fileEditExtension(n),(0,t.registerDoomLeaderContribution)(n,e.FILE_EDIT_LEADER_CONTRIBUTION)}exports.default=n,exports.doomFileEditExtension=n;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("../adapters/pi/extension.cjs");let t=require("@agimon-ai/doompi-ui/leader");function n(n){e.fileEditExtension(n),(0,t.registerDoomLeaderContribution)(n,e.FILE_EDIT_LEADER_CONTRIBUTION)}exports.default=n,exports.doomFileEditExtension=n;
2
2
  //# sourceMappingURL=doom.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"doom.cjs","names":["FILE_EDIT_LEADER_CONTRIBUTION"],"sources":["../../src/extensions/doom.ts"],"sourcesContent":["import { registerDoomLeaderContribution, type DoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { fileEditExtension, FILE_EDIT_LEADER_CONTRIBUTION } from '../extension.ts';\n\nexport function doomFileEditExtension(pi: ExtensionAPI): void {\n fileEditExtension(pi);\n registerDoomLeaderContribution(pi, FILE_EDIT_LEADER_CONTRIBUTION satisfies DoomLeaderContribution);\n}\n\nexport { doomFileEditExtension as default };\n"],"mappings":"gLAIA,SAAgB,EAAsB,EAAwB,CAC5D,EAAA,kBAAkB,CAAE,GACpB,EAAA,EAAA,+BAAA,CAA+B,EAAIA,EAAAA,6BAA8D,CACnG"}
1
+ {"version":3,"file":"doom.cjs","names":["FILE_EDIT_LEADER_CONTRIBUTION"],"sources":["../../src/extensions/doom.ts"],"sourcesContent":["import { type DoomLeaderContribution, registerDoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { FILE_EDIT_LEADER_CONTRIBUTION, fileEditExtension } from '../adapters/pi/extension.ts';\n\nexport function doomFileEditExtension(pi: ExtensionAPI): void {\n fileEditExtension(pi);\n registerDoomLeaderContribution(pi, FILE_EDIT_LEADER_CONTRIBUTION satisfies DoomLeaderContribution);\n}\n\nexport { doomFileEditExtension as default };\n"],"mappings":"4LAIA,SAAgB,EAAsB,EAAwB,CAC5D,EAAA,kBAAkB,CAAE,GACpB,EAAA,EAAA,+BAAA,CAA+B,EAAIA,EAAAA,6BAA8D,CACnG"}
@@ -1,2 +1,2 @@
1
- import{FILE_EDIT_LEADER_CONTRIBUTION as e,fileEditExtension as t}from"../extension.mjs";import{registerDoomLeaderContribution as n}from"@agimon-ai/doompi-ui/leader";function r(r){t(r),n(r,e)}export{r as default,r as doomFileEditExtension};
1
+ import{FILE_EDIT_LEADER_CONTRIBUTION as e,fileEditExtension as t}from"../adapters/pi/extension.mjs";import{registerDoomLeaderContribution as n}from"@agimon-ai/doompi-ui/leader";function r(r){t(r),n(r,e)}export{r as default,r as doomFileEditExtension};
2
2
  //# sourceMappingURL=doom.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"doom.mjs","names":[],"sources":["../../src/extensions/doom.ts"],"sourcesContent":["import { registerDoomLeaderContribution, type DoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { fileEditExtension, FILE_EDIT_LEADER_CONTRIBUTION } from '../extension.ts';\n\nexport function doomFileEditExtension(pi: ExtensionAPI): void {\n fileEditExtension(pi);\n registerDoomLeaderContribution(pi, FILE_EDIT_LEADER_CONTRIBUTION satisfies DoomLeaderContribution);\n}\n\nexport { doomFileEditExtension as default };\n"],"mappings":"qKAIA,SAAgB,EAAsB,EAAwB,CAC5D,EAAkB,CAAE,EACpB,EAA+B,EAAI,CAA8D,CACnG"}
1
+ {"version":3,"file":"doom.mjs","names":[],"sources":["../../src/extensions/doom.ts"],"sourcesContent":["import { type DoomLeaderContribution, registerDoomLeaderContribution } from '@agimon-ai/doompi-ui/leader';\nimport type { ExtensionAPI } from '@earendil-works/pi-coding-agent';\nimport { FILE_EDIT_LEADER_CONTRIBUTION, fileEditExtension } from '../adapters/pi/extension.ts';\n\nexport function doomFileEditExtension(pi: ExtensionAPI): void {\n fileEditExtension(pi);\n registerDoomLeaderContribution(pi, FILE_EDIT_LEADER_CONTRIBUTION satisfies DoomLeaderContribution);\n}\n\nexport { doomFileEditExtension as default };\n"],"mappings":"iLAIA,SAAgB,EAAsB,EAAwB,CAC5D,EAAkB,CAAE,EACpB,EAA+B,EAAI,CAA8D,CACnG"}
@@ -1 +1 @@
1
- const e=require("../extension.cjs");module.exports=e.fileEditExtension;
1
+ const e=require("../adapters/pi/extension.cjs");module.exports=e.fileEditExtension;
@@ -1,2 +1,2 @@
1
- import { fileEditExtension } from "../extension.cjs";
1
+ import { fileEditExtension } from "../adapters/pi/extension.cjs";
2
2
  export = fileEditExtension;
@@ -1,2 +1,2 @@
1
- import { fileEditExtension } from "../extension.mjs";
1
+ import { fileEditExtension } from "../adapters/pi/extension.mjs";
2
2
  export { fileEditExtension as default };
@@ -1 +1 @@
1
- import{fileEditExtension as e}from"../extension.mjs";export{e as default};
1
+ import{fileEditExtension as e}from"../adapters/pi/extension.mjs";export{e as default};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types.cjs"),t=require("./container/index.cjs"),n=require("./extension.cjs");exports.FILE_EDIT_TYPES=e.FILE_EDIT_TYPES,exports.createFileEditContainer=t.createFileEditContainer,exports.fileEditExtension=n.fileEditExtension;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./types/index.cjs"),t=require("./container/index.cjs"),n=require("./adapters/pi/extension.cjs");exports.FILE_EDIT_TYPES=e.FILE_EDIT_TYPES,exports.createFileEditContainer=t.createFileEditContainer,exports.fileEditExtension=n.fileEditExtension;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { fileEditExtension } from "./extension.cjs";
1
+ import { fileEditExtension } from "./adapters/pi/extension.cjs";
2
2
  import { createFileEditContainer } from "./container/index.cjs";
3
- import { FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent } from "./domain.cjs";
4
- import { FILE_EDIT_TYPES } from "./types.cjs";
3
+ import { FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent } from "./services/fileEdit/domain.cjs";
4
+ import { FILE_EDIT_TYPES } from "./types/index.cjs";
5
5
  export { FILE_EDIT_TYPES, FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent, createFileEditContainer, fileEditExtension };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { fileEditExtension } from "./extension.mjs";
1
+ import { fileEditExtension } from "./adapters/pi/extension.mjs";
2
2
  import { createFileEditContainer } from "./container/index.mjs";
3
- import { FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent } from "./domain.mjs";
4
- import { FILE_EDIT_TYPES } from "./types.mjs";
3
+ import { FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent } from "./services/fileEdit/domain.mjs";
4
+ import { FILE_EDIT_TYPES } from "./types/index.mjs";
5
5
  export { FILE_EDIT_TYPES, FileDiff, FileEditEntry, FileEditState, FileEditTool, ResolvedEditor, TimelineEvent, createFileEditContainer, fileEditExtension };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{FILE_EDIT_TYPES as e}from"./types.mjs";import{createFileEditContainer as t}from"./container/index.mjs";import{fileEditExtension as n}from"./extension.mjs";export{e as FILE_EDIT_TYPES,t as createFileEditContainer,n as fileEditExtension};
1
+ import{FILE_EDIT_TYPES as e}from"./types/index.mjs";import{createFileEditContainer as t}from"./container/index.mjs";import{fileEditExtension as n}from"./adapters/pi/extension.mjs";export{e as FILE_EDIT_TYPES,t as createFileEditContainer,n as fileEditExtension};
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../types.cjs"),n=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),r=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let a=require("inversify"),o=require("node:fs/promises");o=e.__toESM(o,1);let s=require("node:path");s=e.__toESM(s,1);const c=`edit`,l=`write`,u=`bash`,d=new Set([`ENOENT`,`ENAMETOOLONG`]);function f(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}let p=class{timeline;pending=new Map;constructor(e){this.timeline=e}async start(e,t,n,r){if(t===c||t===l){let i=f(n,`path`);if(!i)return;let a=s.default.resolve(r,i);this.pending.set(e,{tool:t,paths:new Map([[a,await this.fingerprint(a)]])});return}if(t!==u)return;let i=f(n,`command`);if(!i)return;let a=new Map;for(let e of this.literalPaths(i,r))a.set(e,await this.fingerprint(e));this.pending.set(e,{tool:u,paths:a})}async end(e,t){let n=this.pending.get(e);if(this.pending.delete(e),!(!n||t))for(let[e,t]of n.paths){let r=await this.fingerprint(e);(n.tool===c||n.tool===l||JSON.stringify(t)!==JSON.stringify(r))&&await this.timeline.append({version:1,path:e,tool:n.tool,at:Date.now()})}}literalPaths(e,t){let n=(e.match(/"[^"]+"|'[^']+'|[^\s|;&<>]+/gu)??[]).map(e=>e.replace(/^['"]|['"]$/gu,``)).filter(e=>!e.startsWith(`-`)&&(e.includes(`/`)||/\.[a-z0-9_-]+$/iu.test(e))).map(e=>s.default.resolve(t,e));return[...new Set(n)]}async fingerprint(e){try{let t=await o.default.stat(e);return{exists:t.isFile(),size:t.size,modified:t.mtimeMs}}catch(e){if(e instanceof Error&&`code`in e&&typeof e.code==`string`&&d.has(e.code))return{exists:!1,size:0,modified:0};throw e}}};p=i.default([(0,a.injectable)(),r.default(0,(0,a.inject)(t.FILE_EDIT_TYPES.TimelineStore)),n.default(`design:paramtypes`,[Object])],p),Object.defineProperty(exports,"EditTracker",{enumerable:!0,get:function(){return p}});
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs"),n=require("../../types/index.cjs"),r=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs");let a=require("inversify"),o=require("node:fs/promises");o=e.__toESM(o,1);let s=require("node:path");s=e.__toESM(s,1);const c=`edit`,l=`write`,u=`bash`,d=new Set([`ENOENT`,`ENAMETOOLONG`]);function f(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}let p=class{timeline;pending=new Map;constructor(e){this.timeline=e}async start(e,t,n,r){if(t===c||t===l){let i=f(n,`path`);if(!i)return;let a=s.default.resolve(r,i);this.pending.set(e,{tool:t,paths:new Map([[a,await this.fingerprint(a)]])});return}if(t!==u)return;let i=f(n,`command`);if(!i)return;let a=new Map;for(let e of this.literalPaths(i,r))a.set(e,await this.fingerprint(e));this.pending.set(e,{tool:u,paths:a})}async end(e,t){let n=this.pending.get(e);if(this.pending.delete(e),!(!n||t))for(let[e,t]of n.paths){let r=await this.fingerprint(e);(n.tool===c||n.tool===l||JSON.stringify(t)!==JSON.stringify(r))&&await this.timeline.append({version:1,path:e,tool:n.tool,at:Date.now()})}}literalPaths(e,t){let n=(e.match(/"[^"]+"|'[^']+'|[^\s|;&<>]+/gu)??[]).map(e=>e.replace(/^['"]|['"]$/gu,``)).filter(e=>!e.startsWith(`-`)&&(e.includes(`/`)||/\.[a-z0-9_-]+$/iu.test(e))).map(e=>s.default.resolve(t,e));return[...new Set(n)]}async fingerprint(e){try{let t=await o.default.stat(e);return{exists:t.isFile(),size:t.size,modified:t.mtimeMs}}catch(e){if(e instanceof Error&&`code`in e&&typeof e.code==`string`&&d.has(e.code))return{exists:!1,size:0,modified:0};throw e}}};p=t.default([(0,a.injectable)(),i.default(0,(0,a.inject)(n.FILE_EDIT_TYPES.TimelineStore)),r.default(`design:paramtypes`,[Object])],p),Object.defineProperty(exports,"EditTracker",{enumerable:!0,get:function(){return p}});
2
2
  //# sourceMappingURL=EditTracker.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditTracker.cjs","names":["path","fs","injectable","inject","FILE_EDIT_TYPES"],"sources":["../../../src/services/EditTracker/EditTracker.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport type { FileEditTool } from '../../domain.ts';\nimport { FILE_EDIT_TYPES } from '../../types.ts';\nimport type { ITimelineStore } from '../TimelineStore/types.ts';\nimport type { IEditTracker } from './types.ts';\n\nconst EDIT_TOOL = 'edit';\nconst WRITE_TOOL = 'write';\nconst BASH_TOOL = 'bash';\nconst MISSING_PATH_ERROR_CODES = new Set(['ENOENT', 'ENAMETOOLONG']);\n\ninterface Fingerprint {\n exists: boolean;\n size: number;\n modified: number;\n}\n\ninterface PendingEdit {\n tool: FileEditTool;\n paths: Map<string, Fingerprint>;\n}\n\nfunction objectValue(value: unknown, key: string): string | undefined {\n if (!value || typeof value !== 'object') return undefined;\n const found = (value as Record<string, unknown>)[key];\n return typeof found === 'string' ? found : undefined;\n}\n\n@injectable()\nexport class EditTracker implements IEditTracker {\n private readonly pending = new Map<string, PendingEdit>();\n\n constructor(@inject(FILE_EDIT_TYPES.TimelineStore) private readonly timeline: ITimelineStore) {}\n\n async start(id: string, tool: string, args: unknown, cwd: string): Promise<void> {\n if (tool === EDIT_TOOL || tool === WRITE_TOOL) {\n const supplied = objectValue(args, 'path');\n if (!supplied) return;\n const absolute = path.resolve(cwd, supplied);\n this.pending.set(id, { tool, paths: new Map([[absolute, await this.fingerprint(absolute)]]) });\n return;\n }\n if (tool !== BASH_TOOL) return;\n const command = objectValue(args, 'command');\n if (!command) return;\n const paths = new Map<string, Fingerprint>();\n for (const candidate of this.literalPaths(command, cwd)) paths.set(candidate, await this.fingerprint(candidate));\n this.pending.set(id, { tool: BASH_TOOL, paths });\n }\n\n async end(id: string, isError: boolean): Promise<void> {\n const pending = this.pending.get(id);\n this.pending.delete(id);\n if (!pending || isError) return;\n for (const [filePath, before] of pending.paths) {\n const after = await this.fingerprint(filePath);\n const exactTool = pending.tool === EDIT_TOOL || pending.tool === WRITE_TOOL;\n if (exactTool || JSON.stringify(before) !== JSON.stringify(after)) {\n await this.timeline.append({ version: 1, path: filePath, tool: pending.tool, at: Date.now() });\n }\n }\n }\n\n private literalPaths(command: string, cwd: string): string[] {\n const tokens = command.match(/\"[^\"]+\"|'[^']+'|[^\\s|;&<>]+/gu) ?? [];\n const candidates = tokens\n .map((token) => token.replace(/^['\"]|['\"]$/gu, ''))\n .filter((token) => !token.startsWith('-') && (token.includes('/') || /\\.[a-z0-9_-]+$/iu.test(token)))\n .map((token) => path.resolve(cwd, token));\n return [...new Set(candidates)];\n }\n\n private async fingerprint(filePath: string): Promise<Fingerprint> {\n try {\n const stat = await fs.stat(filePath);\n return { exists: stat.isFile(), size: stat.size, modified: stat.mtimeMs };\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof error.code === 'string' &&\n MISSING_PATH_ERROR_CODES.has(error.code)\n ) {\n return { exists: false, size: 0, modified: 0 };\n }\n throw error;\n }\n }\n}\n"],"mappings":"idAQA,MAAM,EAAY,OACZ,EAAa,QACb,EAAY,OACZ,EAA2B,IAAI,IAAI,CAAC,SAAU,cAAc,CAAC,EAanE,SAAS,EAAY,EAAgB,EAAiC,CACpE,GAAI,CAAC,GAAS,OAAO,GAAU,SAAU,OACzC,IAAM,EAAS,EAAkC,GACjD,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAGO,IAAM,EAAN,KAA0C,CAGqB,SAFpE,QAA2B,IAAI,IAE/B,YAAY,EAAkF,CAA1B,KAAA,SAAA,CAA2B,CAE/F,MAAM,MAAM,EAAY,EAAc,EAAe,EAA4B,CAC/E,GAAI,IAAS,GAAa,IAAS,EAAY,CAC7C,IAAM,EAAW,EAAY,EAAM,MAAM,EACzC,GAAI,CAAC,EAAU,OACf,IAAM,EAAWA,EAAAA,QAAK,QAAQ,EAAK,CAAQ,EAC3C,KAAK,QAAQ,IAAI,EAAI,CAAE,OAAM,MAAO,IAAI,IAAI,CAAC,CAAC,EAAU,MAAM,KAAK,YAAY,CAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,EAC7F,MACF,CACA,GAAI,IAAS,EAAW,OACxB,IAAM,EAAU,EAAY,EAAM,SAAS,EAC3C,GAAI,CAAC,EAAS,OACd,IAAM,EAAQ,IAAI,IAClB,IAAK,IAAM,KAAa,KAAK,aAAa,EAAS,CAAG,EAAG,EAAM,IAAI,EAAW,MAAM,KAAK,YAAY,CAAS,CAAC,EAC/G,KAAK,QAAQ,IAAI,EAAI,CAAE,KAAM,EAAW,OAAM,CAAC,CACjD,CAEA,MAAM,IAAI,EAAY,EAAiC,CACrD,IAAM,EAAU,KAAK,QAAQ,IAAI,CAAE,EACnC,QAAK,QAAQ,OAAO,CAAE,EAClB,GAAC,GAAW,GAChB,IAAK,GAAM,CAAC,EAAU,KAAW,EAAQ,MAAO,CAC9C,IAAM,EAAQ,MAAM,KAAK,YAAY,CAAQ,GAC3B,EAAQ,OAAS,GAAa,EAAQ,OAAS,GAChD,KAAK,UAAU,CAAM,IAAM,KAAK,UAAU,CAAK,IAC9D,MAAM,KAAK,SAAS,OAAO,CAAE,QAAS,EAAG,KAAM,EAAU,KAAM,EAAQ,KAAM,GAAI,KAAK,IAAI,CAAE,CAAC,CAEjG,CACF,CAEA,aAAqB,EAAiB,EAAuB,CAE3D,IAAM,GADS,EAAQ,MAAM,+BAA+B,GAAK,CAAC,EAAA,CAE/D,IAAK,GAAU,EAAM,QAAQ,gBAAiB,EAAE,CAAC,CAAC,CAClD,OAAQ,GAAU,CAAC,EAAM,WAAW,GAAG,IAAM,EAAM,SAAS,GAAG,GAAK,mBAAmB,KAAK,CAAK,EAAE,CAAC,CACpG,IAAK,GAAUA,EAAAA,QAAK,QAAQ,EAAK,CAAK,CAAC,EAC1C,MAAO,CAAC,GAAG,IAAI,IAAI,CAAU,CAAC,CAChC,CAEA,MAAc,YAAY,EAAwC,CAChE,GAAI,CACF,IAAM,EAAO,MAAMC,EAAAA,QAAG,KAAK,CAAQ,EACnC,MAAO,CAAE,OAAQ,EAAK,OAAO,EAAG,KAAM,EAAK,KAAM,SAAU,EAAK,OAAQ,CAC1E,OAAS,EAAO,CACd,GACE,aAAiB,OACjB,SAAU,GACV,OAAO,EAAM,MAAS,UACtB,EAAyB,IAAI,EAAM,IAAI,EAEvC,MAAO,CAAE,OAAQ,GAAO,KAAM,EAAG,SAAU,CAAE,EAE/C,MAAM,CACR,CACF,CACF,gBA5DCC,EAAAA,EAAAA,WAAAA,CAAW,EAIGC,EAAAA,QAAAA,GAAAA,EAAAA,EAAAA,OAAAA,CAAOC,EAAAA,gBAAgB,aAAa,CAAA"}
1
+ {"version":3,"file":"EditTracker.cjs","names":["path","fs","injectable","inject","FILE_EDIT_TYPES"],"sources":["../../../src/services/EditTracker/EditTracker.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\nimport type { FileEditTool } from '../fileEdit/domain.ts';\nimport type { ITimelineStore } from '../TimelineStore/types.ts';\nimport type { IEditTracker } from './types.ts';\n\nconst EDIT_TOOL = 'edit';\nconst WRITE_TOOL = 'write';\nconst BASH_TOOL = 'bash';\nconst MISSING_PATH_ERROR_CODES = new Set(['ENOENT', 'ENAMETOOLONG']);\n\ninterface Fingerprint {\n exists: boolean;\n size: number;\n modified: number;\n}\n\ninterface PendingEdit {\n tool: FileEditTool;\n paths: Map<string, Fingerprint>;\n}\n\nfunction objectValue(value: unknown, key: string): string | undefined {\n if (!value || typeof value !== 'object') return undefined;\n const found = (value as Record<string, unknown>)[key];\n return typeof found === 'string' ? found : undefined;\n}\n\n@injectable()\nexport class EditTracker implements IEditTracker {\n private readonly pending = new Map<string, PendingEdit>();\n\n constructor(@inject(FILE_EDIT_TYPES.TimelineStore) private readonly timeline: ITimelineStore) {}\n\n async start(id: string, tool: string, args: unknown, cwd: string): Promise<void> {\n if (tool === EDIT_TOOL || tool === WRITE_TOOL) {\n const supplied = objectValue(args, 'path');\n if (!supplied) return;\n const absolute = path.resolve(cwd, supplied);\n this.pending.set(id, { tool, paths: new Map([[absolute, await this.fingerprint(absolute)]]) });\n return;\n }\n if (tool !== BASH_TOOL) return;\n const command = objectValue(args, 'command');\n if (!command) return;\n const paths = new Map<string, Fingerprint>();\n for (const candidate of this.literalPaths(command, cwd)) paths.set(candidate, await this.fingerprint(candidate));\n this.pending.set(id, { tool: BASH_TOOL, paths });\n }\n\n async end(id: string, isError: boolean): Promise<void> {\n const pending = this.pending.get(id);\n this.pending.delete(id);\n if (!pending || isError) return;\n for (const [filePath, before] of pending.paths) {\n const after = await this.fingerprint(filePath);\n const exactTool = pending.tool === EDIT_TOOL || pending.tool === WRITE_TOOL;\n if (exactTool || JSON.stringify(before) !== JSON.stringify(after)) {\n await this.timeline.append({ version: 1, path: filePath, tool: pending.tool, at: Date.now() });\n }\n }\n }\n\n private literalPaths(command: string, cwd: string): string[] {\n const tokens = command.match(/\"[^\"]+\"|'[^']+'|[^\\s|;&<>]+/gu) ?? [];\n const candidates = tokens\n .map((token) => token.replace(/^['\"]|['\"]$/gu, ''))\n .filter((token) => !token.startsWith('-') && (token.includes('/') || /\\.[a-z0-9_-]+$/iu.test(token)))\n .map((token) => path.resolve(cwd, token));\n return [...new Set(candidates)];\n }\n\n private async fingerprint(filePath: string): Promise<Fingerprint> {\n try {\n const stat = await fs.stat(filePath);\n return { exists: stat.isFile(), size: stat.size, modified: stat.mtimeMs };\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof error.code === 'string' &&\n MISSING_PATH_ERROR_CODES.has(error.code)\n ) {\n return { exists: false, size: 0, modified: 0 };\n }\n throw error;\n }\n }\n}\n"],"mappings":"udAQA,MAAM,EAAY,OACZ,EAAa,QACb,EAAY,OACZ,EAA2B,IAAI,IAAI,CAAC,SAAU,cAAc,CAAC,EAanE,SAAS,EAAY,EAAgB,EAAiC,CACpE,GAAI,CAAC,GAAS,OAAO,GAAU,SAAU,OACzC,IAAM,EAAS,EAAkC,GACjD,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAGO,IAAM,EAAN,KAA0C,CAGqB,SAFpE,QAA2B,IAAI,IAE/B,YAAY,EAAkF,CAA1B,KAAA,SAAA,CAA2B,CAE/F,MAAM,MAAM,EAAY,EAAc,EAAe,EAA4B,CAC/E,GAAI,IAAS,GAAa,IAAS,EAAY,CAC7C,IAAM,EAAW,EAAY,EAAM,MAAM,EACzC,GAAI,CAAC,EAAU,OACf,IAAM,EAAWA,EAAAA,QAAK,QAAQ,EAAK,CAAQ,EAC3C,KAAK,QAAQ,IAAI,EAAI,CAAE,OAAM,MAAO,IAAI,IAAI,CAAC,CAAC,EAAU,MAAM,KAAK,YAAY,CAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,EAC7F,MACF,CACA,GAAI,IAAS,EAAW,OACxB,IAAM,EAAU,EAAY,EAAM,SAAS,EAC3C,GAAI,CAAC,EAAS,OACd,IAAM,EAAQ,IAAI,IAClB,IAAK,IAAM,KAAa,KAAK,aAAa,EAAS,CAAG,EAAG,EAAM,IAAI,EAAW,MAAM,KAAK,YAAY,CAAS,CAAC,EAC/G,KAAK,QAAQ,IAAI,EAAI,CAAE,KAAM,EAAW,OAAM,CAAC,CACjD,CAEA,MAAM,IAAI,EAAY,EAAiC,CACrD,IAAM,EAAU,KAAK,QAAQ,IAAI,CAAE,EACnC,QAAK,QAAQ,OAAO,CAAE,EAClB,GAAC,GAAW,GAChB,IAAK,GAAM,CAAC,EAAU,KAAW,EAAQ,MAAO,CAC9C,IAAM,EAAQ,MAAM,KAAK,YAAY,CAAQ,GAC3B,EAAQ,OAAS,GAAa,EAAQ,OAAS,GAChD,KAAK,UAAU,CAAM,IAAM,KAAK,UAAU,CAAK,IAC9D,MAAM,KAAK,SAAS,OAAO,CAAE,QAAS,EAAG,KAAM,EAAU,KAAM,EAAQ,KAAM,GAAI,KAAK,IAAI,CAAE,CAAC,CAEjG,CACF,CAEA,aAAqB,EAAiB,EAAuB,CAE3D,IAAM,GADS,EAAQ,MAAM,+BAA+B,GAAK,CAAC,EAAA,CAE/D,IAAK,GAAU,EAAM,QAAQ,gBAAiB,EAAE,CAAC,CAAC,CAClD,OAAQ,GAAU,CAAC,EAAM,WAAW,GAAG,IAAM,EAAM,SAAS,GAAG,GAAK,mBAAmB,KAAK,CAAK,EAAE,CAAC,CACpG,IAAK,GAAUA,EAAAA,QAAK,QAAQ,EAAK,CAAK,CAAC,EAC1C,MAAO,CAAC,GAAG,IAAI,IAAI,CAAU,CAAC,CAChC,CAEA,MAAc,YAAY,EAAwC,CAChE,GAAI,CACF,IAAM,EAAO,MAAMC,EAAAA,QAAG,KAAK,CAAQ,EACnC,MAAO,CAAE,OAAQ,EAAK,OAAO,EAAG,KAAM,EAAK,KAAM,SAAU,EAAK,OAAQ,CAC1E,OAAS,EAAO,CACd,GACE,aAAiB,OACjB,SAAU,GACV,OAAO,EAAM,MAAS,UACtB,EAAyB,IAAI,EAAM,IAAI,EAEvC,MAAO,CAAE,OAAQ,GAAO,KAAM,EAAG,SAAU,CAAE,EAE/C,MAAM,CACR,CACF,CACF,gBA5DCC,EAAAA,EAAAA,WAAAA,CAAW,EAIGC,EAAAA,QAAAA,GAAAA,EAAAA,EAAAA,OAAAA,CAAOC,EAAAA,gBAAgB,aAAa,CAAA"}
@@ -1,2 +1,2 @@
1
- import{FILE_EDIT_TYPES as e}from"../../types.mjs";import t from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import n from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import r from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{inject as i,injectable as a}from"inversify";import o from"node:fs/promises";import s from"node:path";const c=`edit`,l=`write`,u=`bash`,d=new Set([`ENOENT`,`ENAMETOOLONG`]);function f(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}let p=class{timeline;pending=new Map;constructor(e){this.timeline=e}async start(e,t,n,r){if(t===c||t===l){let i=f(n,`path`);if(!i)return;let a=s.resolve(r,i);this.pending.set(e,{tool:t,paths:new Map([[a,await this.fingerprint(a)]])});return}if(t!==u)return;let i=f(n,`command`);if(!i)return;let a=new Map;for(let e of this.literalPaths(i,r))a.set(e,await this.fingerprint(e));this.pending.set(e,{tool:u,paths:a})}async end(e,t){let n=this.pending.get(e);if(this.pending.delete(e),!(!n||t))for(let[e,t]of n.paths){let r=await this.fingerprint(e);(n.tool===c||n.tool===l||JSON.stringify(t)!==JSON.stringify(r))&&await this.timeline.append({version:1,path:e,tool:n.tool,at:Date.now()})}}literalPaths(e,t){let n=(e.match(/"[^"]+"|'[^']+'|[^\s|;&<>]+/gu)??[]).map(e=>e.replace(/^['"]|['"]$/gu,``)).filter(e=>!e.startsWith(`-`)&&(e.includes(`/`)||/\.[a-z0-9_-]+$/iu.test(e))).map(e=>s.resolve(t,e));return[...new Set(n)]}async fingerprint(e){try{let t=await o.stat(e);return{exists:t.isFile(),size:t.size,modified:t.mtimeMs}}catch(e){if(e instanceof Error&&`code`in e&&typeof e.code==`string`&&d.has(e.code))return{exists:!1,size:0,modified:0};throw e}}};p=r([a(),n(0,i(e.TimelineStore)),t(`design:paramtypes`,[Object])],p);export{p as EditTracker};
1
+ import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{FILE_EDIT_TYPES as t}from"../../types/index.mjs";import n from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import r from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import{inject as i,injectable as a}from"inversify";import o from"node:fs/promises";import s from"node:path";const c=`edit`,l=`write`,u=`bash`,d=new Set([`ENOENT`,`ENAMETOOLONG`]);function f(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}let p=class{timeline;pending=new Map;constructor(e){this.timeline=e}async start(e,t,n,r){if(t===c||t===l){let i=f(n,`path`);if(!i)return;let a=s.resolve(r,i);this.pending.set(e,{tool:t,paths:new Map([[a,await this.fingerprint(a)]])});return}if(t!==u)return;let i=f(n,`command`);if(!i)return;let a=new Map;for(let e of this.literalPaths(i,r))a.set(e,await this.fingerprint(e));this.pending.set(e,{tool:u,paths:a})}async end(e,t){let n=this.pending.get(e);if(this.pending.delete(e),!(!n||t))for(let[e,t]of n.paths){let r=await this.fingerprint(e);(n.tool===c||n.tool===l||JSON.stringify(t)!==JSON.stringify(r))&&await this.timeline.append({version:1,path:e,tool:n.tool,at:Date.now()})}}literalPaths(e,t){let n=(e.match(/"[^"]+"|'[^']+'|[^\s|;&<>]+/gu)??[]).map(e=>e.replace(/^['"]|['"]$/gu,``)).filter(e=>!e.startsWith(`-`)&&(e.includes(`/`)||/\.[a-z0-9_-]+$/iu.test(e))).map(e=>s.resolve(t,e));return[...new Set(n)]}async fingerprint(e){try{let t=await o.stat(e);return{exists:t.isFile(),size:t.size,modified:t.mtimeMs}}catch(e){if(e instanceof Error&&`code`in e&&typeof e.code==`string`&&d.has(e.code))return{exists:!1,size:0,modified:0};throw e}}};p=e([a(),r(0,i(t.TimelineStore)),n(`design:paramtypes`,[Object])],p);export{p as EditTracker};
2
2
  //# sourceMappingURL=EditTracker.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditTracker.mjs","names":[],"sources":["../../../src/services/EditTracker/EditTracker.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport type { FileEditTool } from '../../domain.ts';\nimport { FILE_EDIT_TYPES } from '../../types.ts';\nimport type { ITimelineStore } from '../TimelineStore/types.ts';\nimport type { IEditTracker } from './types.ts';\n\nconst EDIT_TOOL = 'edit';\nconst WRITE_TOOL = 'write';\nconst BASH_TOOL = 'bash';\nconst MISSING_PATH_ERROR_CODES = new Set(['ENOENT', 'ENAMETOOLONG']);\n\ninterface Fingerprint {\n exists: boolean;\n size: number;\n modified: number;\n}\n\ninterface PendingEdit {\n tool: FileEditTool;\n paths: Map<string, Fingerprint>;\n}\n\nfunction objectValue(value: unknown, key: string): string | undefined {\n if (!value || typeof value !== 'object') return undefined;\n const found = (value as Record<string, unknown>)[key];\n return typeof found === 'string' ? found : undefined;\n}\n\n@injectable()\nexport class EditTracker implements IEditTracker {\n private readonly pending = new Map<string, PendingEdit>();\n\n constructor(@inject(FILE_EDIT_TYPES.TimelineStore) private readonly timeline: ITimelineStore) {}\n\n async start(id: string, tool: string, args: unknown, cwd: string): Promise<void> {\n if (tool === EDIT_TOOL || tool === WRITE_TOOL) {\n const supplied = objectValue(args, 'path');\n if (!supplied) return;\n const absolute = path.resolve(cwd, supplied);\n this.pending.set(id, { tool, paths: new Map([[absolute, await this.fingerprint(absolute)]]) });\n return;\n }\n if (tool !== BASH_TOOL) return;\n const command = objectValue(args, 'command');\n if (!command) return;\n const paths = new Map<string, Fingerprint>();\n for (const candidate of this.literalPaths(command, cwd)) paths.set(candidate, await this.fingerprint(candidate));\n this.pending.set(id, { tool: BASH_TOOL, paths });\n }\n\n async end(id: string, isError: boolean): Promise<void> {\n const pending = this.pending.get(id);\n this.pending.delete(id);\n if (!pending || isError) return;\n for (const [filePath, before] of pending.paths) {\n const after = await this.fingerprint(filePath);\n const exactTool = pending.tool === EDIT_TOOL || pending.tool === WRITE_TOOL;\n if (exactTool || JSON.stringify(before) !== JSON.stringify(after)) {\n await this.timeline.append({ version: 1, path: filePath, tool: pending.tool, at: Date.now() });\n }\n }\n }\n\n private literalPaths(command: string, cwd: string): string[] {\n const tokens = command.match(/\"[^\"]+\"|'[^']+'|[^\\s|;&<>]+/gu) ?? [];\n const candidates = tokens\n .map((token) => token.replace(/^['\"]|['\"]$/gu, ''))\n .filter((token) => !token.startsWith('-') && (token.includes('/') || /\\.[a-z0-9_-]+$/iu.test(token)))\n .map((token) => path.resolve(cwd, token));\n return [...new Set(candidates)];\n }\n\n private async fingerprint(filePath: string): Promise<Fingerprint> {\n try {\n const stat = await fs.stat(filePath);\n return { exists: stat.isFile(), size: stat.size, modified: stat.mtimeMs };\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof error.code === 'string' &&\n MISSING_PATH_ERROR_CODES.has(error.code)\n ) {\n return { exists: false, size: 0, modified: 0 };\n }\n throw error;\n }\n }\n}\n"],"mappings":"0aAQA,MAAM,EAAY,OACZ,EAAa,QACb,EAAY,OACZ,EAA2B,IAAI,IAAI,CAAC,SAAU,cAAc,CAAC,EAanE,SAAS,EAAY,EAAgB,EAAiC,CACpE,GAAI,CAAC,GAAS,OAAO,GAAU,SAAU,OACzC,IAAM,EAAS,EAAkC,GACjD,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAGO,IAAM,EAAN,KAA0C,CAGqB,SAFpE,QAA2B,IAAI,IAE/B,YAAY,EAAkF,CAA1B,KAAA,SAAA,CAA2B,CAE/F,MAAM,MAAM,EAAY,EAAc,EAAe,EAA4B,CAC/E,GAAI,IAAS,GAAa,IAAS,EAAY,CAC7C,IAAM,EAAW,EAAY,EAAM,MAAM,EACzC,GAAI,CAAC,EAAU,OACf,IAAM,EAAW,EAAK,QAAQ,EAAK,CAAQ,EAC3C,KAAK,QAAQ,IAAI,EAAI,CAAE,OAAM,MAAO,IAAI,IAAI,CAAC,CAAC,EAAU,MAAM,KAAK,YAAY,CAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,EAC7F,MACF,CACA,GAAI,IAAS,EAAW,OACxB,IAAM,EAAU,EAAY,EAAM,SAAS,EAC3C,GAAI,CAAC,EAAS,OACd,IAAM,EAAQ,IAAI,IAClB,IAAK,IAAM,KAAa,KAAK,aAAa,EAAS,CAAG,EAAG,EAAM,IAAI,EAAW,MAAM,KAAK,YAAY,CAAS,CAAC,EAC/G,KAAK,QAAQ,IAAI,EAAI,CAAE,KAAM,EAAW,OAAM,CAAC,CACjD,CAEA,MAAM,IAAI,EAAY,EAAiC,CACrD,IAAM,EAAU,KAAK,QAAQ,IAAI,CAAE,EACnC,QAAK,QAAQ,OAAO,CAAE,EAClB,GAAC,GAAW,GAChB,IAAK,GAAM,CAAC,EAAU,KAAW,EAAQ,MAAO,CAC9C,IAAM,EAAQ,MAAM,KAAK,YAAY,CAAQ,GAC3B,EAAQ,OAAS,GAAa,EAAQ,OAAS,GAChD,KAAK,UAAU,CAAM,IAAM,KAAK,UAAU,CAAK,IAC9D,MAAM,KAAK,SAAS,OAAO,CAAE,QAAS,EAAG,KAAM,EAAU,KAAM,EAAQ,KAAM,GAAI,KAAK,IAAI,CAAE,CAAC,CAEjG,CACF,CAEA,aAAqB,EAAiB,EAAuB,CAE3D,IAAM,GADS,EAAQ,MAAM,+BAA+B,GAAK,CAAC,EAAA,CAE/D,IAAK,GAAU,EAAM,QAAQ,gBAAiB,EAAE,CAAC,CAAC,CAClD,OAAQ,GAAU,CAAC,EAAM,WAAW,GAAG,IAAM,EAAM,SAAS,GAAG,GAAK,mBAAmB,KAAK,CAAK,EAAE,CAAC,CACpG,IAAK,GAAU,EAAK,QAAQ,EAAK,CAAK,CAAC,EAC1C,MAAO,CAAC,GAAG,IAAI,IAAI,CAAU,CAAC,CAChC,CAEA,MAAc,YAAY,EAAwC,CAChE,GAAI,CACF,IAAM,EAAO,MAAM,EAAG,KAAK,CAAQ,EACnC,MAAO,CAAE,OAAQ,EAAK,OAAO,EAAG,KAAM,EAAK,KAAM,SAAU,EAAK,OAAQ,CAC1E,OAAS,EAAO,CACd,GACE,aAAiB,OACjB,SAAU,GACV,OAAO,EAAM,MAAS,UACtB,EAAyB,IAAI,EAAM,IAAI,EAEvC,MAAO,CAAE,OAAQ,GAAO,KAAM,EAAG,SAAU,CAAE,EAE/C,MAAM,CACR,CACF,CACF,OA5DC,EAAW,EAIG,EAAA,EAAA,EAAO,EAAgB,aAAa,CAAA"}
1
+ {"version":3,"file":"EditTracker.mjs","names":[],"sources":["../../../src/services/EditTracker/EditTracker.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { inject, injectable } from 'inversify';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\nimport type { FileEditTool } from '../fileEdit/domain.ts';\nimport type { ITimelineStore } from '../TimelineStore/types.ts';\nimport type { IEditTracker } from './types.ts';\n\nconst EDIT_TOOL = 'edit';\nconst WRITE_TOOL = 'write';\nconst BASH_TOOL = 'bash';\nconst MISSING_PATH_ERROR_CODES = new Set(['ENOENT', 'ENAMETOOLONG']);\n\ninterface Fingerprint {\n exists: boolean;\n size: number;\n modified: number;\n}\n\ninterface PendingEdit {\n tool: FileEditTool;\n paths: Map<string, Fingerprint>;\n}\n\nfunction objectValue(value: unknown, key: string): string | undefined {\n if (!value || typeof value !== 'object') return undefined;\n const found = (value as Record<string, unknown>)[key];\n return typeof found === 'string' ? found : undefined;\n}\n\n@injectable()\nexport class EditTracker implements IEditTracker {\n private readonly pending = new Map<string, PendingEdit>();\n\n constructor(@inject(FILE_EDIT_TYPES.TimelineStore) private readonly timeline: ITimelineStore) {}\n\n async start(id: string, tool: string, args: unknown, cwd: string): Promise<void> {\n if (tool === EDIT_TOOL || tool === WRITE_TOOL) {\n const supplied = objectValue(args, 'path');\n if (!supplied) return;\n const absolute = path.resolve(cwd, supplied);\n this.pending.set(id, { tool, paths: new Map([[absolute, await this.fingerprint(absolute)]]) });\n return;\n }\n if (tool !== BASH_TOOL) return;\n const command = objectValue(args, 'command');\n if (!command) return;\n const paths = new Map<string, Fingerprint>();\n for (const candidate of this.literalPaths(command, cwd)) paths.set(candidate, await this.fingerprint(candidate));\n this.pending.set(id, { tool: BASH_TOOL, paths });\n }\n\n async end(id: string, isError: boolean): Promise<void> {\n const pending = this.pending.get(id);\n this.pending.delete(id);\n if (!pending || isError) return;\n for (const [filePath, before] of pending.paths) {\n const after = await this.fingerprint(filePath);\n const exactTool = pending.tool === EDIT_TOOL || pending.tool === WRITE_TOOL;\n if (exactTool || JSON.stringify(before) !== JSON.stringify(after)) {\n await this.timeline.append({ version: 1, path: filePath, tool: pending.tool, at: Date.now() });\n }\n }\n }\n\n private literalPaths(command: string, cwd: string): string[] {\n const tokens = command.match(/\"[^\"]+\"|'[^']+'|[^\\s|;&<>]+/gu) ?? [];\n const candidates = tokens\n .map((token) => token.replace(/^['\"]|['\"]$/gu, ''))\n .filter((token) => !token.startsWith('-') && (token.includes('/') || /\\.[a-z0-9_-]+$/iu.test(token)))\n .map((token) => path.resolve(cwd, token));\n return [...new Set(candidates)];\n }\n\n private async fingerprint(filePath: string): Promise<Fingerprint> {\n try {\n const stat = await fs.stat(filePath);\n return { exists: stat.isFile(), size: stat.size, modified: stat.mtimeMs };\n } catch (error) {\n if (\n error instanceof Error &&\n 'code' in error &&\n typeof error.code === 'string' &&\n MISSING_PATH_ERROR_CODES.has(error.code)\n ) {\n return { exists: false, size: 0, modified: 0 };\n }\n throw error;\n }\n }\n}\n"],"mappings":"gbAQA,MAAM,EAAY,OACZ,EAAa,QACb,EAAY,OACZ,EAA2B,IAAI,IAAI,CAAC,SAAU,cAAc,CAAC,EAanE,SAAS,EAAY,EAAgB,EAAiC,CACpE,GAAI,CAAC,GAAS,OAAO,GAAU,SAAU,OACzC,IAAM,EAAS,EAAkC,GACjD,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAGO,IAAM,EAAN,KAA0C,CAGqB,SAFpE,QAA2B,IAAI,IAE/B,YAAY,EAAkF,CAA1B,KAAA,SAAA,CAA2B,CAE/F,MAAM,MAAM,EAAY,EAAc,EAAe,EAA4B,CAC/E,GAAI,IAAS,GAAa,IAAS,EAAY,CAC7C,IAAM,EAAW,EAAY,EAAM,MAAM,EACzC,GAAI,CAAC,EAAU,OACf,IAAM,EAAW,EAAK,QAAQ,EAAK,CAAQ,EAC3C,KAAK,QAAQ,IAAI,EAAI,CAAE,OAAM,MAAO,IAAI,IAAI,CAAC,CAAC,EAAU,MAAM,KAAK,YAAY,CAAQ,CAAC,CAAC,CAAC,CAAE,CAAC,EAC7F,MACF,CACA,GAAI,IAAS,EAAW,OACxB,IAAM,EAAU,EAAY,EAAM,SAAS,EAC3C,GAAI,CAAC,EAAS,OACd,IAAM,EAAQ,IAAI,IAClB,IAAK,IAAM,KAAa,KAAK,aAAa,EAAS,CAAG,EAAG,EAAM,IAAI,EAAW,MAAM,KAAK,YAAY,CAAS,CAAC,EAC/G,KAAK,QAAQ,IAAI,EAAI,CAAE,KAAM,EAAW,OAAM,CAAC,CACjD,CAEA,MAAM,IAAI,EAAY,EAAiC,CACrD,IAAM,EAAU,KAAK,QAAQ,IAAI,CAAE,EACnC,QAAK,QAAQ,OAAO,CAAE,EAClB,GAAC,GAAW,GAChB,IAAK,GAAM,CAAC,EAAU,KAAW,EAAQ,MAAO,CAC9C,IAAM,EAAQ,MAAM,KAAK,YAAY,CAAQ,GAC3B,EAAQ,OAAS,GAAa,EAAQ,OAAS,GAChD,KAAK,UAAU,CAAM,IAAM,KAAK,UAAU,CAAK,IAC9D,MAAM,KAAK,SAAS,OAAO,CAAE,QAAS,EAAG,KAAM,EAAU,KAAM,EAAQ,KAAM,GAAI,KAAK,IAAI,CAAE,CAAC,CAEjG,CACF,CAEA,aAAqB,EAAiB,EAAuB,CAE3D,IAAM,GADS,EAAQ,MAAM,+BAA+B,GAAK,CAAC,EAAA,CAE/D,IAAK,GAAU,EAAM,QAAQ,gBAAiB,EAAE,CAAC,CAAC,CAClD,OAAQ,GAAU,CAAC,EAAM,WAAW,GAAG,IAAM,EAAM,SAAS,GAAG,GAAK,mBAAmB,KAAK,CAAK,EAAE,CAAC,CACpG,IAAK,GAAU,EAAK,QAAQ,EAAK,CAAK,CAAC,EAC1C,MAAO,CAAC,GAAG,IAAI,IAAI,CAAU,CAAC,CAChC,CAEA,MAAc,YAAY,EAAwC,CAChE,GAAI,CACF,IAAM,EAAO,MAAM,EAAG,KAAK,CAAQ,EACnC,MAAO,CAAE,OAAQ,EAAK,OAAO,EAAG,KAAM,EAAK,KAAM,SAAU,EAAK,OAAQ,CAC1E,OAAS,EAAO,CACd,GACE,aAAiB,OACjB,SAAU,GACV,OAAO,EAAM,MAAS,UACtB,EAAyB,IAAI,EAAM,IAAI,EAEvC,MAAO,CAAE,OAAQ,GAAO,KAAM,EAAG,SAAU,CAAE,EAE/C,MAAM,CACR,CACF,CACF,OA5DC,EAAW,EAIG,EAAA,EAAA,EAAO,EAAgB,aAAa,CAAA"}
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let n=require("inversify"),r=require("node:fs/promises");r=e.__toESM(r,1);let i=require("node:path");i=e.__toESM(i,1);let a=require("@agimon-ai/doompi-config"),o=require("node:os");o=e.__toESM(o,1);const s=/^\s*command:\s*(.+?)\s*$/mu;function c(){return process.env.PI_CODING_AGENT_DIR||i.default.join(o.default.homedir(),`.pi`,`agent`)}let l=class{path(){return(0,a.globalDoomConfigPath)()}packagePath(){return i.default.join(c(),`doom-file-edit`,`config.yaml`)}async command(){return await this.read(this.path())??await this.read(this.packagePath())}async read(e){try{let t=await r.default.readFile(e,`utf8`),n=/^editor:\s*\n((?:[ \t]+.*(?:\n|$))*)/mu.exec(t)?.[1];if(!n)return;let i=s.exec(n)?.[1]?.trim();if(!i)return;if(/^(?:[-+]?\d+(?:\.\d+)?|true|false|null)$/u.test(i))throw Error(`${e}: editor.command must be a string`);return i.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/u,`$1$2`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}}};l=t.default([(0,n.injectable)()],l),Object.defineProperty(exports,"EditorConfigService",{enumerable:!0,get:function(){return l}});
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let n=require("inversify"),r=require("node:fs/promises");r=e.__toESM(r,1);let i=require("node:os");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);let o=require("@agimon-ai/doompi-config");const s=/^\s*command:\s*(.+?)\s*$/mu;function c(){return process.env.PI_CODING_AGENT_DIR||a.default.join(i.default.homedir(),`.pi`,`agent`)}let l=class{path(){return(0,o.globalDoomConfigPath)()}packagePath(){return a.default.join(c(),`doom-file-edit`,`config.yaml`)}async command(){return await this.read(this.path())??await this.read(this.packagePath())}async read(e){try{let t=await r.default.readFile(e,`utf8`),n=/^editor:\s*\n((?:[ \t]+.*(?:\n|$))*)/mu.exec(t)?.[1];if(!n)return;let i=s.exec(n)?.[1]?.trim();if(!i)return;if(/^(?:[-+]?\d+(?:\.\d+)?|true|false|null)$/u.test(i))throw Error(`${e}: editor.command must be a string`);return i.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/u,`$1$2`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}}};l=t.default([(0,n.injectable)()],l),Object.defineProperty(exports,"EditorConfigService",{enumerable:!0,get:function(){return l}});
2
2
  //# sourceMappingURL=EditorConfigService.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorConfigService.cjs","names":["path","os","globalDoomConfigPath","fs","injectable"],"sources":["../../../src/services/EditorConfigService/EditorConfigService.ts"],"sourcesContent":["import { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { injectable } from 'inversify';\nimport type { IEditorConfigService } from './types.ts';\n\nconst commandPattern = /^\\s*command:\\s*(.+?)\\s*$/mu;\n\nfunction agentDirectory(): string {\n return process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n}\n\n@injectable()\nexport class EditorConfigService implements IEditorConfigService {\n path(): string {\n return globalDoomConfigPath();\n }\n\n packagePath(): string {\n return path.join(agentDirectory(), 'doom-file-edit', 'config.yaml');\n }\n\n async command(): Promise<string | undefined> {\n // Shared Doom config owns `editor:`; the package-scoped file is the\n // fallback for standalone installs that have no Doom config.\n return (await this.read(this.path())) ?? (await this.read(this.packagePath()));\n }\n\n private async read(filePath: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(filePath, 'utf8');\n const editorSection = /^editor:\\s*\\n((?:[ \\t]+.*(?:\\n|$))*)/mu.exec(content)?.[1];\n if (!editorSection) return undefined;\n const value = commandPattern.exec(editorSection)?.[1]?.trim();\n if (!value) return undefined;\n if (/^(?:[-+]?\\d+(?:\\.\\d+)?|true|false|null)$/u.test(value)) {\n throw new Error(`${filePath}: editor.command must be a string`);\n }\n return value.replace(/^(?:\"([\\s\\S]*)\"|'([\\s\\S]*)')$/u, '$1$2');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"iVAOA,MAAM,EAAiB,6BAEvB,SAAS,GAAyB,CAChC,OAAO,QAAQ,IAAI,qBAAuBA,EAAAA,QAAK,KAAKC,EAAAA,QAAG,QAAQ,EAAG,MAAO,OAAO,CAClF,CAGO,IAAM,EAAN,KAA0D,CAC/D,MAAe,CACb,OAAA,EAAOC,EAAAA,qBAAAA,CAAqB,CAC9B,CAEA,aAAsB,CACpB,OAAOF,EAAAA,QAAK,KAAK,EAAe,EAAG,iBAAkB,aAAa,CACpE,CAEA,MAAM,SAAuC,CAG3C,OAAQ,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,GAAO,MAAM,KAAK,KAAK,KAAK,YAAY,CAAC,CAC9E,CAEA,MAAc,KAAK,EAA+C,CAChE,GAAI,CACF,IAAM,EAAU,MAAMG,EAAAA,QAAG,SAAS,EAAU,MAAM,EAC5C,EAAgB,yCAAyC,KAAK,CAAO,CAAC,GAAG,GAC/E,GAAI,CAAC,EAAe,OACpB,IAAM,EAAQ,EAAe,KAAK,CAAa,CAAC,GAAG,EAAE,EAAE,KAAK,EAC5D,GAAI,CAAC,EAAO,OACZ,GAAI,4CAA4C,KAAK,CAAK,EACxD,MAAU,MAAM,GAAG,EAAS,kCAAkC,EAEhE,OAAO,EAAM,QAAQ,iCAAkC,MAAM,CAC/D,OAAS,EAAO,CACd,GAAI,aAAiB,OAAS,SAAU,GAAS,EAAM,OAAS,SAAU,OAC1E,MAAM,CACR,CACF,CACF,EAhCCC,EAAAA,EAAAA,QAAAA,EAAAA,EAAAA,EAAAA,WAAAA,CAAW,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"EditorConfigService.cjs","names":["path","os","globalDoomConfigPath","fs","injectable"],"sources":["../../../src/services/EditorConfigService/EditorConfigService.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport { injectable } from 'inversify';\nimport type { IEditorConfigService } from './types.ts';\n\nconst commandPattern = /^\\s*command:\\s*(.+?)\\s*$/mu;\n\nfunction agentDirectory(): string {\n return process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n}\n\n@injectable()\nexport class EditorConfigService implements IEditorConfigService {\n path(): string {\n return globalDoomConfigPath();\n }\n\n packagePath(): string {\n return path.join(agentDirectory(), 'doom-file-edit', 'config.yaml');\n }\n\n async command(): Promise<string | undefined> {\n // Shared Doom config owns `editor:`; the package-scoped file is the\n // fallback for standalone installs that have no Doom config.\n return (await this.read(this.path())) ?? (await this.read(this.packagePath()));\n }\n\n private async read(filePath: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(filePath, 'utf8');\n const editorSection = /^editor:\\s*\\n((?:[ \\t]+.*(?:\\n|$))*)/mu.exec(content)?.[1];\n if (!editorSection) return undefined;\n const value = commandPattern.exec(editorSection)?.[1]?.trim();\n if (!value) return undefined;\n if (/^(?:[-+]?\\d+(?:\\.\\d+)?|true|false|null)$/u.test(value)) {\n throw new Error(`${filePath}: editor.command must be a string`);\n }\n return value.replace(/^(?:\"([\\s\\S]*)\"|'([\\s\\S]*)')$/u, '$1$2');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"qVAOA,MAAM,EAAiB,6BAEvB,SAAS,GAAyB,CAChC,OAAO,QAAQ,IAAI,qBAAuBA,EAAAA,QAAK,KAAKC,EAAAA,QAAG,QAAQ,EAAG,MAAO,OAAO,CAClF,CAGO,IAAM,EAAN,KAA0D,CAC/D,MAAe,CACb,OAAA,EAAOC,EAAAA,qBAAAA,CAAqB,CAC9B,CAEA,aAAsB,CACpB,OAAOF,EAAAA,QAAK,KAAK,EAAe,EAAG,iBAAkB,aAAa,CACpE,CAEA,MAAM,SAAuC,CAG3C,OAAQ,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,GAAO,MAAM,KAAK,KAAK,KAAK,YAAY,CAAC,CAC9E,CAEA,MAAc,KAAK,EAA+C,CAChE,GAAI,CACF,IAAM,EAAU,MAAMG,EAAAA,QAAG,SAAS,EAAU,MAAM,EAC5C,EAAgB,yCAAyC,KAAK,CAAO,CAAC,GAAG,GAC/E,GAAI,CAAC,EAAe,OACpB,IAAM,EAAQ,EAAe,KAAK,CAAa,CAAC,GAAG,EAAE,EAAE,KAAK,EAC5D,GAAI,CAAC,EAAO,OACZ,GAAI,4CAA4C,KAAK,CAAK,EACxD,MAAU,MAAM,GAAG,EAAS,kCAAkC,EAEhE,OAAO,EAAM,QAAQ,iCAAkC,MAAM,CAC/D,OAAS,EAAO,CACd,GAAI,aAAiB,OAAS,SAAU,GAAS,EAAM,OAAS,SAAU,OAC1E,MAAM,CACR,CACF,CACF,EAhCCC,EAAAA,EAAAA,QAAAA,EAAAA,EAAAA,EAAAA,WAAAA,CAAW,CAAA,EAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{injectable as t}from"inversify";import n from"node:fs/promises";import r from"node:path";import{globalDoomConfigPath as i}from"@agimon-ai/doompi-config";import a from"node:os";const o=/^\s*command:\s*(.+?)\s*$/mu;function s(){return process.env.PI_CODING_AGENT_DIR||r.join(a.homedir(),`.pi`,`agent`)}let c=class{path(){return i()}packagePath(){return r.join(s(),`doom-file-edit`,`config.yaml`)}async command(){return await this.read(this.path())??await this.read(this.packagePath())}async read(e){try{let t=await n.readFile(e,`utf8`),r=/^editor:\s*\n((?:[ \t]+.*(?:\n|$))*)/mu.exec(t)?.[1];if(!r)return;let i=o.exec(r)?.[1]?.trim();if(!i)return;if(/^(?:[-+]?\d+(?:\.\d+)?|true|false|null)$/u.test(i))throw Error(`${e}: editor.command must be a string`);return i.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/u,`$1$2`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}}};c=e([t()],c);export{c as EditorConfigService};
1
+ import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{injectable as t}from"inversify";import n from"node:fs/promises";import r from"node:os";import i from"node:path";import{globalDoomConfigPath as a}from"@agimon-ai/doompi-config";const o=/^\s*command:\s*(.+?)\s*$/mu;function s(){return process.env.PI_CODING_AGENT_DIR||i.join(r.homedir(),`.pi`,`agent`)}let c=class{path(){return a()}packagePath(){return i.join(s(),`doom-file-edit`,`config.yaml`)}async command(){return await this.read(this.path())??await this.read(this.packagePath())}async read(e){try{let t=await n.readFile(e,`utf8`),r=/^editor:\s*\n((?:[ \t]+.*(?:\n|$))*)/mu.exec(t)?.[1];if(!r)return;let i=o.exec(r)?.[1]?.trim();if(!i)return;if(/^(?:[-+]?\d+(?:\.\d+)?|true|false|null)$/u.test(i))throw Error(`${e}: editor.command must be a string`);return i.replace(/^(?:"([\s\S]*)"|'([\s\S]*)')$/u,`$1$2`)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return;throw e}}};c=e([t()],c);export{c as EditorConfigService};
2
2
  //# sourceMappingURL=EditorConfigService.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorConfigService.mjs","names":[],"sources":["../../../src/services/EditorConfigService/EditorConfigService.ts"],"sourcesContent":["import { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { injectable } from 'inversify';\nimport type { IEditorConfigService } from './types.ts';\n\nconst commandPattern = /^\\s*command:\\s*(.+?)\\s*$/mu;\n\nfunction agentDirectory(): string {\n return process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n}\n\n@injectable()\nexport class EditorConfigService implements IEditorConfigService {\n path(): string {\n return globalDoomConfigPath();\n }\n\n packagePath(): string {\n return path.join(agentDirectory(), 'doom-file-edit', 'config.yaml');\n }\n\n async command(): Promise<string | undefined> {\n // Shared Doom config owns `editor:`; the package-scoped file is the\n // fallback for standalone installs that have no Doom config.\n return (await this.read(this.path())) ?? (await this.read(this.packagePath()));\n }\n\n private async read(filePath: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(filePath, 'utf8');\n const editorSection = /^editor:\\s*\\n((?:[ \\t]+.*(?:\\n|$))*)/mu.exec(content)?.[1];\n if (!editorSection) return undefined;\n const value = commandPattern.exec(editorSection)?.[1]?.trim();\n if (!value) return undefined;\n if (/^(?:[-+]?\\d+(?:\\.\\d+)?|true|false|null)$/u.test(value)) {\n throw new Error(`${filePath}: editor.command must be a string`);\n }\n return value.replace(/^(?:\"([\\s\\S]*)\"|'([\\s\\S]*)')$/u, '$1$2');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"4QAOA,MAAM,EAAiB,6BAEvB,SAAS,GAAyB,CAChC,OAAO,QAAQ,IAAI,qBAAuB,EAAK,KAAK,EAAG,QAAQ,EAAG,MAAO,OAAO,CAClF,CAGO,IAAM,EAAN,KAA0D,CAC/D,MAAe,CACb,OAAO,EAAqB,CAC9B,CAEA,aAAsB,CACpB,OAAO,EAAK,KAAK,EAAe,EAAG,iBAAkB,aAAa,CACpE,CAEA,MAAM,SAAuC,CAG3C,OAAQ,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,GAAO,MAAM,KAAK,KAAK,KAAK,YAAY,CAAC,CAC9E,CAEA,MAAc,KAAK,EAA+C,CAChE,GAAI,CACF,IAAM,EAAU,MAAM,EAAG,SAAS,EAAU,MAAM,EAC5C,EAAgB,yCAAyC,KAAK,CAAO,CAAC,GAAG,GAC/E,GAAI,CAAC,EAAe,OACpB,IAAM,EAAQ,EAAe,KAAK,CAAa,CAAC,GAAG,EAAE,EAAE,KAAK,EAC5D,GAAI,CAAC,EAAO,OACZ,GAAI,4CAA4C,KAAK,CAAK,EACxD,MAAU,MAAM,GAAG,EAAS,kCAAkC,EAEhE,OAAO,EAAM,QAAQ,iCAAkC,MAAM,CAC/D,OAAS,EAAO,CACd,GAAI,aAAiB,OAAS,SAAU,GAAS,EAAM,OAAS,SAAU,OAC1E,MAAM,CACR,CACF,CACF,EAhCC,EAAA,EAAA,CAAA,EAAW,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"EditorConfigService.mjs","names":[],"sources":["../../../src/services/EditorConfigService/EditorConfigService.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { globalDoomConfigPath } from '@agimon-ai/doompi-config';\nimport { injectable } from 'inversify';\nimport type { IEditorConfigService } from './types.ts';\n\nconst commandPattern = /^\\s*command:\\s*(.+?)\\s*$/mu;\n\nfunction agentDirectory(): string {\n return process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n}\n\n@injectable()\nexport class EditorConfigService implements IEditorConfigService {\n path(): string {\n return globalDoomConfigPath();\n }\n\n packagePath(): string {\n return path.join(agentDirectory(), 'doom-file-edit', 'config.yaml');\n }\n\n async command(): Promise<string | undefined> {\n // Shared Doom config owns `editor:`; the package-scoped file is the\n // fallback for standalone installs that have no Doom config.\n return (await this.read(this.path())) ?? (await this.read(this.packagePath()));\n }\n\n private async read(filePath: string): Promise<string | undefined> {\n try {\n const content = await fs.readFile(filePath, 'utf8');\n const editorSection = /^editor:\\s*\\n((?:[ \\t]+.*(?:\\n|$))*)/mu.exec(content)?.[1];\n if (!editorSection) return undefined;\n const value = commandPattern.exec(editorSection)?.[1]?.trim();\n if (!value) return undefined;\n if (/^(?:[-+]?\\d+(?:\\.\\d+)?|true|false|null)$/u.test(value)) {\n throw new Error(`${filePath}: editor.command must be a string`);\n }\n return value.replace(/^(?:\"([\\s\\S]*)\"|'([\\s\\S]*)')$/u, '$1$2');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"4QAOA,MAAM,EAAiB,6BAEvB,SAAS,GAAyB,CAChC,OAAO,QAAQ,IAAI,qBAAuB,EAAK,KAAK,EAAG,QAAQ,EAAG,MAAO,OAAO,CAClF,CAGO,IAAM,EAAN,KAA0D,CAC/D,MAAe,CACb,OAAO,EAAqB,CAC9B,CAEA,aAAsB,CACpB,OAAO,EAAK,KAAK,EAAe,EAAG,iBAAkB,aAAa,CACpE,CAEA,MAAM,SAAuC,CAG3C,OAAQ,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,GAAO,MAAM,KAAK,KAAK,KAAK,YAAY,CAAC,CAC9E,CAEA,MAAc,KAAK,EAA+C,CAChE,GAAI,CACF,IAAM,EAAU,MAAM,EAAG,SAAS,EAAU,MAAM,EAC5C,EAAgB,yCAAyC,KAAK,CAAO,CAAC,GAAG,GAC/E,GAAI,CAAC,EAAe,OACpB,IAAM,EAAQ,EAAe,KAAK,CAAa,CAAC,GAAG,EAAE,EAAE,KAAK,EAC5D,GAAI,CAAC,EAAO,OACZ,GAAI,4CAA4C,KAAK,CAAK,EACxD,MAAU,MAAM,GAAG,EAAS,kCAAkC,EAEhE,OAAO,EAAM,QAAQ,iCAAkC,MAAM,CAC/D,OAAS,EAAO,CACd,GAAI,aAAiB,OAAS,SAAU,GAAS,EAAM,OAAS,SAAU,OAC1E,MAAM,CACR,CACF,CACF,EAhCC,EAAA,EAAA,CAAA,EAAW,CAAA,EAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../types.cjs"),n=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),r=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs"),a=require("../../commandLine.cjs");let o=require("inversify"),s=require("node:fs/promises");s=e.__toESM(s,1);let c=require("node:path");c=e.__toESM(c,1);let l=require("cross-spawn");l=e.__toESM(l,1);let u=class{config;constructor(e){this.config=e}async resolve(e=process.env,t=process.platform){let n=await this.config.command(),r=[...n?[{template:n,source:`configured`}]:[],...e.VISUAL?[{template:e.VISUAL,source:`VISUAL`}]:[],...e.EDITOR?[{template:e.EDITOR,source:`EDITOR`}]:[],{template:t===`win32`?`notepad {file}`:`nano {file}`,source:`fallback`}];for(let n of r){let r=a.splitCommandLine(n.template)[0];if(r&&await this.isExecutable(r,e,t))return n}}async launch(e,t,n){try{let r=await this.resolve();if(!r)return{success:!1,error:`No editor command could be resolved`};let[i,...o]=a.expandEditorTemplate(r.template,e,t);if(!i)return{success:!1,error:`Editor command must not be empty`};n.stop();try{await new Promise((e,t)=>{let n=(0,l.default)(i,o,{stdio:`inherit`,shell:!1});n.once(`error`,t),n.once(`exit`,()=>e())})}finally{n.start(),n.requestRender(!0)}return{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async isExecutable(e,t,n){let r=n===`win32`?(t.PATHEXT??`.EXE;.CMD;.BAT`).split(`;`):[``],i=c.default.isAbsolute(e)||e.includes(c.default.sep)?[``]:(t.PATH??``).split(c.default.delimiter);for(let t of i)for(let i of r){let r=t?c.default.join(t,`${e}${i}`):`${e}${i}`;try{return await s.default.access(r,n===`win32`?s.default.constants.F_OK:s.default.constants.X_OK),!0}catch(e){if(!(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`EACCES`)))throw e}}return!1}};u=i.default([(0,o.injectable)(),r.default(0,(0,o.inject)(t.FILE_EDIT_TYPES.EditorConfigService)),n.default(`design:paramtypes`,[Object])],u),Object.defineProperty(exports,"EditorLauncher",{enumerable:!0,get:function(){return u}});
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs"),n=require("../../adapters/process/commandLine.cjs"),r=require("../../types/index.cjs"),i=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.cjs"),a=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.cjs");let o=require("inversify"),s=require("node:fs/promises");s=e.__toESM(s,1);let c=require("node:path");c=e.__toESM(c,1);let l=require("cross-spawn");l=e.__toESM(l,1);let u=class{config;constructor(e){this.config=e}async resolve(e=process.env,t=process.platform){let r=await this.config.command(),i=[...r?[{template:r,source:`configured`}]:[],...e.VISUAL?[{template:e.VISUAL,source:`VISUAL`}]:[],...e.EDITOR?[{template:e.EDITOR,source:`EDITOR`}]:[],{template:t===`win32`?`notepad {file}`:`nano {file}`,source:`fallback`}];for(let r of i){let i=n.splitCommandLine(r.template)[0];if(i&&await this.isExecutable(i,e,t))return r}}async launch(e,t,r){try{let i=await this.resolve();if(!i)return{success:!1,error:`No editor command could be resolved`};let[a,...o]=n.expandEditorTemplate(i.template,e,t);if(!a)return{success:!1,error:`Editor command must not be empty`};r.stop();try{await new Promise((e,t)=>{let n=(0,l.default)(a,o,{stdio:`inherit`,shell:!1});n.once(`error`,t),n.once(`exit`,()=>e())})}finally{r.start(),r.requestRender(!0)}return{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async isExecutable(e,t,n){let r=n===`win32`?(t.PATHEXT??`.EXE;.CMD;.BAT`).split(`;`):[``],i=c.default.isAbsolute(e)||e.includes(c.default.sep)?[``]:(t.PATH??``).split(c.default.delimiter);for(let t of i)for(let i of r){let r=t?c.default.join(t,`${e}${i}`):`${e}${i}`;try{return await s.default.access(r,n===`win32`?s.default.constants.F_OK:s.default.constants.X_OK),!0}catch(e){if(!(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`EACCES`)))throw e}}return!1}};u=t.default([(0,o.injectable)(),a.default(0,(0,o.inject)(r.FILE_EDIT_TYPES.EditorConfigService)),i.default(`design:paramtypes`,[Object])],u),Object.defineProperty(exports,"EditorLauncher",{enumerable:!0,get:function(){return u}});
2
2
  //# sourceMappingURL=EditorLauncher.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorLauncher.cjs","names":["splitCommandLine","expandEditorTemplate","spawn","path","fs","injectable","inject","FILE_EDIT_TYPES"],"sources":["../../../src/services/EditorLauncher/EditorLauncher.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { inject, injectable } from 'inversify';\nimport { expandEditorTemplate, splitCommandLine } from '../../commandLine.ts';\nimport type { ResolvedEditor } from '../../domain.ts';\nimport { FILE_EDIT_TYPES } from '../../types.ts';\nimport type { IEditorConfigService } from '../EditorConfigService/types.ts';\nimport type { EditorLaunchResult, EditorTui, IEditorLauncher } from './types.ts';\n\n@injectable()\nexport class EditorLauncher implements IEditorLauncher {\n constructor(@inject(FILE_EDIT_TYPES.EditorConfigService) private readonly config: IEditorConfigService) {}\n\n async resolve(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n ): Promise<ResolvedEditor | undefined> {\n const configured = await this.config.command();\n const candidates: ResolvedEditor[] = [\n ...(configured ? [{ template: configured, source: 'configured' as const }] : []),\n ...(env.VISUAL ? [{ template: env.VISUAL, source: 'VISUAL' as const }] : []),\n ...(env.EDITOR ? [{ template: env.EDITOR, source: 'EDITOR' as const }] : []),\n { template: platform === 'win32' ? 'notepad {file}' : 'nano {file}', source: 'fallback' },\n ];\n for (const candidate of candidates) {\n const executable = splitCommandLine(candidate.template)[0];\n if (executable && (await this.isExecutable(executable, env, platform))) return candidate;\n }\n return undefined;\n }\n\n async launch(filePath: string, line: number, tui: EditorTui): Promise<EditorLaunchResult> {\n try {\n const editor = await this.resolve();\n if (!editor) return { success: false, error: 'No editor command could be resolved' };\n const [command, ...args] = expandEditorTemplate(editor.template, filePath, line);\n if (!command) return { success: false, error: 'Editor command must not be empty' };\n tui.stop();\n try {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: 'inherit', shell: false });\n child.once('error', reject);\n child.once('exit', () => resolve());\n });\n } finally {\n tui.start();\n tui.requestRender(true);\n }\n return { success: true };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n private async isExecutable(command: string, env: NodeJS.ProcessEnv, platform: NodeJS.Platform): Promise<boolean> {\n const extensions = platform === 'win32' ? (env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';') : [''];\n const locations =\n path.isAbsolute(command) || command.includes(path.sep) ? [''] : (env.PATH ?? '').split(path.delimiter);\n for (const location of locations) {\n for (const extension of extensions) {\n const candidate = location ? path.join(location, `${command}${extension}`) : `${command}${extension}`;\n try {\n await fs.access(candidate, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);\n return true;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && (error.code === 'ENOENT' || error.code === 'EACCES')))\n throw error;\n }\n }\n }\n return false;\n }\n}\n"],"mappings":"kiBAWO,IAAM,EAAN,KAAgD,CACqB,OAA1E,YAAY,EAA4F,CAA9B,KAAA,OAAA,CAA+B,CAEzG,MAAM,QACJ,EAAyB,QAAQ,IACjC,EAA4B,QAAQ,SACC,CACrC,IAAM,EAAa,MAAM,KAAK,OAAO,QAAQ,EACvC,EAA+B,CACnC,GAAI,EAAa,CAAC,CAAE,SAAU,EAAY,OAAQ,YAAsB,CAAC,EAAI,CAAC,EAC9E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,CAAE,SAAU,IAAa,QAAU,iBAAmB,cAAe,OAAQ,UAAW,CAC1F,EACA,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAaA,EAAAA,iBAAiB,EAAU,QAAQ,CAAC,CAAC,GACxD,GAAI,GAAe,MAAM,KAAK,aAAa,EAAY,EAAK,CAAQ,EAAI,OAAO,CACjF,CAEF,CAEA,MAAM,OAAO,EAAkB,EAAc,EAA6C,CACxF,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,QAAQ,EAClC,GAAI,CAAC,EAAQ,MAAO,CAAE,QAAS,GAAO,MAAO,qCAAsC,EACnF,GAAM,CAAC,EAAS,GAAG,GAAQC,EAAAA,qBAAqB,EAAO,SAAU,EAAU,CAAI,EAC/E,GAAI,CAAC,EAAS,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAmC,EACjF,EAAI,KAAK,EACT,GAAI,CACF,MAAM,IAAI,SAAe,EAAS,IAAW,CAC3C,IAAM,GAAA,EAAQC,EAAAA,QAAAA,CAAM,EAAS,EAAM,CAAE,MAAO,UAAW,MAAO,EAAM,CAAC,EACrE,EAAM,KAAK,QAAS,CAAM,EAC1B,EAAM,KAAK,WAAc,EAAQ,CAAC,CACpC,CAAC,CACH,QAAU,CACR,EAAI,MAAM,EACV,EAAI,cAAc,EAAI,CACxB,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,OAAS,EAAO,CACd,MAAO,CAAE,QAAS,GAAO,MAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CACzF,CACF,CAEA,MAAc,aAAa,EAAiB,EAAwB,EAA6C,CAC/G,IAAM,EAAa,IAAa,SAAW,EAAI,SAAW,iBAAA,CAAkB,MAAM,GAAG,EAAI,CAAC,EAAE,EACtF,EACJC,EAAAA,QAAK,WAAW,CAAO,GAAK,EAAQ,SAASA,EAAAA,QAAK,GAAG,EAAI,CAAC,EAAE,GAAK,EAAI,MAAQ,GAAA,CAAI,MAAMA,EAAAA,QAAK,SAAS,EACvG,IAAK,IAAM,KAAY,EACrB,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAY,EAAWA,EAAAA,QAAK,KAAK,EAAU,GAAG,IAAU,GAAW,EAAI,GAAG,IAAU,IAC1F,GAAI,CAEF,OADA,MAAMC,EAAAA,QAAG,OAAO,EAAW,IAAa,QAAUA,EAAAA,QAAG,UAAU,KAAOA,EAAAA,QAAG,UAAU,IAAI,EAChF,EACT,OAAS,EAAO,CACd,GAAI,EAAE,aAAiB,OAAS,SAAU,IAAU,EAAM,OAAS,UAAY,EAAM,OAAS,WAC5F,MAAM,CACV,CACF,CAEF,MAAO,EACT,CACF,gBA/DCC,EAAAA,EAAAA,WAAAA,CAAW,EAEGC,EAAAA,QAAAA,GAAAA,EAAAA,EAAAA,OAAAA,CAAOC,EAAAA,gBAAgB,mBAAmB,CAAA"}
1
+ {"version":3,"file":"EditorLauncher.cjs","names":["splitCommandLine","expandEditorTemplate","spawn","path","fs","injectable","inject","FILE_EDIT_TYPES"],"sources":["../../../src/services/EditorLauncher/EditorLauncher.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { inject, injectable } from 'inversify';\nimport { expandEditorTemplate, splitCommandLine } from '../../adapters/process/commandLine.ts';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\nimport type { IEditorConfigService } from '../EditorConfigService/types.ts';\nimport type { ResolvedEditor } from '../fileEdit/domain.ts';\nimport type { EditorLaunchResult, EditorTui, IEditorLauncher } from './types.ts';\n\n@injectable()\nexport class EditorLauncher implements IEditorLauncher {\n constructor(@inject(FILE_EDIT_TYPES.EditorConfigService) private readonly config: IEditorConfigService) {}\n\n async resolve(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n ): Promise<ResolvedEditor | undefined> {\n const configured = await this.config.command();\n const candidates: ResolvedEditor[] = [\n ...(configured ? [{ template: configured, source: 'configured' as const }] : []),\n ...(env.VISUAL ? [{ template: env.VISUAL, source: 'VISUAL' as const }] : []),\n ...(env.EDITOR ? [{ template: env.EDITOR, source: 'EDITOR' as const }] : []),\n { template: platform === 'win32' ? 'notepad {file}' : 'nano {file}', source: 'fallback' },\n ];\n for (const candidate of candidates) {\n const executable = splitCommandLine(candidate.template)[0];\n if (executable && (await this.isExecutable(executable, env, platform))) return candidate;\n }\n return undefined;\n }\n\n async launch(filePath: string, line: number, tui: EditorTui): Promise<EditorLaunchResult> {\n try {\n const editor = await this.resolve();\n if (!editor) return { success: false, error: 'No editor command could be resolved' };\n const [command, ...args] = expandEditorTemplate(editor.template, filePath, line);\n if (!command) return { success: false, error: 'Editor command must not be empty' };\n tui.stop();\n try {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: 'inherit', shell: false });\n child.once('error', reject);\n child.once('exit', () => resolve());\n });\n } finally {\n tui.start();\n tui.requestRender(true);\n }\n return { success: true };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n private async isExecutable(command: string, env: NodeJS.ProcessEnv, platform: NodeJS.Platform): Promise<boolean> {\n const extensions = platform === 'win32' ? (env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';') : [''];\n const locations =\n path.isAbsolute(command) || command.includes(path.sep) ? [''] : (env.PATH ?? '').split(path.delimiter);\n for (const location of locations) {\n for (const extension of extensions) {\n const candidate = location ? path.join(location, `${command}${extension}`) : `${command}${extension}`;\n try {\n await fs.access(candidate, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);\n return true;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && (error.code === 'ENOENT' || error.code === 'EACCES')))\n throw error;\n }\n }\n }\n return false;\n }\n}\n"],"mappings":"yjBAWO,IAAM,EAAN,KAAgD,CACqB,OAA1E,YAAY,EAA4F,CAA9B,KAAA,OAAA,CAA+B,CAEzG,MAAM,QACJ,EAAyB,QAAQ,IACjC,EAA4B,QAAQ,SACC,CACrC,IAAM,EAAa,MAAM,KAAK,OAAO,QAAQ,EACvC,EAA+B,CACnC,GAAI,EAAa,CAAC,CAAE,SAAU,EAAY,OAAQ,YAAsB,CAAC,EAAI,CAAC,EAC9E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,CAAE,SAAU,IAAa,QAAU,iBAAmB,cAAe,OAAQ,UAAW,CAC1F,EACA,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAaA,EAAAA,iBAAiB,EAAU,QAAQ,CAAC,CAAC,GACxD,GAAI,GAAe,MAAM,KAAK,aAAa,EAAY,EAAK,CAAQ,EAAI,OAAO,CACjF,CAEF,CAEA,MAAM,OAAO,EAAkB,EAAc,EAA6C,CACxF,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,QAAQ,EAClC,GAAI,CAAC,EAAQ,MAAO,CAAE,QAAS,GAAO,MAAO,qCAAsC,EACnF,GAAM,CAAC,EAAS,GAAG,GAAQC,EAAAA,qBAAqB,EAAO,SAAU,EAAU,CAAI,EAC/E,GAAI,CAAC,EAAS,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAmC,EACjF,EAAI,KAAK,EACT,GAAI,CACF,MAAM,IAAI,SAAe,EAAS,IAAW,CAC3C,IAAM,GAAA,EAAQC,EAAAA,QAAAA,CAAM,EAAS,EAAM,CAAE,MAAO,UAAW,MAAO,EAAM,CAAC,EACrE,EAAM,KAAK,QAAS,CAAM,EAC1B,EAAM,KAAK,WAAc,EAAQ,CAAC,CACpC,CAAC,CACH,QAAU,CACR,EAAI,MAAM,EACV,EAAI,cAAc,EAAI,CACxB,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,OAAS,EAAO,CACd,MAAO,CAAE,QAAS,GAAO,MAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CACzF,CACF,CAEA,MAAc,aAAa,EAAiB,EAAwB,EAA6C,CAC/G,IAAM,EAAa,IAAa,SAAW,EAAI,SAAW,iBAAA,CAAkB,MAAM,GAAG,EAAI,CAAC,EAAE,EACtF,EACJC,EAAAA,QAAK,WAAW,CAAO,GAAK,EAAQ,SAASA,EAAAA,QAAK,GAAG,EAAI,CAAC,EAAE,GAAK,EAAI,MAAQ,GAAA,CAAI,MAAMA,EAAAA,QAAK,SAAS,EACvG,IAAK,IAAM,KAAY,EACrB,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAY,EAAWA,EAAAA,QAAK,KAAK,EAAU,GAAG,IAAU,GAAW,EAAI,GAAG,IAAU,IAC1F,GAAI,CAEF,OADA,MAAMC,EAAAA,QAAG,OAAO,EAAW,IAAa,QAAUA,EAAAA,QAAG,UAAU,KAAOA,EAAAA,QAAG,UAAU,IAAI,EAChF,EACT,OAAS,EAAO,CACd,GAAI,EAAE,aAAiB,OAAS,SAAU,IAAU,EAAM,OAAS,UAAY,EAAM,OAAS,WAC5F,MAAM,CACV,CACF,CAEF,MAAO,EACT,CACF,gBA/DCC,EAAAA,EAAAA,WAAAA,CAAW,EAEGC,EAAAA,QAAAA,GAAAA,EAAAA,EAAAA,OAAAA,CAAOC,EAAAA,gBAAgB,mBAAmB,CAAA"}
@@ -1,2 +1,2 @@
1
- import{FILE_EDIT_TYPES as e}from"../../types.mjs";import t from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import n from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import r from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{expandEditorTemplate as i,splitCommandLine as a}from"../../commandLine.mjs";import{inject as o,injectable as s}from"inversify";import c from"node:fs/promises";import l from"node:path";import u from"cross-spawn";let d=class{config;constructor(e){this.config=e}async resolve(e=process.env,t=process.platform){let n=await this.config.command(),r=[...n?[{template:n,source:`configured`}]:[],...e.VISUAL?[{template:e.VISUAL,source:`VISUAL`}]:[],...e.EDITOR?[{template:e.EDITOR,source:`EDITOR`}]:[],{template:t===`win32`?`notepad {file}`:`nano {file}`,source:`fallback`}];for(let n of r){let r=a(n.template)[0];if(r&&await this.isExecutable(r,e,t))return n}}async launch(e,t,n){try{let r=await this.resolve();if(!r)return{success:!1,error:`No editor command could be resolved`};let[a,...o]=i(r.template,e,t);if(!a)return{success:!1,error:`Editor command must not be empty`};n.stop();try{await new Promise((e,t)=>{let n=u(a,o,{stdio:`inherit`,shell:!1});n.once(`error`,t),n.once(`exit`,()=>e())})}finally{n.start(),n.requestRender(!0)}return{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async isExecutable(e,t,n){let r=n===`win32`?(t.PATHEXT??`.EXE;.CMD;.BAT`).split(`;`):[``],i=l.isAbsolute(e)||e.includes(l.sep)?[``]:(t.PATH??``).split(l.delimiter);for(let t of i)for(let i of r){let r=t?l.join(t,`${e}${i}`):`${e}${i}`;try{return await c.access(r,n===`win32`?c.constants.F_OK:c.constants.X_OK),!0}catch(e){if(!(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`EACCES`)))throw e}}return!1}};d=r([s(),n(0,o(e.EditorConfigService)),t(`design:paramtypes`,[Object])],d);export{d as EditorLauncher};
1
+ import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{expandEditorTemplate as t,splitCommandLine as n}from"../../adapters/process/commandLine.mjs";import{FILE_EDIT_TYPES as r}from"../../types/index.mjs";import i from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateMetadata.mjs";import a from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorateParam.mjs";import{inject as o,injectable as s}from"inversify";import c from"node:fs/promises";import l from"node:path";import u from"cross-spawn";let d=class{config;constructor(e){this.config=e}async resolve(e=process.env,t=process.platform){let r=await this.config.command(),i=[...r?[{template:r,source:`configured`}]:[],...e.VISUAL?[{template:e.VISUAL,source:`VISUAL`}]:[],...e.EDITOR?[{template:e.EDITOR,source:`EDITOR`}]:[],{template:t===`win32`?`notepad {file}`:`nano {file}`,source:`fallback`}];for(let r of i){let i=n(r.template)[0];if(i&&await this.isExecutable(i,e,t))return r}}async launch(e,n,r){try{let i=await this.resolve();if(!i)return{success:!1,error:`No editor command could be resolved`};let[a,...o]=t(i.template,e,n);if(!a)return{success:!1,error:`Editor command must not be empty`};r.stop();try{await new Promise((e,t)=>{let n=u(a,o,{stdio:`inherit`,shell:!1});n.once(`error`,t),n.once(`exit`,()=>e())})}finally{r.start(),r.requestRender(!0)}return{success:!0}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async isExecutable(e,t,n){let r=n===`win32`?(t.PATHEXT??`.EXE;.CMD;.BAT`).split(`;`):[``],i=l.isAbsolute(e)||e.includes(l.sep)?[``]:(t.PATH??``).split(l.delimiter);for(let t of i)for(let i of r){let r=t?l.join(t,`${e}${i}`):`${e}${i}`;try{return await c.access(r,n===`win32`?c.constants.F_OK:c.constants.X_OK),!0}catch(e){if(!(e instanceof Error&&`code`in e&&(e.code===`ENOENT`||e.code===`EACCES`)))throw e}}return!1}};d=e([s(),a(0,o(r.EditorConfigService)),i(`design:paramtypes`,[Object])],d);export{d as EditorLauncher};
2
2
  //# sourceMappingURL=EditorLauncher.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorLauncher.mjs","names":[],"sources":["../../../src/services/EditorLauncher/EditorLauncher.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { inject, injectable } from 'inversify';\nimport { expandEditorTemplate, splitCommandLine } from '../../commandLine.ts';\nimport type { ResolvedEditor } from '../../domain.ts';\nimport { FILE_EDIT_TYPES } from '../../types.ts';\nimport type { IEditorConfigService } from '../EditorConfigService/types.ts';\nimport type { EditorLaunchResult, EditorTui, IEditorLauncher } from './types.ts';\n\n@injectable()\nexport class EditorLauncher implements IEditorLauncher {\n constructor(@inject(FILE_EDIT_TYPES.EditorConfigService) private readonly config: IEditorConfigService) {}\n\n async resolve(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n ): Promise<ResolvedEditor | undefined> {\n const configured = await this.config.command();\n const candidates: ResolvedEditor[] = [\n ...(configured ? [{ template: configured, source: 'configured' as const }] : []),\n ...(env.VISUAL ? [{ template: env.VISUAL, source: 'VISUAL' as const }] : []),\n ...(env.EDITOR ? [{ template: env.EDITOR, source: 'EDITOR' as const }] : []),\n { template: platform === 'win32' ? 'notepad {file}' : 'nano {file}', source: 'fallback' },\n ];\n for (const candidate of candidates) {\n const executable = splitCommandLine(candidate.template)[0];\n if (executable && (await this.isExecutable(executable, env, platform))) return candidate;\n }\n return undefined;\n }\n\n async launch(filePath: string, line: number, tui: EditorTui): Promise<EditorLaunchResult> {\n try {\n const editor = await this.resolve();\n if (!editor) return { success: false, error: 'No editor command could be resolved' };\n const [command, ...args] = expandEditorTemplate(editor.template, filePath, line);\n if (!command) return { success: false, error: 'Editor command must not be empty' };\n tui.stop();\n try {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: 'inherit', shell: false });\n child.once('error', reject);\n child.once('exit', () => resolve());\n });\n } finally {\n tui.start();\n tui.requestRender(true);\n }\n return { success: true };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n private async isExecutable(command: string, env: NodeJS.ProcessEnv, platform: NodeJS.Platform): Promise<boolean> {\n const extensions = platform === 'win32' ? (env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';') : [''];\n const locations =\n path.isAbsolute(command) || command.includes(path.sep) ? [''] : (env.PATH ?? '').split(path.delimiter);\n for (const location of locations) {\n for (const extension of extensions) {\n const candidate = location ? path.join(location, `${command}${extension}`) : `${command}${extension}`;\n try {\n await fs.access(candidate, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);\n return true;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && (error.code === 'ENOENT' || error.code === 'EACCES')))\n throw error;\n }\n }\n }\n return false;\n }\n}\n"],"mappings":"whBAWO,IAAM,EAAN,KAAgD,CACqB,OAA1E,YAAY,EAA4F,CAA9B,KAAA,OAAA,CAA+B,CAEzG,MAAM,QACJ,EAAyB,QAAQ,IACjC,EAA4B,QAAQ,SACC,CACrC,IAAM,EAAa,MAAM,KAAK,OAAO,QAAQ,EACvC,EAA+B,CACnC,GAAI,EAAa,CAAC,CAAE,SAAU,EAAY,OAAQ,YAAsB,CAAC,EAAI,CAAC,EAC9E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,CAAE,SAAU,IAAa,QAAU,iBAAmB,cAAe,OAAQ,UAAW,CAC1F,EACA,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAa,EAAiB,EAAU,QAAQ,CAAC,CAAC,GACxD,GAAI,GAAe,MAAM,KAAK,aAAa,EAAY,EAAK,CAAQ,EAAI,OAAO,CACjF,CAEF,CAEA,MAAM,OAAO,EAAkB,EAAc,EAA6C,CACxF,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,QAAQ,EAClC,GAAI,CAAC,EAAQ,MAAO,CAAE,QAAS,GAAO,MAAO,qCAAsC,EACnF,GAAM,CAAC,EAAS,GAAG,GAAQ,EAAqB,EAAO,SAAU,EAAU,CAAI,EAC/E,GAAI,CAAC,EAAS,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAmC,EACjF,EAAI,KAAK,EACT,GAAI,CACF,MAAM,IAAI,SAAe,EAAS,IAAW,CAC3C,IAAM,EAAQ,EAAM,EAAS,EAAM,CAAE,MAAO,UAAW,MAAO,EAAM,CAAC,EACrE,EAAM,KAAK,QAAS,CAAM,EAC1B,EAAM,KAAK,WAAc,EAAQ,CAAC,CACpC,CAAC,CACH,QAAU,CACR,EAAI,MAAM,EACV,EAAI,cAAc,EAAI,CACxB,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,OAAS,EAAO,CACd,MAAO,CAAE,QAAS,GAAO,MAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CACzF,CACF,CAEA,MAAc,aAAa,EAAiB,EAAwB,EAA6C,CAC/G,IAAM,EAAa,IAAa,SAAW,EAAI,SAAW,iBAAA,CAAkB,MAAM,GAAG,EAAI,CAAC,EAAE,EACtF,EACJ,EAAK,WAAW,CAAO,GAAK,EAAQ,SAAS,EAAK,GAAG,EAAI,CAAC,EAAE,GAAK,EAAI,MAAQ,GAAA,CAAI,MAAM,EAAK,SAAS,EACvG,IAAK,IAAM,KAAY,EACrB,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAY,EAAW,EAAK,KAAK,EAAU,GAAG,IAAU,GAAW,EAAI,GAAG,IAAU,IAC1F,GAAI,CAEF,OADA,MAAM,EAAG,OAAO,EAAW,IAAa,QAAU,EAAG,UAAU,KAAO,EAAG,UAAU,IAAI,EAChF,EACT,OAAS,EAAO,CACd,GAAI,EAAE,aAAiB,OAAS,SAAU,IAAU,EAAM,OAAS,UAAY,EAAM,OAAS,WAC5F,MAAM,CACV,CACF,CAEF,MAAO,EACT,CACF,OA/DC,EAAW,EAEG,EAAA,EAAA,EAAO,EAAgB,mBAAmB,CAAA"}
1
+ {"version":3,"file":"EditorLauncher.mjs","names":[],"sources":["../../../src/services/EditorLauncher/EditorLauncher.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport spawn from 'cross-spawn';\nimport { inject, injectable } from 'inversify';\nimport { expandEditorTemplate, splitCommandLine } from '../../adapters/process/commandLine.ts';\nimport { FILE_EDIT_TYPES } from '../../types/index.ts';\nimport type { IEditorConfigService } from '../EditorConfigService/types.ts';\nimport type { ResolvedEditor } from '../fileEdit/domain.ts';\nimport type { EditorLaunchResult, EditorTui, IEditorLauncher } from './types.ts';\n\n@injectable()\nexport class EditorLauncher implements IEditorLauncher {\n constructor(@inject(FILE_EDIT_TYPES.EditorConfigService) private readonly config: IEditorConfigService) {}\n\n async resolve(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n ): Promise<ResolvedEditor | undefined> {\n const configured = await this.config.command();\n const candidates: ResolvedEditor[] = [\n ...(configured ? [{ template: configured, source: 'configured' as const }] : []),\n ...(env.VISUAL ? [{ template: env.VISUAL, source: 'VISUAL' as const }] : []),\n ...(env.EDITOR ? [{ template: env.EDITOR, source: 'EDITOR' as const }] : []),\n { template: platform === 'win32' ? 'notepad {file}' : 'nano {file}', source: 'fallback' },\n ];\n for (const candidate of candidates) {\n const executable = splitCommandLine(candidate.template)[0];\n if (executable && (await this.isExecutable(executable, env, platform))) return candidate;\n }\n return undefined;\n }\n\n async launch(filePath: string, line: number, tui: EditorTui): Promise<EditorLaunchResult> {\n try {\n const editor = await this.resolve();\n if (!editor) return { success: false, error: 'No editor command could be resolved' };\n const [command, ...args] = expandEditorTemplate(editor.template, filePath, line);\n if (!command) return { success: false, error: 'Editor command must not be empty' };\n tui.stop();\n try {\n await new Promise<void>((resolve, reject) => {\n const child = spawn(command, args, { stdio: 'inherit', shell: false });\n child.once('error', reject);\n child.once('exit', () => resolve());\n });\n } finally {\n tui.start();\n tui.requestRender(true);\n }\n return { success: true };\n } catch (error) {\n return { success: false, error: error instanceof Error ? error.message : String(error) };\n }\n }\n\n private async isExecutable(command: string, env: NodeJS.ProcessEnv, platform: NodeJS.Platform): Promise<boolean> {\n const extensions = platform === 'win32' ? (env.PATHEXT ?? '.EXE;.CMD;.BAT').split(';') : [''];\n const locations =\n path.isAbsolute(command) || command.includes(path.sep) ? [''] : (env.PATH ?? '').split(path.delimiter);\n for (const location of locations) {\n for (const extension of extensions) {\n const candidate = location ? path.join(location, `${command}${extension}`) : `${command}${extension}`;\n try {\n await fs.access(candidate, platform === 'win32' ? fs.constants.F_OK : fs.constants.X_OK);\n return true;\n } catch (error) {\n if (!(error instanceof Error && 'code' in error && (error.code === 'ENOENT' || error.code === 'EACCES')))\n throw error;\n }\n }\n }\n return false;\n }\n}\n"],"mappings":"+iBAWO,IAAM,EAAN,KAAgD,CACqB,OAA1E,YAAY,EAA4F,CAA9B,KAAA,OAAA,CAA+B,CAEzG,MAAM,QACJ,EAAyB,QAAQ,IACjC,EAA4B,QAAQ,SACC,CACrC,IAAM,EAAa,MAAM,KAAK,OAAO,QAAQ,EACvC,EAA+B,CACnC,GAAI,EAAa,CAAC,CAAE,SAAU,EAAY,OAAQ,YAAsB,CAAC,EAAI,CAAC,EAC9E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,GAAI,EAAI,OAAS,CAAC,CAAE,SAAU,EAAI,OAAQ,OAAQ,QAAkB,CAAC,EAAI,CAAC,EAC1E,CAAE,SAAU,IAAa,QAAU,iBAAmB,cAAe,OAAQ,UAAW,CAC1F,EACA,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAa,EAAiB,EAAU,QAAQ,CAAC,CAAC,GACxD,GAAI,GAAe,MAAM,KAAK,aAAa,EAAY,EAAK,CAAQ,EAAI,OAAO,CACjF,CAEF,CAEA,MAAM,OAAO,EAAkB,EAAc,EAA6C,CACxF,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,QAAQ,EAClC,GAAI,CAAC,EAAQ,MAAO,CAAE,QAAS,GAAO,MAAO,qCAAsC,EACnF,GAAM,CAAC,EAAS,GAAG,GAAQ,EAAqB,EAAO,SAAU,EAAU,CAAI,EAC/E,GAAI,CAAC,EAAS,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAmC,EACjF,EAAI,KAAK,EACT,GAAI,CACF,MAAM,IAAI,SAAe,EAAS,IAAW,CAC3C,IAAM,EAAQ,EAAM,EAAS,EAAM,CAAE,MAAO,UAAW,MAAO,EAAM,CAAC,EACrE,EAAM,KAAK,QAAS,CAAM,EAC1B,EAAM,KAAK,WAAc,EAAQ,CAAC,CACpC,CAAC,CACH,QAAU,CACR,EAAI,MAAM,EACV,EAAI,cAAc,EAAI,CACxB,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,OAAS,EAAO,CACd,MAAO,CAAE,QAAS,GAAO,MAAO,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAE,CACzF,CACF,CAEA,MAAc,aAAa,EAAiB,EAAwB,EAA6C,CAC/G,IAAM,EAAa,IAAa,SAAW,EAAI,SAAW,iBAAA,CAAkB,MAAM,GAAG,EAAI,CAAC,EAAE,EACtF,EACJ,EAAK,WAAW,CAAO,GAAK,EAAQ,SAAS,EAAK,GAAG,EAAI,CAAC,EAAE,GAAK,EAAI,MAAQ,GAAA,CAAI,MAAM,EAAK,SAAS,EACvG,IAAK,IAAM,KAAY,EACrB,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAY,EAAW,EAAK,KAAK,EAAU,GAAG,IAAU,GAAW,EAAI,GAAG,IAAU,IAC1F,GAAI,CAEF,OADA,MAAM,EAAG,OAAO,EAAW,IAAa,QAAU,EAAG,UAAU,KAAO,EAAG,UAAU,IAAI,EAChF,EACT,OAAS,EAAO,CACd,GAAI,EAAE,aAAiB,OAAS,SAAU,IAAU,EAAM,OAAS,UAAY,EAAM,OAAS,WAC5F,MAAM,CACV,CACF,CAEF,MAAO,EACT,CACF,OA/DC,EAAW,EAEG,EAAA,EAAA,EAAO,EAAgB,mBAAmB,CAAA"}
@@ -1,2 +1,2 @@
1
- const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let n=require("inversify"),r=require("node:path");r=e.__toESM(r,1);let i=require("node:os");i=e.__toESM(i,1);let a=require("node:child_process"),o=require("node:crypto"),s=require("node:fs");s=e.__toESM(s,1);let c=require("@agimon-ai/doompi-extension-contracts/child-process");function l(e){return(0,o.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}let u=class{sessionKey(e,t=process.env){if(t[c.SUBAGENT_CHILD_ENV]){let e=t[c.SUBAGENT_PARENT_SESSION_ENV];if(e)return e}return e}timelinePath(e,t){let n=this.gitCommonDirectory(e),a=l(s.default.realpathSync(e)),o=process.env.PI_CODING_AGENT_DIR||r.default.join(i.default.homedir(),`.pi`,`agent`),c=r.default.join(n??o,`doom-file-edit`);return s.default.mkdirSync(c,{recursive:!0}),r.default.join(c,`${a}-${l(t)}.jsonl`)}gitCommonDirectory(e){try{return(0,a.execFileSync)(`git`,[`rev-parse`,`--path-format=absolute`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()||void 0}catch(e){if(e instanceof Error)return;throw e}}};u=t.default([(0,n.injectable)()],u),Object.defineProperty(exports,"FileEditPaths",{enumerable:!0,get:function(){return u}});
1
+ const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.cjs");let n=require("@agimon-ai/doompi-extension-contracts/child-process"),r=require("inversify"),i=require("node:os");i=e.__toESM(i,1);let a=require("node:path");a=e.__toESM(a,1);let o=require("node:child_process"),s=require("node:crypto"),c=require("node:fs");c=e.__toESM(c,1);function l(e){return(0,s.createHash)(`sha256`).update(e).digest(`hex`).slice(0,16)}let u=class{sessionKey(e,t=process.env){if(t[n.SUBAGENT_CHILD_ENV]){let e=t[n.SUBAGENT_PARENT_SESSION_ENV];if(e)return e}return e}timelinePath(e,t){let n=this.gitCommonDirectory(e),r=l(c.default.realpathSync(e)),o=process.env.PI_CODING_AGENT_DIR||a.default.join(i.default.homedir(),`.pi`,`agent`),s=a.default.join(n??o,`doom-file-edit`);return c.default.mkdirSync(s,{recursive:!0}),a.default.join(s,`${r}-${l(t)}.jsonl`)}gitCommonDirectory(e){try{return(0,o.execFileSync)(`git`,[`rev-parse`,`--path-format=absolute`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()||void 0}catch(e){if(e instanceof Error)return;throw e}}};u=t.default([(0,r.injectable)()],u),Object.defineProperty(exports,"FileEditPaths",{enumerable:!0,get:function(){return u}});
2
2
  //# sourceMappingURL=FileEditPaths.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileEditPaths.cjs","names":["createHash","SUBAGENT_CHILD_ENV","SUBAGENT_PARENT_SESSION_ENV","fs","path","os","execFileSync","injectable"],"sources":["../../../src/services/FileEditPaths/FileEditPaths.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { injectable } from 'inversify';\nimport type { IFileEditPaths } from './types.ts';\n\nfunction hash(value: string): string {\n return createHash('sha256').update(value).digest('hex').slice(0, 16);\n}\n\n@injectable()\nexport class FileEditPaths implements IFileEditPaths {\n sessionKey(sessionId: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env[SUBAGENT_CHILD_ENV]) {\n const parent = env[SUBAGENT_PARENT_SESSION_ENV];\n if (parent) return parent;\n }\n return sessionId;\n }\n\n timelinePath(cwd: string, sessionKey: string): string {\n const commonDirectory = this.gitCommonDirectory(cwd);\n const worktree = hash(fs.realpathSync(cwd));\n const agentDirectory = process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n const directory = path.join(commonDirectory ?? agentDirectory, 'doom-file-edit');\n fs.mkdirSync(directory, { recursive: true });\n return path.join(directory, `${worktree}-${hash(sessionKey)}.jsonl`);\n }\n\n private gitCommonDirectory(cwd: string): string | undefined {\n try {\n const result = execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {\n cwd,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n return result || undefined;\n } catch (error) {\n if (error instanceof Error) return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"gaASA,SAAS,EAAK,EAAuB,CACnC,OAAA,EAAOA,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAE,CACrE,CAGO,IAAM,EAAN,KAA8C,CACnD,WAAW,EAAmB,EAAyB,QAAQ,IAAa,CAC1E,GAAI,EAAIC,EAAAA,oBAAqB,CAC3B,IAAM,EAAS,EAAIC,EAAAA,6BACnB,GAAI,EAAQ,OAAO,CACrB,CACA,OAAO,CACT,CAEA,aAAa,EAAa,EAA4B,CACpD,IAAM,EAAkB,KAAK,mBAAmB,CAAG,EAC7C,EAAW,EAAKC,EAAAA,QAAG,aAAa,CAAG,CAAC,EACpC,EAAiB,QAAQ,IAAI,qBAAuBC,EAAAA,QAAK,KAAKC,EAAAA,QAAG,QAAQ,EAAG,MAAO,OAAO,EAC1F,EAAYD,EAAAA,QAAK,KAAK,GAAmB,EAAgB,gBAAgB,EAE/E,OADA,EAAA,QAAG,UAAU,EAAW,CAAE,UAAW,EAAK,CAAC,EACpCA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAS,GAAG,EAAK,CAAU,EAAE,OAAO,CACrE,CAEA,mBAA2B,EAAiC,CAC1D,GAAI,CAMF,OAAA,EALeE,EAAAA,aAAAA,CAAa,MAAO,CAAC,YAAa,yBAA0B,kBAAkB,EAAG,CAC9F,MACA,SAAU,OACV,MAAO,CAAC,SAAU,OAAQ,QAAQ,CACpC,CAAC,CAAC,CAAC,KACS,GAAK,IAAA,EACnB,OAAS,EAAO,CACd,GAAI,aAAiB,MAAO,OAC5B,MAAM,CACR,CACF,CACF,EAhCCC,EAAAA,EAAAA,QAAAA,EAAAA,EAAAA,EAAAA,WAAAA,CAAW,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"FileEditPaths.cjs","names":["createHash","SUBAGENT_CHILD_ENV","SUBAGENT_PARENT_SESSION_ENV","fs","path","os","execFileSync","injectable"],"sources":["../../../src/services/FileEditPaths/FileEditPaths.ts"],"sourcesContent":["import { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from '@agimon-ai/doompi-extension-contracts/child-process';\nimport { injectable } from 'inversify';\nimport type { IFileEditPaths } from './types.ts';\n\nfunction hash(value: string): string {\n return createHash('sha256').update(value).digest('hex').slice(0, 16);\n}\n\n@injectable()\nexport class FileEditPaths implements IFileEditPaths {\n sessionKey(sessionId: string, env: NodeJS.ProcessEnv = process.env): string {\n if (env[SUBAGENT_CHILD_ENV]) {\n const parent = env[SUBAGENT_PARENT_SESSION_ENV];\n if (parent) return parent;\n }\n return sessionId;\n }\n\n timelinePath(cwd: string, sessionKey: string): string {\n const commonDirectory = this.gitCommonDirectory(cwd);\n const worktree = hash(fs.realpathSync(cwd));\n const agentDirectory = process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), '.pi', 'agent');\n const directory = path.join(commonDirectory ?? agentDirectory, 'doom-file-edit');\n fs.mkdirSync(directory, { recursive: true });\n return path.join(directory, `${worktree}-${hash(sessionKey)}.jsonl`);\n }\n\n private gitCommonDirectory(cwd: string): string | undefined {\n try {\n const result = execFileSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], {\n cwd,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n return result || undefined;\n } catch (error) {\n if (error instanceof Error) return undefined;\n throw error;\n }\n }\n}\n"],"mappings":"4ZASA,SAAS,EAAK,EAAuB,CACnC,OAAA,EAAOA,EAAAA,WAAAA,CAAW,QAAQ,CAAC,CAAC,OAAO,CAAK,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,EAAG,EAAE,CACrE,CAGO,IAAM,EAAN,KAA8C,CACnD,WAAW,EAAmB,EAAyB,QAAQ,IAAa,CAC1E,GAAI,EAAIC,EAAAA,oBAAqB,CAC3B,IAAM,EAAS,EAAIC,EAAAA,6BACnB,GAAI,EAAQ,OAAO,CACrB,CACA,OAAO,CACT,CAEA,aAAa,EAAa,EAA4B,CACpD,IAAM,EAAkB,KAAK,mBAAmB,CAAG,EAC7C,EAAW,EAAKC,EAAAA,QAAG,aAAa,CAAG,CAAC,EACpC,EAAiB,QAAQ,IAAI,qBAAuBC,EAAAA,QAAK,KAAKC,EAAAA,QAAG,QAAQ,EAAG,MAAO,OAAO,EAC1F,EAAYD,EAAAA,QAAK,KAAK,GAAmB,EAAgB,gBAAgB,EAE/E,OADA,EAAA,QAAG,UAAU,EAAW,CAAE,UAAW,EAAK,CAAC,EACpCA,EAAAA,QAAK,KAAK,EAAW,GAAG,EAAS,GAAG,EAAK,CAAU,EAAE,OAAO,CACrE,CAEA,mBAA2B,EAAiC,CAC1D,GAAI,CAMF,OAAA,EALeE,EAAAA,aAAAA,CAAa,MAAO,CAAC,YAAa,yBAA0B,kBAAkB,EAAG,CAC9F,MACA,SAAU,OACV,MAAO,CAAC,SAAU,OAAQ,QAAQ,CACpC,CAAC,CAAC,CAAC,KACS,GAAK,IAAA,EACnB,OAAS,EAAO,CACd,GAAI,aAAiB,MAAO,OAC5B,MAAM,CACR,CACF,CACF,EAhCCC,EAAAA,EAAAA,QAAAA,EAAAA,EAAAA,EAAAA,WAAAA,CAAW,CAAA,EAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{injectable as t}from"inversify";import n from"node:path";import r from"node:os";import{execFileSync as i}from"node:child_process";import{createHash as a}from"node:crypto";import o from"node:fs";import{SUBAGENT_CHILD_ENV as s,SUBAGENT_PARENT_SESSION_ENV as c}from"@agimon-ai/doompi-extension-contracts/child-process";function l(e){return a(`sha256`).update(e).digest(`hex`).slice(0,16)}let u=class{sessionKey(e,t=process.env){if(t[s]){let e=t[c];if(e)return e}return e}timelinePath(e,t){let i=this.gitCommonDirectory(e),a=l(o.realpathSync(e)),s=process.env.PI_CODING_AGENT_DIR||n.join(r.homedir(),`.pi`,`agent`),c=n.join(i??s,`doom-file-edit`);return o.mkdirSync(c,{recursive:!0}),n.join(c,`${a}-${l(t)}.jsonl`)}gitCommonDirectory(e){try{return i(`git`,[`rev-parse`,`--path-format=absolute`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()||void 0}catch(e){if(e instanceof Error)return;throw e}}};u=e([t()],u);export{u as FileEditPaths};
1
+ import e from"../../_virtual/_@oxc-project_runtime@0.143.0/helpers/esm/decorate.mjs";import{SUBAGENT_CHILD_ENV as t,SUBAGENT_PARENT_SESSION_ENV as n}from"@agimon-ai/doompi-extension-contracts/child-process";import{injectable as r}from"inversify";import i from"node:os";import a from"node:path";import{execFileSync as o}from"node:child_process";import{createHash as s}from"node:crypto";import c from"node:fs";function l(e){return s(`sha256`).update(e).digest(`hex`).slice(0,16)}let u=class{sessionKey(e,r=process.env){if(r[t]){let e=r[n];if(e)return e}return e}timelinePath(e,t){let n=this.gitCommonDirectory(e),r=l(c.realpathSync(e)),o=process.env.PI_CODING_AGENT_DIR||a.join(i.homedir(),`.pi`,`agent`),s=a.join(n??o,`doom-file-edit`);return c.mkdirSync(s,{recursive:!0}),a.join(s,`${r}-${l(t)}.jsonl`)}gitCommonDirectory(e){try{return o(`git`,[`rev-parse`,`--path-format=absolute`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim()||void 0}catch(e){if(e instanceof Error)return;throw e}}};u=e([r()],u);export{u as FileEditPaths};
2
2
  //# sourceMappingURL=FileEditPaths.mjs.map