@agimon-ai/doompi-file-edit 0.0.1-alpha.80 → 0.0.1-alpha.81
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.
- package/dist/{src/schemas/apiContracts.cjs → apiContracts.cjs} +9 -7
- package/dist/apiContracts.cjs.map +1 -0
- package/dist/{src/schemas/apiContracts.d.mts.map → apiContracts.d.mts.map} +1 -1
- package/dist/{src/schemas/apiContracts.mjs → apiContracts.mjs} +2 -2
- package/dist/apiContracts.mjs.map +1 -0
- package/dist/extensions/pi.cjs +309 -14
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.mts +1 -1
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +298 -7
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +610 -15
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts +1 -1
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +599 -7
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/fileEditDependencies-CAnZUtLx.mjs +491 -0
- package/dist/fileEditDependencies-CAnZUtLx.mjs.map +1 -0
- package/dist/fileEditDependencies-C_9BS-aJ.cjs +500 -0
- package/dist/fileEditDependencies-C_9BS-aJ.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts +311 -4
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/treeManifest-BzCs3h_c.mjs +1042 -0
- package/dist/treeManifest-BzCs3h_c.mjs.map +1 -0
- package/dist/treeManifest-CtKbEtkE.cjs +1157 -0
- package/dist/treeManifest-CtKbEtkE.cjs.map +1 -0
- package/dist/{src/services/doomIgnore/index.mjs → webFiles-Bxs3fiqe.mjs} +8 -2
- package/dist/webFiles-Bxs3fiqe.mjs.map +1 -0
- package/dist/{src/services/doomIgnore/index.cjs → webFiles-gkmgR3MY.cjs} +33 -5
- package/dist/webFiles-gkmgR3MY.cjs.map +1 -0
- package/package.json +18 -18
- package/dist/_virtual/_rolldown/runtime.cjs +0 -23
- package/dist/api-contracts.cjs +0 -7
- package/dist/api-contracts.d.cts +0 -2
- package/dist/api-contracts.d.mts +0 -2
- package/dist/api-contracts.mjs +0 -2
- package/dist/extensions/pi.d.cts +0 -5
- package/dist/extensions/pi.d.cts.map +0 -1
- package/dist/extensions/server.d.cts +0 -5
- package/dist/extensions/server.d.cts.map +0 -1
- package/dist/index.d.cts +0 -4
- package/dist/src/constants/package.cjs +0 -10
- package/dist/src/constants/package.cjs.map +0 -1
- package/dist/src/constants/package.mjs +0 -8
- package/dist/src/constants/package.mjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/fileEdits.server.cjs +0 -9
- package/dist/src/extensions/(backend)/channel/fileEdits.server.cjs.map +0 -1
- package/dist/src/extensions/(backend)/channel/fileEdits.server.mjs +0 -10
- package/dist/src/extensions/(backend)/channel/fileEdits.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/piRoot.cjs +0 -15
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/piRoot.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/piRoot.mjs +0 -15
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/piRoot.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.cjs +0 -13
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.mjs +0 -13
- package/dist/src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/api/file-edits/route.server.cjs +0 -15
- package/dist/src/extensions/workspaces/sessions/(backend)/api/file-edits/route.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/api/file-edits/route.server.mjs +0 -16
- package/dist/src/extensions/workspaces/sessions/(backend)/api/file-edits/route.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.server.cjs +0 -6
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.server.mjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.server.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs +0 -8
- package/dist/src/extensions/workspaces/sessions/(backend)/root.cli.mjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs +0 -7
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.cjs.map +0 -1
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs +0 -8
- package/dist/src/extensions/workspaces/sessions/(backend)/root.server.mjs.map +0 -1
- package/dist/src/schemas/apiContracts.cjs.map +0 -1
- package/dist/src/schemas/apiContracts.d.cts +0 -53
- package/dist/src/schemas/apiContracts.d.cts.map +0 -1
- package/dist/src/schemas/apiContracts.mjs.map +0 -1
- package/dist/src/services/commandLine/index.cjs +0 -39
- package/dist/src/services/commandLine/index.cjs.map +0 -1
- package/dist/src/services/commandLine/index.mjs +0 -37
- package/dist/src/services/commandLine/index.mjs.map +0 -1
- package/dist/src/services/doomIgnore/index.cjs.map +0 -1
- package/dist/src/services/doomIgnore/index.mjs.map +0 -1
- package/dist/src/services/editTracker/index.cjs +0 -250
- package/dist/src/services/editTracker/index.cjs.map +0 -1
- package/dist/src/services/editTracker/index.mjs +0 -248
- package/dist/src/services/editTracker/index.mjs.map +0 -1
- package/dist/src/services/editorConfigService/index.cjs +0 -42
- package/dist/src/services/editorConfigService/index.cjs.map +0 -1
- package/dist/src/services/editorConfigService/index.mjs +0 -38
- package/dist/src/services/editorConfigService/index.mjs.map +0 -1
- package/dist/src/services/editorLauncher/index.cjs +0 -92
- package/dist/src/services/editorLauncher/index.cjs.map +0 -1
- package/dist/src/services/editorLauncher/index.mjs +0 -88
- package/dist/src/services/editorLauncher/index.mjs.map +0 -1
- package/dist/src/services/fileChanges/index.cjs +0 -143
- package/dist/src/services/fileChanges/index.cjs.map +0 -1
- package/dist/src/services/fileChanges/index.mjs +0 -136
- package/dist/src/services/fileChanges/index.mjs.map +0 -1
- package/dist/src/services/fileEditPaths/index.cjs +0 -89
- package/dist/src/services/fileEditPaths/index.cjs.map +0 -1
- package/dist/src/services/fileEditPaths/index.mjs +0 -85
- package/dist/src/services/fileEditPaths/index.mjs.map +0 -1
- package/dist/src/services/fileEditRuntime/index.cjs +0 -194
- package/dist/src/services/fileEditRuntime/index.cjs.map +0 -1
- package/dist/src/services/fileEditRuntime/index.mjs +0 -190
- package/dist/src/services/fileEditRuntime/index.mjs.map +0 -1
- package/dist/src/services/fileEditSession/index.cjs +0 -110
- package/dist/src/services/fileEditSession/index.cjs.map +0 -1
- package/dist/src/services/fileEditSession/index.mjs +0 -107
- package/dist/src/services/fileEditSession/index.mjs.map +0 -1
- package/dist/src/services/fileEditsApi/index.cjs +0 -313
- package/dist/src/services/fileEditsApi/index.cjs.map +0 -1
- package/dist/src/services/fileEditsApi/index.mjs +0 -308
- package/dist/src/services/fileEditsApi/index.mjs.map +0 -1
- package/dist/src/services/gitDiffService/index.cjs +0 -114
- package/dist/src/services/gitDiffService/index.cjs.map +0 -1
- package/dist/src/services/gitDiffService/index.mjs +0 -110
- package/dist/src/services/gitDiffService/index.mjs.map +0 -1
- package/dist/src/services/gitStatus/index.cjs +0 -94
- package/dist/src/services/gitStatus/index.cjs.map +0 -1
- package/dist/src/services/gitStatus/index.mjs +0 -92
- package/dist/src/services/gitStatus/index.mjs.map +0 -1
- package/dist/src/services/lineDiff/index.cjs +0 -206
- package/dist/src/services/lineDiff/index.cjs.map +0 -1
- package/dist/src/services/lineDiff/index.mjs +0 -205
- package/dist/src/services/lineDiff/index.mjs.map +0 -1
- package/dist/src/services/sessionStateSweep/index.cjs +0 -89
- package/dist/src/services/sessionStateSweep/index.cjs.map +0 -1
- package/dist/src/services/sessionStateSweep/index.mjs +0 -85
- package/dist/src/services/sessionStateSweep/index.mjs.map +0 -1
- package/dist/src/services/snapshotStore/index.cjs +0 -87
- package/dist/src/services/snapshotStore/index.cjs.map +0 -1
- package/dist/src/services/snapshotStore/index.mjs +0 -83
- package/dist/src/services/snapshotStore/index.mjs.map +0 -1
- package/dist/src/services/timelineStore/index.cjs +0 -99
- package/dist/src/services/timelineStore/index.cjs.map +0 -1
- package/dist/src/services/timelineStore/index.mjs +0 -97
- package/dist/src/services/timelineStore/index.mjs.map +0 -1
- package/dist/src/services/treeManifest/index.cjs +0 -148
- package/dist/src/services/treeManifest/index.cjs.map +0 -1
- package/dist/src/services/treeManifest/index.mjs +0 -143
- package/dist/src/services/treeManifest/index.mjs.map +0 -1
- package/dist/src/services/webFilesChannel/index.cjs +0 -109
- package/dist/src/services/webFilesChannel/index.cjs.map +0 -1
- package/dist/src/services/webFilesChannel/index.mjs +0 -105
- package/dist/src/services/webFilesChannel/index.mjs.map +0 -1
- package/dist/src/tui/fileEditDependencies.cjs +0 -43
- package/dist/src/tui/fileEditDependencies.cjs.map +0 -1
- package/dist/src/tui/fileEditDependencies.d.cts +0 -12
- package/dist/src/tui/fileEditDependencies.d.cts.map +0 -1
- package/dist/src/tui/fileEditDependencies.d.mts +0 -12
- package/dist/src/tui/fileEditDependencies.d.mts.map +0 -1
- package/dist/src/tui/fileEditDependencies.mjs +0 -43
- package/dist/src/tui/fileEditDependencies.mjs.map +0 -1
- package/dist/src/tui/fileEditOverlay.cjs +0 -144
- package/dist/src/tui/fileEditOverlay.cjs.map +0 -1
- package/dist/src/tui/fileEditOverlay.mjs +0 -142
- package/dist/src/tui/fileEditOverlay.mjs.map +0 -1
- package/dist/src/tui/fileEditWorkflow.cjs +0 -68
- package/dist/src/tui/fileEditWorkflow.cjs.map +0 -1
- package/dist/src/tui/fileEditWorkflow.mjs +0 -68
- package/dist/src/tui/fileEditWorkflow.mjs.map +0 -1
- package/dist/src/types/apiRoutes.cjs +0 -56
- package/dist/src/types/apiRoutes.cjs.map +0 -1
- package/dist/src/types/apiRoutes.mjs +0 -56
- package/dist/src/types/apiRoutes.mjs.map +0 -1
- package/dist/src/types/domain.d.cts +0 -91
- package/dist/src/types/domain.d.cts.map +0 -1
- package/dist/src/types/domain.d.mts +0 -91
- package/dist/src/types/domain.d.mts.map +0 -1
- package/dist/src/types/editTracker.d.cts +0 -29
- package/dist/src/types/editTracker.d.cts.map +0 -1
- package/dist/src/types/editTracker.d.mts +0 -29
- package/dist/src/types/editTracker.d.mts.map +0 -1
- package/dist/src/types/editorConfigService.d.cts +0 -11
- package/dist/src/types/editorConfigService.d.cts.map +0 -1
- package/dist/src/types/editorConfigService.d.mts +0 -11
- package/dist/src/types/editorConfigService.d.mts.map +0 -1
- package/dist/src/types/editorLauncher.d.cts +0 -17
- package/dist/src/types/editorLauncher.d.cts.map +0 -1
- package/dist/src/types/editorLauncher.d.mts +0 -17
- package/dist/src/types/editorLauncher.d.mts.map +0 -1
- package/dist/src/types/fileEditPaths.d.cts +0 -20
- package/dist/src/types/fileEditPaths.d.cts.map +0 -1
- package/dist/src/types/fileEditPaths.d.mts +0 -20
- package/dist/src/types/fileEditPaths.d.mts.map +0 -1
- package/dist/src/types/fileEditWorkflow.d.cts +0 -7
- package/dist/src/types/fileEditWorkflow.d.cts.map +0 -1
- package/dist/src/types/fileEditWorkflow.d.mts +0 -7
- package/dist/src/types/fileEditWorkflow.d.mts.map +0 -1
- package/dist/src/types/fileEditsApi.cjs +0 -25
- package/dist/src/types/fileEditsApi.cjs.map +0 -1
- package/dist/src/types/fileEditsApi.mjs +0 -24
- package/dist/src/types/fileEditsApi.mjs.map +0 -1
- package/dist/src/types/gitDiffService.d.cts +0 -7
- package/dist/src/types/gitDiffService.d.cts.map +0 -1
- package/dist/src/types/gitDiffService.d.mts +0 -7
- package/dist/src/types/gitDiffService.d.mts.map +0 -1
- package/dist/src/types/index.d.cts +0 -24
- package/dist/src/types/index.d.cts.map +0 -1
- package/dist/src/types/index.d.mts +0 -24
- package/dist/src/types/index.d.mts.map +0 -1
- package/dist/src/types/snapshotStore.d.cts +0 -35
- package/dist/src/types/snapshotStore.d.cts.map +0 -1
- package/dist/src/types/snapshotStore.d.mts +0 -35
- package/dist/src/types/snapshotStore.d.mts.map +0 -1
- package/dist/src/types/timelineStore.d.cts +0 -12
- package/dist/src/types/timelineStore.d.cts.map +0 -1
- package/dist/src/types/timelineStore.d.mts +0 -12
- package/dist/src/types/timelineStore.d.mts.map +0 -1
- package/dist/src/types/treeManifest.d.cts +0 -70
- package/dist/src/types/treeManifest.d.cts.map +0 -1
- package/dist/src/types/treeManifest.d.mts +0 -70
- package/dist/src/types/treeManifest.d.mts.map +0 -1
- package/dist/src/types/webFiles.cjs +0 -10
- package/dist/src/types/webFiles.cjs.map +0 -1
- package/dist/src/types/webFiles.mjs +0 -9
- package/dist/src/types/webFiles.mjs.map +0 -1
- /package/dist/{src/schemas/apiContracts.d.mts → apiContracts.d.mts} +0 -0
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
let _agimon_ai_doompi_core_apiContracts = require("@agimon-ai/doompi-core/apiContracts");
|
|
2
6
|
let typebox = require("typebox");
|
|
3
7
|
//#region src/schemas/apiContracts.ts
|
|
4
8
|
const S = typebox.Type.String();
|
|
@@ -63,7 +67,7 @@ const query = [{
|
|
|
63
67
|
required: true,
|
|
64
68
|
schema: typebox.Type.String({ minLength: 1 })
|
|
65
69
|
}];
|
|
66
|
-
const apiContracts = (0,
|
|
70
|
+
const apiContracts = (0, _agimon_ai_doompi_core_apiContracts.defineApiContract)({
|
|
67
71
|
version: 1,
|
|
68
72
|
dynamic: [],
|
|
69
73
|
http: [
|
|
@@ -76,7 +80,7 @@ const apiContracts = (0, _agimon_ai_doompi_core_api_contracts.defineApiContract)
|
|
|
76
80
|
authentication: "owner",
|
|
77
81
|
description: "Read recorded changes and current file content.",
|
|
78
82
|
parameters: query,
|
|
79
|
-
responses: (0,
|
|
83
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(FileDetailSchema)
|
|
80
84
|
},
|
|
81
85
|
{
|
|
82
86
|
id: "files.preview",
|
|
@@ -87,7 +91,7 @@ const apiContracts = (0, _agimon_ai_doompi_core_api_contracts.defineApiContract)
|
|
|
87
91
|
authentication: "owner",
|
|
88
92
|
description: "Read a file contained in the session directory.",
|
|
89
93
|
parameters: query,
|
|
90
|
-
responses: (0,
|
|
94
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({
|
|
91
95
|
path: S,
|
|
92
96
|
relPath: S,
|
|
93
97
|
working: Working
|
|
@@ -110,7 +114,7 @@ const apiContracts = (0, _agimon_ai_doompi_core_api_contracts.defineApiContract)
|
|
|
110
114
|
content: S
|
|
111
115
|
})
|
|
112
116
|
},
|
|
113
|
-
responses: (0,
|
|
117
|
+
responses: (0, _agimon_ai_doompi_core_apiContracts.jsonApiResponses)(typebox.Type.Object({ hash: S }))
|
|
114
118
|
},
|
|
115
119
|
{
|
|
116
120
|
id: "files.delete",
|
|
@@ -146,8 +150,6 @@ const apiContracts = (0, _agimon_ai_doompi_core_api_contracts.defineApiContract)
|
|
|
146
150
|
}))
|
|
147
151
|
});
|
|
148
152
|
//#endregion
|
|
149
|
-
exports.FileDetailSchema = FileDetailSchema;
|
|
150
|
-
exports.FilesPayloadSchema = FilesPayloadSchema;
|
|
151
153
|
exports.apiContracts = apiContracts;
|
|
152
154
|
exports.default = apiContracts;
|
|
153
155
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.cjs","names":["Type","defineApiContract","jsonApiResponses"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst B = Type.Boolean();\nconst O = Type.Optional;\nconst literals = <T extends string>(values: T[]) => Type.Union(values.map((value) => Type.Literal(value)));\nconst Tool = literals(['edit', 'write', 'bash', 'user']);\nconst Hunk = Type.Object({\n start: N,\n rows: Type.Array(Type.Object({ marker: literals(['+', '-', ' ']), line: N, content: S })),\n});\nconst Diff = { additions: N, removals: N, hunks: O(Type.Array(Hunk)), note: O(S) };\nconst Working = Type.Object({ content: S, hash: S, unavailable: B, reason: O(S) });\nexport const FileDetailSchema = Type.Object({\n path: S,\n relPath: S,\n versions: Type.Array(Type.Object({ index: N, tool: Tool, at: N, origin: literals(['tool', 'scan']), ...Diff })),\n cumulative: Type.Object(Diff),\n working: Working,\n});\nexport const FilesPayloadSchema = Type.Object({\n items: Type.Array(Type.Object({ path: S, relPath: S, tool: Tool, at: N, count: N, diffable: B })),\n});\nconst query = [{ name: 'path', in: 'query' as const, required: true, schema: Type.String({ minLength: 1 }) }];\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: [],\n http: [\n {\n id: 'files.detail',\n scope: 'session',\n basePath: 'file-edits',\n path: '/detail',\n method: 'GET',\n authentication: 'owner',\n description: 'Read recorded changes and current file content.',\n parameters: query,\n responses: jsonApiResponses(FileDetailSchema),\n },\n {\n id: 'files.preview',\n scope: 'session',\n basePath: 'file-edits',\n path: '/preview',\n method: 'GET',\n authentication: 'owner',\n description: 'Read a file contained in the session directory.',\n parameters: query,\n responses: jsonApiResponses(Type.Object({ path: S, relPath: S, working: Working })),\n },\n {\n id: 'files.save',\n scope: 'session',\n basePath: 'file-edits',\n path: '/content',\n method: 'PUT',\n authentication: 'owner',\n description: 'Save a recorded file if its hash still matches.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ path: S, expectedHash: S, content: S }),\n },\n responses: jsonApiResponses(Type.Object({ hash: S })),\n },\n {\n id: 'files.delete',\n scope: 'session',\n basePath: 'file-edits',\n path: '/content',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Delete a recorded file.',\n parameters: query,\n responses: {\n '204': { description: 'File deleted or already absent.' },\n '404': { description: 'Unrecorded file.', schema: Type.Object({ error: S }) },\n '409': { description: 'Deletion failed.', schema: Type.Object({ error: S }) },\n },\n },\n ],\n sockets: (['global', 'workspace'] as const).map((scope) => ({\n id: 'files.channel',\n scope,\n service: 'doompi.hub.v1',\n member: 'file_edits',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'File edits channel payload in the hub frame payload property.',\n input: FilesPayloadSchema,\n })),\n});\nexport default apiContracts;\n"],"mappings":";;;;;;;AAGA,MAAM,IAAIA,QAAAA,KAAK,OAAO;AACtB,MAAM,IAAIA,QAAAA,KAAK,OAAO;AACtB,MAAM,IAAIA,QAAAA,KAAK,QAAQ;AACvB,MAAM,IAAIA,QAAAA,KAAK;AACf,MAAM,YAA8B,WAAgBA,QAAAA,KAAK,MAAM,OAAO,KAAK,UAAUA,QAAAA,KAAK,QAAQ,KAAK,CAAC,CAAC;AACzG,MAAM,OAAO,SAAS;CAAC;CAAQ;CAAS;CAAQ;AAAM,CAAC;AACvD,MAAM,OAAOA,QAAAA,KAAK,OAAO;CACvB,OAAO;CACP,MAAMA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO;EAAE,QAAQ,SAAS;GAAC;GAAK;GAAK;EAAG,CAAC;EAAG,MAAM;EAAG,SAAS;CAAE,CAAC,CAAC;AAC1F,CAAC;AACD,MAAM,OAAO;CAAE,WAAW;CAAG,UAAU;CAAG,OAAO,EAAEA,QAAAA,KAAK,MAAM,IAAI,CAAC;CAAG,MAAM,EAAE,CAAC;AAAE;AACjF,MAAM,UAAUA,QAAAA,KAAK,OAAO;CAAE,SAAS;CAAG,MAAM;CAAG,aAAa;CAAG,QAAQ,EAAE,CAAC;AAAE,CAAC;AACjF,MAAa,mBAAmBA,QAAAA,KAAK,OAAO;CAC1C,MAAM;CACN,SAAS;CACT,UAAUA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO;EAAE,OAAO;EAAG,MAAM;EAAM,IAAI;EAAG,QAAQ,SAAS,CAAC,QAAQ,MAAM,CAAC;EAAG,GAAG;CAAK,CAAC,CAAC;CAC9G,YAAYA,QAAAA,KAAK,OAAO,IAAI;CAC5B,SAAS;AACX,CAAC;AACD,MAAa,qBAAqBA,QAAAA,KAAK,OAAO,EAC5C,OAAOA,QAAAA,KAAK,MAAMA,QAAAA,KAAK,OAAO;CAAE,MAAM;CAAG,SAAS;CAAG,MAAM;CAAM,IAAI;CAAG,OAAO;CAAG,UAAU;AAAE,CAAC,CAAC,EAClG,CAAC;AACD,MAAM,QAAQ,CAAC;CAAE,MAAM;CAAQ,IAAI;CAAkB,UAAU;CAAM,QAAQA,QAAAA,KAAK,OAAO,EAAE,WAAW,EAAE,CAAC;AAAE,CAAC;AAC5G,MAAa,gBAAA,GAAeC,oCAAAA,kBAAAA,CAAkB;CAC5C,SAAS;CACT,SAAS,CAAC;CACV,MAAM;EACJ;GACE,IAAI;GACJ,OAAO;GACP,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,YAAY;GACZ,YAAA,GAAWC,oCAAAA,iBAAAA,CAAiB,gBAAgB;EAC9C;EACA;GACE,IAAI;GACJ,OAAO;GACP,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,YAAY;GACZ,YAAA,GAAWA,oCAAAA,iBAAAA,CAAiBF,QAAAA,KAAK,OAAO;IAAE,MAAM;IAAG,SAAS;IAAG,SAAS;GAAQ,CAAC,CAAC;EACpF;EACA;GACE,IAAI;GACJ,OAAO;GACP,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,MAAM;IACJ,UAAU;IACV,aAAa;IACb,QAAQA,QAAAA,KAAK,OAAO;KAAE,MAAM;KAAG,cAAc;KAAG,SAAS;IAAE,CAAC;GAC9D;GACA,YAAA,GAAWE,oCAAAA,iBAAAA,CAAiBF,QAAAA,KAAK,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;EACtD;EACA;GACE,IAAI;GACJ,OAAO;GACP,UAAU;GACV,MAAM;GACN,QAAQ;GACR,gBAAgB;GAChB,aAAa;GACb,YAAY;GACZ,WAAW;IACT,OAAO,EAAE,aAAa,kCAAkC;IACxD,OAAO;KAAE,aAAa;KAAoB,QAAQA,QAAAA,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC;IAAE;IAC5E,OAAO;KAAE,aAAa;KAAoB,QAAQA,QAAAA,KAAK,OAAO,EAAE,OAAO,EAAE,CAAC;IAAE;GAC9E;EACF;CACF;CACA,SAAU,CAAC,UAAU,WAAW,CAAC,CAAW,KAAK,WAAW;EAC1D,IAAI;EACJ;EACA,SAAS;EACT,QAAQ;EACR,MAAM;EACN,WAAW;EACX,aAAa;EACb,OAAO;CACT,EAAE;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apiContracts.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBA0Ba"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineApiContract, jsonApiResponses } from "@agimon-ai/doompi-core/
|
|
1
|
+
import { defineApiContract, jsonApiResponses } from "@agimon-ai/doompi-core/apiContracts";
|
|
2
2
|
import { Type } from "typebox";
|
|
3
3
|
//#region src/schemas/apiContracts.ts
|
|
4
4
|
const S = Type.String();
|
|
@@ -146,6 +146,6 @@ const apiContracts = defineApiContract({
|
|
|
146
146
|
}))
|
|
147
147
|
});
|
|
148
148
|
//#endregion
|
|
149
|
-
export {
|
|
149
|
+
export { apiContracts, apiContracts as default };
|
|
150
150
|
|
|
151
151
|
//# sourceMappingURL=apiContracts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract, jsonApiResponses } from '@agimon-ai/doompi-core/apiContracts';\nimport { Type } from 'typebox';\n\nconst S = Type.String();\nconst N = Type.Number();\nconst B = Type.Boolean();\nconst O = Type.Optional;\nconst literals = <T extends string>(values: T[]) => Type.Union(values.map((value) => Type.Literal(value)));\nconst Tool = literals(['edit', 'write', 'bash', 'user']);\nconst Hunk = Type.Object({\n start: N,\n rows: Type.Array(Type.Object({ marker: literals(['+', '-', ' ']), line: N, content: S })),\n});\nconst Diff = { additions: N, removals: N, hunks: O(Type.Array(Hunk)), note: O(S) };\nconst Working = Type.Object({ content: S, hash: S, unavailable: B, reason: O(S) });\nexport const FileDetailSchema = Type.Object({\n path: S,\n relPath: S,\n versions: Type.Array(Type.Object({ index: N, tool: Tool, at: N, origin: literals(['tool', 'scan']), ...Diff })),\n cumulative: Type.Object(Diff),\n working: Working,\n});\nexport const FilesPayloadSchema = Type.Object({\n items: Type.Array(Type.Object({ path: S, relPath: S, tool: Tool, at: N, count: N, diffable: B })),\n});\nconst query = [{ name: 'path', in: 'query' as const, required: true, schema: Type.String({ minLength: 1 }) }];\nexport const apiContracts = defineApiContract({\n version: 1,\n dynamic: [],\n http: [\n {\n id: 'files.detail',\n scope: 'session',\n basePath: 'file-edits',\n path: '/detail',\n method: 'GET',\n authentication: 'owner',\n description: 'Read recorded changes and current file content.',\n parameters: query,\n responses: jsonApiResponses(FileDetailSchema),\n },\n {\n id: 'files.preview',\n scope: 'session',\n basePath: 'file-edits',\n path: '/preview',\n method: 'GET',\n authentication: 'owner',\n description: 'Read a file contained in the session directory.',\n parameters: query,\n responses: jsonApiResponses(Type.Object({ path: S, relPath: S, working: Working })),\n },\n {\n id: 'files.save',\n scope: 'session',\n basePath: 'file-edits',\n path: '/content',\n method: 'PUT',\n authentication: 'owner',\n description: 'Save a recorded file if its hash still matches.',\n body: {\n required: true,\n contentType: 'application/json',\n schema: Type.Object({ path: S, expectedHash: S, content: S }),\n },\n responses: jsonApiResponses(Type.Object({ hash: S })),\n },\n {\n id: 'files.delete',\n scope: 'session',\n basePath: 'file-edits',\n path: '/content',\n method: 'DELETE',\n authentication: 'owner',\n description: 'Delete a recorded file.',\n parameters: query,\n responses: {\n '204': { description: 'File deleted or already absent.' },\n '404': { description: 'Unrecorded file.', schema: Type.Object({ error: S }) },\n '409': { description: 'Deletion failed.', schema: Type.Object({ error: S }) },\n },\n },\n ],\n sockets: (['global', 'workspace'] as const).map((scope) => ({\n id: 'files.channel',\n scope,\n service: 'doompi.hub.v1',\n member: 'file_edits',\n kind: 'channel',\n direction: 'server-to-client',\n description: 'File edits channel payload in the hub frame payload property.',\n input: FilesPayloadSchema,\n })),\n});\nexport default apiContracts;\n"],"mappings":"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"}
|
package/dist/extensions/pi.cjs
CHANGED
|
@@ -2,34 +2,329 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
let
|
|
11
|
-
|
|
5
|
+
const require_treeManifest = require("../treeManifest-CtKbEtkE.cjs");
|
|
6
|
+
const require_fileEditDependencies = require("../fileEditDependencies-C_9BS-aJ.cjs");
|
|
7
|
+
const require_webFiles = require("../webFiles-gkmgR3MY.cjs");
|
|
8
|
+
let node_fs_promises = require("node:fs/promises");
|
|
9
|
+
node_fs_promises = require_treeManifest.__toESM(node_fs_promises, 1);
|
|
10
|
+
let node_path = require("node:path");
|
|
11
|
+
node_path = require_treeManifest.__toESM(node_path, 1);
|
|
12
|
+
let node_fs = require("node:fs");
|
|
13
|
+
node_fs = require_treeManifest.__toESM(node_fs, 1);
|
|
14
|
+
let _agimon_ai_doompi_core_childProcess = require("@agimon-ai/doompi-core/childProcess");
|
|
15
|
+
let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
|
|
16
|
+
let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
|
|
17
|
+
let _agimon_ai_doompi_core_uiHub = require("@agimon-ai/doompi-core/uiHub");
|
|
18
|
+
let _agimon_ai_doompi_telemetry = require("@agimon-ai/doompi-telemetry");
|
|
19
|
+
//#region src/constants/package.ts
|
|
20
|
+
const FILES_COMMAND = "file-edits";
|
|
21
|
+
const PACKAGE_SOURCE = "@agimon-ai/doompi-file-edit";
|
|
22
|
+
const DOOM_IGNORE_FILE = ".doomignore";
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/services/sessionStateSweep/index.ts
|
|
25
|
+
/**
|
|
26
|
+
* Remove the state sessions left behind when they never got to clean up.
|
|
27
|
+
*
|
|
28
|
+
* A session clears its own timeline and snapshots on shutdown, which covers the
|
|
29
|
+
* ordinary case and nothing else: a killed process, a crash, or a machine that
|
|
30
|
+
* lost power leaves both behind, and nothing ever looked at the directory
|
|
31
|
+
* again. One week of that filled a real checkout with hundreds of megabytes.
|
|
32
|
+
*
|
|
33
|
+
* Age is the only signal used, because it is the only one that is true from
|
|
34
|
+
* another process. A running session appends as it works, so its timeline is
|
|
35
|
+
* recent; a dead one stops moving at the moment it died.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* How long state may sit untouched before a later session removes it.
|
|
39
|
+
*
|
|
40
|
+
* Generous on purpose. The cost of waiting is disk, and the cost of being wrong
|
|
41
|
+
* is deleting a live session's history, so this is set far beyond any plausible
|
|
42
|
+
* gap between two appends rather than close to it.
|
|
43
|
+
*/
|
|
44
|
+
const STATE_MAX_AGE_MS = 6048e5;
|
|
45
|
+
const TIMELINE_SUFFIX = ".jsonl";
|
|
46
|
+
const SNAPSHOTS_SUFFIX = ".blobs";
|
|
47
|
+
async function remove(target) {
|
|
48
|
+
await node_fs_promises.default.rm(target, {
|
|
49
|
+
recursive: true,
|
|
50
|
+
force: true
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** The most recent time anything under this session's state moved. */
|
|
54
|
+
async function lastTouched(paths) {
|
|
55
|
+
let newest;
|
|
56
|
+
for (const target of paths) try {
|
|
57
|
+
const stat = await node_fs_promises.default.stat(target);
|
|
58
|
+
if (newest === void 0 || stat.mtimeMs > newest) newest = stat.mtimeMs;
|
|
59
|
+
} catch {}
|
|
60
|
+
return newest;
|
|
61
|
+
}
|
|
62
|
+
/** How many sessions' worth of state was removed. */
|
|
63
|
+
async function sweepSessionState(options) {
|
|
64
|
+
const { directory, keep, removeDirectory = false, now = Date.now(), maxAgeMs = STATE_MAX_AGE_MS } = options;
|
|
65
|
+
let entries;
|
|
66
|
+
try {
|
|
67
|
+
entries = await node_fs_promises.default.readdir(directory);
|
|
68
|
+
} catch {
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
const floor = now - maxAgeMs;
|
|
72
|
+
const timelines = new Set(entries.filter((entry) => entry.endsWith(TIMELINE_SUFFIX)));
|
|
73
|
+
let removed = 0;
|
|
74
|
+
for (const entry of timelines) {
|
|
75
|
+
const timelinePath = node_path.default.join(directory, entry);
|
|
76
|
+
if (keep !== void 0 && timelinePath === keep) continue;
|
|
77
|
+
const snapshotsPath = `${timelinePath.slice(0, -6)}${SNAPSHOTS_SUFFIX}`;
|
|
78
|
+
const lockPath = `${timelinePath}.lock`;
|
|
79
|
+
const touched = await lastTouched([
|
|
80
|
+
timelinePath,
|
|
81
|
+
snapshotsPath,
|
|
82
|
+
lockPath
|
|
83
|
+
]);
|
|
84
|
+
if (touched === void 0 || touched >= floor) continue;
|
|
85
|
+
await remove(snapshotsPath);
|
|
86
|
+
await remove(timelinePath);
|
|
87
|
+
await remove(lockPath);
|
|
88
|
+
removed += 1;
|
|
89
|
+
}
|
|
90
|
+
for (const entry of entries) {
|
|
91
|
+
if (!entry.endsWith(SNAPSHOTS_SUFFIX)) continue;
|
|
92
|
+
if (timelines.has(`${entry.slice(0, -6)}${TIMELINE_SUFFIX}`)) continue;
|
|
93
|
+
const orphan = node_path.default.join(directory, entry);
|
|
94
|
+
const touched = await lastTouched([orphan]);
|
|
95
|
+
if (touched === void 0 || touched >= floor) continue;
|
|
96
|
+
await remove(orphan);
|
|
97
|
+
}
|
|
98
|
+
if (removeDirectory) try {
|
|
99
|
+
await node_fs_promises.default.rmdir(directory);
|
|
100
|
+
} catch {}
|
|
101
|
+
return removed;
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
//#region src/services/fileEditRuntime/index.ts
|
|
105
|
+
/**
|
|
106
|
+
* The project's ignore rules as a test over absolute paths, or nothing when the
|
|
107
|
+
* file is absent, empty, or unreadable.
|
|
108
|
+
*
|
|
109
|
+
* Read once per session, like the exclude list it is passed beside. The web
|
|
110
|
+
* reader re-reads the same file per request, so a mid-session edit reaches the
|
|
111
|
+
* list before it reaches the recorder; that is a pre-existing difference and
|
|
112
|
+
* not one this read introduces.
|
|
113
|
+
*/
|
|
114
|
+
function readDoomIgnore(cwd) {
|
|
115
|
+
let content;
|
|
116
|
+
try {
|
|
117
|
+
content = node_fs.default.readFileSync(node_path.default.join(cwd, DOOM_IGNORE_FILE), "utf8");
|
|
118
|
+
} catch {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const matcher = require_webFiles.createDoomIgnoreMatcher(content);
|
|
122
|
+
if (matcher === void 0) return void 0;
|
|
123
|
+
return (filePath) => matcher(node_path.default.relative(cwd, filePath));
|
|
124
|
+
}
|
|
125
|
+
const FILE_EDIT_LEADER_CONTRIBUTION = {
|
|
126
|
+
source: PACKAGE_SOURCE,
|
|
127
|
+
bindings: [{
|
|
128
|
+
id: "editor.files",
|
|
129
|
+
path: [{
|
|
130
|
+
key: "e",
|
|
131
|
+
label: "extension",
|
|
132
|
+
detail: "tools, skills and config",
|
|
133
|
+
order: 50
|
|
134
|
+
}, {
|
|
135
|
+
key: "f",
|
|
136
|
+
label: "files",
|
|
137
|
+
detail: "session edits"
|
|
138
|
+
}],
|
|
139
|
+
command: { name: FILES_COMMAND }
|
|
140
|
+
}]
|
|
141
|
+
};
|
|
142
|
+
function createFileEditRuntime(dependencies) {
|
|
143
|
+
const { paths, timeline, snapshots, editTracker: tracker, workflow } = dependencies;
|
|
144
|
+
const telemetry = (0, _agimon_ai_doompi_telemetry.createDoomTelemetry)({
|
|
145
|
+
serviceName: "doom-file-edit",
|
|
146
|
+
packageName: PACKAGE_SOURCE,
|
|
147
|
+
env: process.env,
|
|
148
|
+
enableLogs: true,
|
|
149
|
+
enableTraces: true
|
|
150
|
+
});
|
|
151
|
+
const toolStartedAt = /* @__PURE__ */ new Map();
|
|
152
|
+
let active = true;
|
|
153
|
+
let sessionGeneration = 0;
|
|
154
|
+
let sessionContext;
|
|
155
|
+
/**
|
|
156
|
+
* Publishes the count the cockpit's activity group keys off. The group is
|
|
157
|
+
* hidden until this status exists, so it is written on every append rather
|
|
158
|
+
* than only when the count changes.
|
|
159
|
+
*/
|
|
160
|
+
const publishStatus = async () => {
|
|
161
|
+
if (!active || !sessionContext?.hasUI) return;
|
|
162
|
+
const entries = await timeline.list();
|
|
163
|
+
sessionContext.ui.setStatus(require_webFiles.filesStatusKey, entries.length === 0 ? "" : `${entries.length} ${entries.length === 1 ? "file" : "files"}`);
|
|
164
|
+
};
|
|
165
|
+
const dispose = async () => {
|
|
166
|
+
active = false;
|
|
167
|
+
sessionGeneration += 1;
|
|
168
|
+
toolStartedAt.clear();
|
|
169
|
+
await tracker.flush();
|
|
170
|
+
tracker.reset();
|
|
171
|
+
const closing = sessionContext;
|
|
172
|
+
sessionContext = void 0;
|
|
173
|
+
try {
|
|
174
|
+
if (!process.env[_agimon_ai_doompi_core_childProcess.SUBAGENT_CHILD_ENV]) {
|
|
175
|
+
await timeline.clear();
|
|
176
|
+
await snapshots.clear();
|
|
177
|
+
}
|
|
178
|
+
if (closing?.hasUI) closing.ui.setStatus(require_webFiles.filesStatusKey, void 0);
|
|
179
|
+
await telemetry.recordEvent("doom_file_edit.timeline_finished", { outcome: "closed" });
|
|
180
|
+
} finally {
|
|
181
|
+
await telemetry.shutdown();
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* Clears state no session will claim again. Never awaited and never allowed
|
|
186
|
+
* to throw: a sweep that cannot run is not a reason to fail a session.
|
|
187
|
+
*/
|
|
188
|
+
const sweepAbandonedState = async (cwd, keep) => {
|
|
189
|
+
try {
|
|
190
|
+
await sweepSessionState({
|
|
191
|
+
directory: paths.stateDirectory(),
|
|
192
|
+
keep
|
|
193
|
+
});
|
|
194
|
+
const legacy = paths.legacyStateDirectory(cwd);
|
|
195
|
+
if (legacy === void 0 || legacy === paths.stateDirectory()) return;
|
|
196
|
+
await sweepSessionState({
|
|
197
|
+
directory: legacy,
|
|
198
|
+
removeDirectory: true
|
|
199
|
+
});
|
|
200
|
+
} catch {}
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
onDispose: dispose,
|
|
204
|
+
services: [(cordis) => {
|
|
205
|
+
cordis.inject([_agimon_ai_doompi_core_uiHub.DOOM_UI_HUB_SERVICE], (uiContext) => {
|
|
206
|
+
const contribution = (0, _agimon_ai_doompi_core_uiHub.requireDoomUiHub)(uiContext).registerLeader(FILE_EDIT_LEADER_CONTRIBUTION);
|
|
207
|
+
return () => contribution.dispose();
|
|
208
|
+
});
|
|
209
|
+
}],
|
|
210
|
+
commands: [[FILES_COMMAND, {
|
|
211
|
+
description: "Review files edited in this session",
|
|
212
|
+
handler: async (_args, ctx) => {
|
|
213
|
+
if (!active) return;
|
|
214
|
+
if (!ctx.hasUI) {
|
|
215
|
+
ctx.ui.notify("/file-edits requires interactive mode", "error");
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
await workflow.open(ctx);
|
|
219
|
+
}
|
|
220
|
+
}]],
|
|
221
|
+
events: {
|
|
222
|
+
session_start: (_event, ctx) => {
|
|
223
|
+
if (!active) return;
|
|
224
|
+
sessionGeneration += 1;
|
|
225
|
+
toolStartedAt.clear();
|
|
226
|
+
sessionContext = ctx;
|
|
227
|
+
const sessionKey = paths.sessionKey(ctx.sessionManager.getSessionId());
|
|
228
|
+
const timelinePath = paths.timelinePath(ctx.cwd, sessionKey);
|
|
229
|
+
const snapshotsPath = paths.snapshotsPath(ctx.cwd, sessionKey);
|
|
230
|
+
timeline.initialize(timelinePath);
|
|
231
|
+
snapshots.initialize(snapshotsPath);
|
|
232
|
+
sweepAbandonedState(ctx.cwd, timelinePath);
|
|
233
|
+
const isIgnored = readDoomIgnore(ctx.cwd);
|
|
234
|
+
tracker.reset({
|
|
235
|
+
exclude: [
|
|
236
|
+
timelinePath,
|
|
237
|
+
`${timelinePath}.lock`,
|
|
238
|
+
snapshotsPath
|
|
239
|
+
],
|
|
240
|
+
...isIgnored === void 0 ? {} : { isIgnored }
|
|
241
|
+
});
|
|
242
|
+
publishStatus();
|
|
243
|
+
telemetry.recordEvent("doom_file_edit.timeline_started", { outcome: "initialized" });
|
|
244
|
+
},
|
|
245
|
+
tool_execution_start: async (event, ctx) => {
|
|
246
|
+
if (!active) return;
|
|
247
|
+
const ownGeneration = sessionGeneration;
|
|
248
|
+
toolStartedAt.set(event.toolCallId, Date.now());
|
|
249
|
+
const hookStartedAt = Date.now();
|
|
250
|
+
await tracker.start(event.toolCallId, event.toolName, event.args, ctx.cwd);
|
|
251
|
+
const hookMs = Date.now() - hookStartedAt;
|
|
252
|
+
if (!active || ownGeneration !== sessionGeneration) {
|
|
253
|
+
toolStartedAt.delete(event.toolCallId);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
telemetry.recordEvent("doom_file_edit.edit_started", {
|
|
257
|
+
"tool.name": event.toolName,
|
|
258
|
+
hook_ms: hookMs
|
|
259
|
+
});
|
|
260
|
+
},
|
|
261
|
+
tool_execution_end: async (event, ctx) => {
|
|
262
|
+
if (!active) return;
|
|
263
|
+
const startedAt = toolStartedAt.get(event.toolCallId);
|
|
264
|
+
toolStartedAt.delete(event.toolCallId);
|
|
265
|
+
const hookStartedAt = Date.now();
|
|
266
|
+
await tracker.end(event.toolCallId, event.isError, ctx.cwd);
|
|
267
|
+
if (!active) return;
|
|
268
|
+
await publishStatus();
|
|
269
|
+
const hookMs = Date.now() - hookStartedAt;
|
|
270
|
+
telemetry.recordEvent("doom_file_edit.edit_finished", {
|
|
271
|
+
"tool.name": event.toolName,
|
|
272
|
+
"tool.result.error": event.isError,
|
|
273
|
+
...startedAt === void 0 ? {} : { duration_ms: Date.now() - startedAt },
|
|
274
|
+
hook_ms: hookMs,
|
|
275
|
+
outcome: event.isError ? "failed" : "completed"
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts
|
|
283
|
+
const createFileEditPiRoot = () => {
|
|
284
|
+
const runtime = createFileEditRuntime(require_fileEditDependencies.createFileEditDependencies());
|
|
285
|
+
return {
|
|
286
|
+
value: runtime,
|
|
287
|
+
services: runtime.services,
|
|
288
|
+
onDispose: runtime.onDispose
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
//#endregion
|
|
292
|
+
//#region src/extensions/workspaces/sessions/(backend)/root.cli.ts
|
|
293
|
+
var root_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoot)(createFileEditPiRoot);
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.ts
|
|
296
|
+
var file_edits_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineRoutedContribution)((context) => [context.root.commands[0]], { cardinality: "many" });
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.ts
|
|
299
|
+
var session_start_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)((context) => context.root.events.session_start);
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.ts
|
|
302
|
+
var tool_execution_end_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)((context) => context.root.events.tool_execution_end);
|
|
303
|
+
//#endregion
|
|
304
|
+
//#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.ts
|
|
305
|
+
var tool_execution_start_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)((context) => context.root.events.tool_execution_start);
|
|
306
|
+
//#endregion
|
|
12
307
|
//#region generated/pi.ts
|
|
13
308
|
const at = (value, context) => typeof value === "function" ? value(context) : value;
|
|
14
309
|
const many = (value, context) => {
|
|
15
310
|
const resolved = typeof value === "function" ? value(context) : value;
|
|
16
311
|
return Array.isArray(resolved) ? resolved : [resolved];
|
|
17
312
|
};
|
|
18
|
-
const extension = (0,
|
|
19
|
-
const scopeSession = await
|
|
313
|
+
const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-file-edit", async (context) => {
|
|
314
|
+
const scopeSession = await root_cli_default(context);
|
|
20
315
|
const contextSession = {
|
|
21
316
|
...context,
|
|
22
317
|
root: scopeSession.value
|
|
23
318
|
};
|
|
24
319
|
return {
|
|
25
|
-
...(0,
|
|
320
|
+
...(0, _agimon_ai_doompi_core_extensionFile.composeRootHooks)(scopeSession),
|
|
26
321
|
get commands() {
|
|
27
|
-
return [...many(
|
|
322
|
+
return [...many(file_edits_cli_default, contextSession)];
|
|
28
323
|
},
|
|
29
324
|
events: {
|
|
30
|
-
session_start: at(
|
|
31
|
-
tool_execution_end: at(
|
|
32
|
-
tool_execution_start: at(
|
|
325
|
+
session_start: at(session_start_cli_default, contextSession),
|
|
326
|
+
tool_execution_end: at(tool_execution_end_cli_default, contextSession),
|
|
327
|
+
tool_execution_start: at(tool_execution_start_cli_default, contextSession)
|
|
33
328
|
},
|
|
34
329
|
services: [...scopeSession.services ?? []]
|
|
35
330
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.cjs","names":["definePiExtension","rootSession","composeRootHooks","commandFileEdits","hookSessionStart","hookToolExecutionEnd","hookToolExecutionStart"],"sources":["../../generated/pi.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/pi-extension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extension-file';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandFileEdits from '../src/extensions/workspaces/sessions/(backend)/command/file-edits.cli';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.cli';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli';\nimport hookToolExecutionStart from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandFileEdits> | OptionsOf<typeof hookSessionStart> | OptionsOf<typeof hookToolExecutionEnd> | OptionsOf<typeof hookToolExecutionStart>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-file-edit', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandFileEdits, contextSession)]; },\n events: {\n session_start: at(hookSessionStart, contextSession) as NonNullable<PiPluginContributions['events']>['session_start'],\n tool_execution_end: at(hookToolExecutionEnd, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_end'],\n tool_execution_start: at(hookToolExecutionStart, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_start'],\n },\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AAEpE,MAAM,QAAc,OAA6C,YAA6B;CAC5F,MAAM,WAAW,OAAO,UAAU,aAAc,MAA4B,OAAO,IAAI;CACvF,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAa;AAC5D;AAEA,MAAa,aAAA,GAAYA,oCAAAA,kBAAAA,CAAoC,+BAA+B,OAAO,YAAY;CAC7G,MAAM,eAAe,MAAMC,iBAAAA,QAAY,OAAO;CAC9C,MAAM,iBAAiB;EAAE,GAAG;EAAS,MAAM,aAAa;CAAM;CAC9D,OAAO;EACL,IAAA,GAAGC,sCAAAA,iBAAAA,CAAiB,YAAY;EAChC,IAAI,WAA8C;GAAE,OAAO,CAAC,GAAG,KAAKC,uBAAAA,SAAkB,cAAc,CAAC;EAAG;EACxG,QAAQ;GACN,eAAe,GAAGC,0BAAAA,SAAkB,cAAc;GAClD,oBAAoB,GAAGC,+BAAAA,SAAsB,cAAc;GAC3D,sBAAsB,GAAGC,iCAAAA,SAAwB,cAAc;EACjE;EACA,UAAU,CAAC,GAAI,aAAa,YAAY,CAAC,CAAE;CAC7C;AACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"pi.cjs","names":["fs","path","fs","path","createDoomIgnoreMatcher","createDoomTelemetry","filesStatusKey","SUBAGENT_CHILD_ENV","DOOM_UI_HUB_SERVICE","requireDoomUiHub","createFileEditDependencies","defineRoot","defineRoutedContribution","defineCliHook","defineCliHook","defineCliHook","definePiExtension","rootSession","composeRootHooks","commandFileEdits","hookSessionStart","hookToolExecutionEnd","hookToolExecutionStart"],"sources":["../../src/constants/package.ts","../../src/services/sessionStateSweep/index.ts","../../src/services/fileEditRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/piRoot.ts","../../src/extensions/workspaces/sessions/(backend)/root.cli.ts","../../src/extensions/workspaces/sessions/(backend)/command/file-edits.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-start.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli.ts","../../generated/pi.ts"],"sourcesContent":["export const FILES_COMMAND = 'file-edits';\nexport const PACKAGE_SOURCE = '@agimon-ai/doompi-file-edit';\nexport const DOOM_IGNORE_FILE = '.doomignore';\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\n\n/**\n * Remove the state sessions left behind when they never got to clean up.\n *\n * A session clears its own timeline and snapshots on shutdown, which covers the\n * ordinary case and nothing else: a killed process, a crash, or a machine that\n * lost power leaves both behind, and nothing ever looked at the directory\n * again. One week of that filled a real checkout with hundreds of megabytes.\n *\n * Age is the only signal used, because it is the only one that is true from\n * another process. A running session appends as it works, so its timeline is\n * recent; a dead one stops moving at the moment it died.\n */\n\n/**\n * How long state may sit untouched before a later session removes it.\n *\n * Generous on purpose. The cost of waiting is disk, and the cost of being wrong\n * is deleting a live session's history, so this is set far beyond any plausible\n * gap between two appends rather than close to it.\n */\nexport const STATE_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\nconst TIMELINE_SUFFIX = '.jsonl';\nconst SNAPSHOTS_SUFFIX = '.blobs';\n\nexport interface SweepSessionStateOptions {\n directory: string;\n /** The caller's own timeline, which is never a candidate however it looks. */\n keep?: string;\n /** Remove the directory itself once nothing is left in it. */\n removeDirectory?: boolean;\n now?: number;\n maxAgeMs?: number;\n}\n\nasync function remove(target: string): Promise<void> {\n await fs.rm(target, { recursive: true, force: true });\n}\n\n/** The most recent time anything under this session's state moved. */\nasync function lastTouched(paths: readonly string[]): Promise<number | undefined> {\n let newest: number | undefined;\n for (const target of paths) {\n try {\n const stat = await fs.stat(target);\n if (newest === undefined || stat.mtimeMs > newest) newest = stat.mtimeMs;\n } catch {\n // Not there is not a reason to keep the rest.\n }\n }\n return newest;\n}\n\n/** How many sessions' worth of state was removed. */\nexport async function sweepSessionState(options: SweepSessionStateOptions): Promise<number> {\n const { directory, keep, removeDirectory = false, now = Date.now(), maxAgeMs = STATE_MAX_AGE_MS } = options;\n let entries: string[];\n try {\n entries = await fs.readdir(directory);\n } catch {\n return 0;\n }\n const floor = now - maxAgeMs;\n const timelines = new Set(entries.filter((entry) => entry.endsWith(TIMELINE_SUFFIX)));\n let removed = 0;\n\n for (const entry of timelines) {\n const timelinePath = path.join(directory, entry);\n if (keep !== undefined && timelinePath === keep) continue;\n const snapshotsPath = `${timelinePath.slice(0, -TIMELINE_SUFFIX.length)}${SNAPSHOTS_SUFFIX}`;\n const lockPath = `${timelinePath}.lock`;\n const touched = await lastTouched([timelinePath, snapshotsPath, lockPath]);\n if (touched === undefined || touched >= floor) continue;\n // Content first. A crash between the two leaves a timeline whose snapshots\n // are gone, which reads as a session whose diffs expired. The other order\n // leaves a blob tree nothing will ever name again, which is the shape of\n // the leak this exists to clear.\n await remove(snapshotsPath);\n await remove(timelinePath);\n await remove(lockPath);\n removed += 1;\n }\n\n // A blob tree whose timeline is already gone is exactly what a half-finished\n // cleanup leaves, and nothing else will ever look for it.\n for (const entry of entries) {\n if (!entry.endsWith(SNAPSHOTS_SUFFIX)) continue;\n if (timelines.has(`${entry.slice(0, -SNAPSHOTS_SUFFIX.length)}${TIMELINE_SUFFIX}`)) continue;\n const orphan = path.join(directory, entry);\n const touched = await lastTouched([orphan]);\n if (touched === undefined || touched >= floor) continue;\n await remove(orphan);\n }\n\n if (removeDirectory) {\n try {\n await fs.rmdir(directory);\n } catch {\n // Still holding something, so it is not this sweep's to remove.\n }\n }\n return removed;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { SUBAGENT_CHILD_ENV } from '@agimon-ai/doompi-core/childProcess';\nimport type { LeaderContribution } from '@agimon-ai/doompi-core/leader';\nimport type { PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { DOOM_UI_HUB_SERVICE, requireDoomUiHub } from '@agimon-ai/doompi-core/uiHub';\nimport { createDoomTelemetry, type DoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport type { Context } from '@deepseek-ai/cordis';\nimport type { ExtensionContext } from '@earendil-works/pi-coding-agent';\n\nimport { FILES_COMMAND, PACKAGE_SOURCE, DOOM_IGNORE_FILE } from '../../constants/package';\nimport { createDoomIgnoreMatcher } from '../../services/doomIgnore';\nimport { sweepSessionState } from '../../services/sessionStateSweep';\nimport type { FileEditDependencies } from '../../types';\nimport { filesStatusKey } from '../../types/webFiles';\n/**\n * The project's ignore rules as a test over absolute paths, or nothing when the\n * file is absent, empty, or unreadable.\n *\n * Read once per session, like the exclude list it is passed beside. The web\n * reader re-reads the same file per request, so a mid-session edit reaches the\n * list before it reaches the recorder; that is a pre-existing difference and\n * not one this read introduces.\n */\nfunction readDoomIgnore(cwd: string): ((filePath: string) => boolean) | undefined {\n let content: string;\n try {\n content = fs.readFileSync(path.join(cwd, DOOM_IGNORE_FILE), 'utf8');\n } catch {\n return undefined;\n }\n const matcher = createDoomIgnoreMatcher(content);\n if (matcher === undefined) return undefined;\n return (filePath: string): boolean => matcher(path.relative(cwd, filePath));\n}\n\nexport const FILE_EDIT_LEADER_CONTRIBUTION = {\n source: PACKAGE_SOURCE,\n bindings: [\n {\n id: 'editor.files',\n path: [\n { key: 'e', label: 'extension', detail: 'tools, skills and config', order: 50 },\n { key: 'f', label: 'files', detail: 'session edits' },\n ],\n command: { name: FILES_COMMAND },\n },\n ],\n} as const satisfies LeaderContribution;\nexport function createFileEditRuntime(dependencies: FileEditDependencies): PiPluginContributions {\n const { paths, timeline, snapshots, editTracker: tracker, workflow } = dependencies;\n const telemetry: DoomTelemetry = createDoomTelemetry({\n serviceName: 'doom-file-edit',\n packageName: PACKAGE_SOURCE,\n env: process.env,\n enableLogs: true,\n enableTraces: true,\n });\n const toolStartedAt = new Map<string, number>();\n let active = true;\n let sessionGeneration = 0;\n let sessionContext: ExtensionContext | undefined;\n\n /**\n * Publishes the count the cockpit's activity group keys off. The group is\n * hidden until this status exists, so it is written on every append rather\n * than only when the count changes.\n */\n const publishStatus = async (): Promise<void> => {\n if (!active || !sessionContext?.hasUI) return;\n const entries = await timeline.list();\n sessionContext.ui.setStatus(\n filesStatusKey,\n entries.length === 0 ? '' : `${entries.length} ${entries.length === 1 ? 'file' : 'files'}`,\n );\n };\n\n const dispose = async () => {\n active = false;\n sessionGeneration += 1;\n toolStartedAt.clear();\n // A scan deferred by the last bash call would otherwise append after the\n // clear below and leave a timeline no session owns.\n await tracker.flush();\n tracker.reset();\n const closing = sessionContext;\n sessionContext = undefined;\n try {\n if (!process.env[SUBAGENT_CHILD_ENV]) {\n await timeline.clear();\n // The snapshots exist only to diff this session, so they go with it\n // rather than accumulating a copy of the tree on every run.\n await snapshots.clear();\n }\n if (closing?.hasUI) closing.ui.setStatus(filesStatusKey, undefined);\n await telemetry.recordEvent('doom_file_edit.timeline_finished', { outcome: 'closed' });\n } finally {\n await telemetry.shutdown();\n }\n };\n\n /**\n * Clears state no session will claim again. Never awaited and never allowed\n * to throw: a sweep that cannot run is not a reason to fail a session.\n */\n const sweepAbandonedState = async (cwd: string, keep: string): Promise<void> => {\n try {\n await sweepSessionState({ directory: paths.stateDirectory(), keep });\n const legacy = paths.legacyStateDirectory(cwd);\n if (legacy === undefined || legacy === paths.stateDirectory()) return;\n // Same age rule, so a build still running against the old location is\n // not robbed of the session it is in the middle of.\n await sweepSessionState({ directory: legacy, removeDirectory: true });\n } catch {\n // Nothing here is worth interrupting a session that is starting.\n }\n };\n return {\n onDispose: dispose,\n services: [\n (cordis: Context) => {\n cordis.inject([DOOM_UI_HUB_SERVICE], (uiContext) => {\n const contribution = requireDoomUiHub(uiContext).registerLeader(FILE_EDIT_LEADER_CONTRIBUTION);\n return () => contribution.dispose();\n });\n },\n ],\n commands: [\n [\n FILES_COMMAND,\n {\n description: 'Review files edited in this session',\n handler: async (_args, ctx) => {\n if (!active) return;\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 ],\n events: {\n session_start: (_event, ctx) => {\n if (!active) return;\n sessionGeneration += 1;\n toolStartedAt.clear();\n sessionContext = ctx;\n const sessionKey = paths.sessionKey(ctx.sessionManager.getSessionId());\n const timelinePath = paths.timelinePath(ctx.cwd, sessionKey);\n const snapshotsPath = paths.snapshotsPath(ctx.cwd, sessionKey);\n timeline.initialize(timelinePath);\n snapshots.initialize(snapshotsPath);\n // Inside a git worktree these land under the repository's own git\n // directory, which can sit inside the tree the tracker walks. Naming them\n // here is what stops the package's bookkeeping reading as session edits.\n // Whatever earlier sessions were killed before they could clean up, plus\n // anything an older build left in the repository's own git directory.\n void sweepAbandonedState(ctx.cwd, timelinePath);\n const isIgnored = readDoomIgnore(ctx.cwd);\n tracker.reset({\n exclude: [timelinePath, `${timelinePath}.lock`, snapshotsPath],\n ...(isIgnored === undefined ? {} : { isIgnored }),\n });\n // A resumed session already has a timeline, so the group must show its\n // count from the first paint rather than waiting for the next edit.\n void publishStatus();\n void telemetry.recordEvent('doom_file_edit.timeline_started', { outcome: 'initialized' });\n },\n tool_execution_start: async (event, ctx) => {\n if (!active) return;\n const ownGeneration = sessionGeneration;\n toolStartedAt.set(event.toolCallId, Date.now());\n const hookStartedAt = Date.now();\n await tracker.start(event.toolCallId, event.toolName, event.args, ctx.cwd);\n const hookMs = Date.now() - hookStartedAt;\n if (!active || ownGeneration !== sessionGeneration) {\n toolStartedAt.delete(event.toolCallId);\n return;\n }\n void telemetry.recordEvent('doom_file_edit.edit_started', {\n 'tool.name': event.toolName,\n hook_ms: hookMs,\n });\n },\n tool_execution_end: async (event, ctx) => {\n if (!active) return;\n const startedAt = toolStartedAt.get(event.toolCallId);\n toolStartedAt.delete(event.toolCallId);\n // Measured separately from the tool's own duration: this is the part of\n // the wait that belongs to this package rather than to the tool.\n const hookStartedAt = Date.now();\n await tracker.end(event.toolCallId, event.isError, ctx.cwd);\n if (!active) return;\n await publishStatus();\n const hookMs = Date.now() - hookStartedAt;\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 hook_ms: hookMs,\n outcome: event.isError ? 'failed' : 'completed',\n });\n },\n },\n };\n}\n","import { createFileEditRuntime } from '../../../../../services/fileEditRuntime';\nimport { createFileEditDependencies } from '../../../../../tui/fileEditDependencies';\nexport const createFileEditPiRoot = () => {\n const runtime = createFileEditRuntime(createFileEditDependencies());\n return { value: runtime, services: runtime.services, onDispose: runtime.onDispose };\n};\nexport type FileEditPiScope = Awaited<ReturnType<typeof createFileEditPiRoot>>['value'];\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createFileEditPiRoot } from './_lib/piRoot';\n\nexport default defineRoot(createFileEditPiRoot);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineRoutedContribution(\n (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => [context.root.commands![0]!] as const,\n { cardinality: 'many' },\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.session_start!,\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.tool_execution_end!,\n);\n","import { defineCliHook, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\nimport type { PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport type { FileEditPiScope } from '../_lib/piRoot';\nexport default defineCliHook(\n (context: WithRoot<PiPluginContext<unknown>, FileEditPiScope>) => context.root.events!.tool_execution_start!,\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, type PiPluginContext, type PiPluginContributions } from '@agimon-ai/doompi-core/piExtension';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.cli';\nimport commandFileEdits from '../src/extensions/workspaces/sessions/(backend)/command/file-edits.cli';\nimport hookSessionStart from '../src/extensions/workspaces/sessions/(backend)/hook/session-start.cli';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.cli';\nimport hookToolExecutionStart from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof rootSession> | OptionsOf<typeof commandFileEdits> | OptionsOf<typeof hookSessionStart> | OptionsOf<typeof hookToolExecutionEnd> | OptionsOf<typeof hookToolExecutionStart>, undefined>;\ntype Intersect<Union> =\n (Union extends unknown ? (value: Union) => void : never) extends (value: infer Value) => void ? Value : never;\ntype ExtensionOptions = [InferredOptions] extends [never] ? undefined : Intersect<InferredOptions>;\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\ntype ManyFactory<T, C> = (context: C) => T | readonly T[];\nconst many = <T, C>(value: T | readonly T[] | ManyFactory<T, C>, context: C): readonly T[] => {\n const resolved = typeof value === 'function' ? (value as ManyFactory<T, C>)(context) : value;\n return Array.isArray(resolved) ? resolved : [resolved as T];\n};\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-file-edit', async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get commands(): PiPluginContributions['commands'] { return [...many(commandFileEdits, contextSession)]; },\n events: {\n session_start: at(hookSessionStart, contextSession) as NonNullable<PiPluginContributions['events']>['session_start'],\n tool_execution_end: at(hookToolExecutionEnd, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_end'],\n tool_execution_start: at(hookToolExecutionStart, contextSession) as NonNullable<PiPluginContributions['events']>['tool_execution_start'],\n },\n services: [...(scopeSession.services ?? [])],\n };\n});\n\nexport default extension;\n"],"mappings":"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"}
|
package/dist/extensions/pi.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region generated/pi.d.ts
|
|
2
|
-
export declare const extension: import("@agimon-ai/doompi-core/
|
|
2
|
+
export declare const extension: import("@agimon-ai/doompi-core/runtimePiExtension").DefinedPiExtension<undefined>;
|
|
3
3
|
//#endregion
|
|
4
4
|
export { extension as default };
|
|
5
5
|
//# sourceMappingURL=pi.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAyBa
|
|
1
|
+
{"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAyBa,+DAAS"}
|