dsh-hashline-edit 0.1.1 → 0.2.0

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 (130) hide show
  1. package/README.md +70 -69
  2. package/cordis.patch.yml +1 -1
  3. package/lib/index.js +4143 -4518
  4. package/lib/types/dsh/contracts.d.ts +69 -6
  5. package/lib/types/dsh/fs.d.ts +38 -3
  6. package/lib/types/dsh/guidance.d.ts +5 -5
  7. package/lib/types/dsh/hide.d.ts +78 -0
  8. package/lib/types/dsh/host-compat.d.ts +7 -78
  9. package/lib/types/dsh/index.d.ts +17 -7
  10. package/lib/types/dsh/metrics/events.d.ts +8 -1
  11. package/lib/types/dsh/metrics/instrument.d.ts +20 -14
  12. package/lib/types/dsh/metrics/observer.d.ts +28 -0
  13. package/lib/types/dsh/sandbox.d.ts +2 -2
  14. package/lib/types/dsh/shell-hook.d.ts +17 -8
  15. package/lib/types/dsh/shell-view.d.ts +52 -0
  16. package/lib/types/dsh/tools/apply-patch.d.ts +38 -0
  17. package/lib/types/dsh/tools/context.d.ts +19 -1
  18. package/lib/types/dsh/tools/output.d.ts +32 -4
  19. package/lib/types/dsh/tools/read.d.ts +12 -15
  20. package/lib/types/dsh/tools/undo.d.ts +5 -0
  21. package/lib/types/dsh/write-hook.d.ts +8 -22
  22. package/lib/types/src/apply-patch/commit.d.ts +49 -0
  23. package/lib/types/src/apply-patch/grammar.d.ts +29 -0
  24. package/lib/types/src/apply-patch/lifecycle.d.ts +32 -0
  25. package/lib/types/src/apply-patch/plan.d.ts +50 -0
  26. package/lib/types/src/apply-patch/render.d.ts +51 -0
  27. package/lib/types/src/apply-patch/resolve.d.ts +129 -0
  28. package/lib/types/src/apply-patch/tool.d.ts +54 -0
  29. package/lib/types/src/apply-patch/types.d.ts +362 -0
  30. package/lib/types/src/domain-errors.d.ts +16 -2
  31. package/lib/types/src/edit-undo.d.ts +11 -2
  32. package/lib/types/src/file-content/detection.d.ts +17 -0
  33. package/lib/types/src/file-content/index.d.ts +2 -2
  34. package/lib/types/src/file-content/preview.d.ts +1 -1
  35. package/lib/types/src/fs-lifecycle.d.ts +44 -0
  36. package/lib/types/src/hashline/resolve.d.ts +6 -0
  37. package/lib/types/src/host-utils.d.ts +63 -0
  38. package/lib/types/src/mutation-engine/batch-span-gate.d.ts +6 -0
  39. package/lib/types/src/mutation-engine/edit-request.d.ts +34 -0
  40. package/lib/types/src/mutation-engine/pipeline.d.ts +18 -3
  41. package/lib/types/src/mutation-engine/types.d.ts +50 -58
  42. package/lib/types/src/read-expansion/grammar-manifest.d.ts +4 -2
  43. package/lib/types/src/read-expansion/java-decoration.d.ts +21 -0
  44. package/lib/types/src/read-expansion/span-expansion.d.ts +6 -2
  45. package/lib/types/src/read-expansion/span-kind.d.ts +3 -2
  46. package/lib/types/src/read-expansion/vue-decoration.d.ts +14 -0
  47. package/lib/types/src/served-session/serve-render.d.ts +9 -3
  48. package/lib/types/src/undo-store.d.ts +17 -1
  49. package/package.json +10 -22
  50. package/prompts/apply-patch-guidelines.md +10 -0
  51. package/prompts/apply-patch.md +1 -0
  52. package/prompts/read-guidelines.md +5 -5
  53. package/prompts/read.md +1 -1
  54. package/prompts/undo-last-edit-guidelines.md +2 -2
  55. package/prompts/undo-last-edit-snippet.md +1 -1
  56. package/prompts/undo-last-edit.md +1 -1
  57. package/src/apply-patch/commit.ts +190 -0
  58. package/src/apply-patch/grammar.ts +620 -0
  59. package/src/apply-patch/index.ts +17 -0
  60. package/src/apply-patch/lifecycle.ts +195 -0
  61. package/src/apply-patch/plan.ts +800 -0
  62. package/src/apply-patch/render.ts +137 -0
  63. package/src/apply-patch/resolve.ts +470 -0
  64. package/src/apply-patch/tool.ts +257 -0
  65. package/src/apply-patch/types.ts +387 -0
  66. package/src/cut-repair.ts +77 -11
  67. package/src/domain-errors.ts +58 -10
  68. package/src/edit-undo.ts +379 -25
  69. package/src/file-content/detection.ts +34 -0
  70. package/src/file-content/index.ts +2 -2
  71. package/src/file-content/preview.ts +1 -1
  72. package/src/file-content/served-header.ts +1 -1
  73. package/src/fs-lifecycle.ts +201 -0
  74. package/src/hash-store.ts +18 -1
  75. package/src/hashline/lease-resolve.ts +14 -8
  76. package/src/hashline/resolve.ts +30 -27
  77. package/src/host-utils.ts +224 -0
  78. package/src/mutation-engine/batch-span-gate.ts +17 -4
  79. package/src/mutation-engine/edit-request.ts +39 -0
  80. package/src/mutation-engine/pipeline.ts +535 -63
  81. package/src/mutation-engine/types.ts +49 -65
  82. package/src/mutation-queue.ts +1 -1
  83. package/src/prompts.ts +0 -28
  84. package/src/read-expansion/ast-provider.ts +4 -0
  85. package/src/read-expansion/grammar-manifest.ts +21 -2
  86. package/src/read-expansion/java-decoration.ts +34 -0
  87. package/src/read-expansion/span-expansion.ts +6 -2
  88. package/src/read-expansion/span-kind.ts +3 -1
  89. package/src/read-expansion/vue-decoration.ts +43 -0
  90. package/src/served-session/serve-render.ts +5 -5
  91. package/src/undo-store.ts +74 -5
  92. package/lib/types/dsh/encoding-bridge.d.ts +0 -25
  93. package/lib/types/dsh/encoding.d.ts +0 -144
  94. package/lib/types/dsh/tools/edit.d.ts +0 -10
  95. package/lib/types/src/edit-tool.d.ts +0 -41
  96. package/lib/types/src/mutation-engine/engine.d.ts +0 -31
  97. package/lib/types/src/payload-contract.d.ts +0 -124
  98. package/prompts/edit-guidelines.md +0 -10
  99. package/prompts/edit-snippet.md +0 -1
  100. package/prompts/edit.md +0 -1
  101. package/src/bash-classifier.ts +0 -1626
  102. package/src/bash-conversion/decide.ts +0 -812
  103. package/src/bash-display-transform.ts +0 -50
  104. package/src/bash-multifile-config.ts +0 -239
  105. package/src/bash-view-config.ts +0 -158
  106. package/src/edit-normalize.ts +0 -8
  107. package/src/edit-render.ts +0 -161
  108. package/src/edit-tool.ts +0 -116
  109. package/src/edit.ts +0 -136
  110. package/src/integrations/pi-lens/command.ts +0 -712
  111. package/src/integrations/pi-lens/config.ts +0 -148
  112. package/src/integrations/pi-lens/io-bridge-adapter.ts +0 -234
  113. package/src/integrations/pi-lens/io-bridge.ts +0 -112
  114. package/src/integrations/pi-lens/settings-overlay.ts +0 -272
  115. package/src/lifecycle-hooks/index.ts +0 -1992
  116. package/src/lifecycle-hooks/types.ts +0 -64
  117. package/src/mutated-files.ts +0 -75
  118. package/src/mutation-engine/engine.ts +0 -173
  119. package/src/mutation-engine/index.ts +0 -17
  120. package/src/payload-contract.ts +0 -637
  121. package/src/preview-controller.ts +0 -84
  122. package/src/read.ts +0 -865
  123. package/src/search-hook.ts +0 -41
  124. package/src/store-config.ts +0 -73
  125. package/src/store-janitor-warning.ts +0 -169
  126. package/src/store-janitor.ts +0 -539
  127. package/src/store-kernel/settings.ts +0 -233
  128. package/src/store.ts +0 -154
  129. package/src/tui-presenter.ts +0 -134
  130. package/src/write-hook.ts +0 -130
package/src/edit-tool.ts DELETED
@@ -1,116 +0,0 @@
1
- /** SAFETY: EditTool — deep module owning the edit Use Case seam.
2
- *
3
- * Graded surface: one narrow interface `EditTool { execute, preview }`
4
- * hides pipeline delegation, warnings/drift stitching.
5
- * Frameworks (pi TUI) never cross this seam — that lives in TuiPresenter.
6
- * Clean Architecture: Use Cases depend inward only (mutation-engine),
7
- * never outward to Frameworks.
8
- *
9
- * Typed boundaries: validate once at admission (payload-contract via normReq/assertReq),
10
- * trust inside. Immutable state: never mutates caller-owned request.
11
- */
12
-
13
- import { constants } from "node:fs";
14
- import { sessionKeyFor } from "./served-session/session.js";
15
- import { normReq, assertReq, type NormalizedEditRequest } from "./payload-contract.js";
16
- import { execute as engineExecute, preview as enginePreview } from "./mutation-engine/engine.js";
17
- import { isMutationSuccess } from "./mutation-engine/types.js";
18
- import { attachEnvelope } from "./error-envelope.js";
19
-
20
- type EditToolContext = {
21
- cwd: string;
22
- sessionManager?: { getSessionId(): string };
23
- };
24
-
25
- export type PreviewContext = {
26
- sessionManager?: { getSessionId(): string };
27
- };
28
-
29
- type PreviewResult = { diff: string } | { error: string };
30
-
31
- export interface EditTool {
32
- /** SAFETY: Execute a validated edit; returns pi tool_result or throws on failure. Admission: params validated by normReq/assertReq. */
33
- execute(
34
- params: unknown,
35
- signal: AbortSignal | undefined,
36
- ctx: EditToolContext,
37
- ): Promise<{
38
- content: Array<{ type: "text"; text: string }>;
39
- details: unknown;
40
- }>;
41
- /** SAFETY: Preview without persisting — mirrors pi's compPreview(request, cwd, ctx). The ctx must carry the session whose serves the anchors came from (#165). */
42
- preview(request: unknown, cwd: string, ctx: PreviewContext): Promise<PreviewResult>;
43
- }
44
-
45
- export function createEditTool(): EditTool {
46
- return {
47
- async execute(params, signal, ctx) {
48
- const canonical = normReq(params);
49
- assertReq(canonical);
50
- // SAFETY: ctx is untyped at pi boundary — cast validated by pi's runtime context shape (cwd + sessionManager)
51
- const sessionKey = sessionKeyFor(
52
- ctx as unknown as { sessionManager?: { getSessionId(): string } },
53
- );
54
- // SAFETY: canonical is validated NormalizedEditRequest after assertReq — trusted inside boundary
55
- const result = await engineExecute(canonical as NormalizedEditRequest, ctx.cwd, {
56
- accessMode: constants.R_OK | constants.W_OK,
57
- // SAFETY: signal is AbortSignal | undefined at pi boundary — runtime check via engine's abortIf
58
- ...(signal !== undefined ? { signal } : {}),
59
- sessionKey,
60
- });
61
- if (isMutationSuccess(result)) {
62
- // SAFETY: toolResult is validated by isMutationSuccess discriminated union guard
63
- return result.toolResult as {
64
- content: Array<{ type: "text"; text: string }>;
65
- details: unknown;
66
- };
67
- }
68
- // WHY: every range-family producer emits `details.cause` (user-facing diagnosis) —
69
- // WHY: carry it on the thrown error so callers catching the message still see the cause.
70
- // WHY: the whole failure envelope (code, diagnosis, rows, block) is stamped through the
71
- // WHY: envelope assembler (src/error-envelope.ts) — this seam never hand-copies fields.
72
- const failure = new Error(result.message);
73
- attachEnvelope(failure, {
74
- code: result.code,
75
- ...(result.cause !== undefined ? { cause: result.cause } : {}),
76
- // WHY: the raw payload message rides the envelope so the adapter can name the tool.
77
- // WHY: The rendered message alone cannot say which call raised the refusal.
78
- ...(result.payloadMessage !== undefined ? { payloadMessage: result.payloadMessage } : {}),
79
- servedRows: result.servedRows ?? [],
80
- servedBlock: result.servedBlock ?? "",
81
- });
82
- throw failure;
83
- },
84
- async preview(request, cwd, ctx) {
85
- try {
86
- const normalized = normReq(request);
87
- assertReq(normalized);
88
- // SAFETY: normalized is validated NormalizedEditRequest after assertReq
89
- // WHY: (#165) preview verifies against the SAME session the anchors were served to —
90
- // WHY: without a session, sessionKeyFor fails loud here instead of minting a key whose
91
- // WHY: lease lookups all miss as a misleading E_UNKNOWN_ANCHOR.
92
- const result = await enginePreview(normalized as NormalizedEditRequest, cwd, {
93
- accessMode: constants.R_OK,
94
- sessionKey: sessionKeyFor(ctx),
95
- });
96
- if (!isMutationSuccess(result)) {
97
- return { error: result.message };
98
- }
99
- const file = result.raw;
100
- if (file.originalNormalized === file.result) {
101
- return {
102
- error: `No changes made to ${file.path}. The edit produced identical content.`,
103
- };
104
- }
105
- return {
106
- // WHY: #174 single projection — the engine's `preview` seam already produced the
107
- // WHY: `genDiff` text with the pane's context; this display path renders it and
108
- // WHY: never re-projects.
109
- diff: result.diff,
110
- };
111
- } catch (error: unknown) {
112
- return { error: error instanceof Error ? error.message : String(error) };
113
- }
114
- },
115
- };
116
- }
package/src/edit.ts DELETED
@@ -1,136 +0,0 @@
1
- /** SAFETY: Edit tool — thin adapter over deep EditTool + TuiPresenter.
2
- *
3
- * Clean Architecture: this module is the Interface Adapter seam.
4
- * It owns the pi ToolDefinition wiring only; Use Case lives in EditTool,
5
- * Framework (pi TUI) lives in TuiPresenter.
6
- */
7
-
8
- import type { ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
9
- import type { TSchema } from "typebox";
10
- import {
11
- prepareEditArguments,
12
- EDIT_DESCRIPTION,
13
- type NormalizedEditRequest,
14
- type EditItem,
15
- editToolSchema,
16
- editItemSchema,
17
- anchorFromSchema,
18
- anchorToSchema,
19
- editFileSchema,
20
- editModeSchema,
21
- assertReq,
22
- } from "./payload-contract.js";
23
- import { withPayloadSubject } from "./domain-errors.js";
24
- import { attributePayloadSubject } from "./error-envelope.js";
25
- import { createEditTool, type PreviewContext } from "./edit-tool.js";
26
- import { createTuiPresenter } from "./tui-presenter.js";
27
- import { loadP, loadGuide } from "./prompts.js";
28
- import type { EditDetails } from "./edit-response.js";
29
- import type { RPreview, RRState } from "./edit-render.js";
30
-
31
- void EDIT_DESCRIPTION;
32
- /** SAFETY: @deprecated Import from "./payload-contract.js" — single source per ADR-0007 */
33
- export { assertReq };
34
- /** SAFETY: @deprecated Import from "./payload-contract.js" — single source per ADR-0007. Re-exports retained for compatibility until next MAJOR. `replaceWithSchema` is REMOVED: the ticket-04 wire has no `replace_with` fold. */
35
- export {
36
- editToolSchema,
37
- editItemSchema,
38
- anchorFromSchema,
39
- anchorToSchema,
40
- editFileSchema,
41
- editModeSchema,
42
- };
43
- export { reuseText, reuseMarkdown } from "./tui-presenter.js";
44
-
45
- /** The wire item (ticket-04): exactly one payload — `text` or `text_ref` — plus optional `at`. */
46
- export type EditParams = EditItem;
47
-
48
- export type EditRequest = NormalizedEditRequest;
49
-
50
- export async function compPreview(
51
- request: unknown,
52
- cwd: string,
53
- ctx: PreviewContext,
54
- ): Promise<RPreview> {
55
- const tool = createEditTool();
56
- return tool.preview(request, cwd, ctx);
57
- }
58
-
59
- type ToolDef = ToolDefinition<TSchema, EditDetails, RRState> & {
60
- renderShell?: "default" | "self";
61
- };
62
-
63
- export function buildToolDef(
64
- getSessionManager?: () => { getSessionId(): string } | undefined,
65
- ): ToolDef {
66
- const E_DESC = loadP("../prompts/edit.md");
67
- const E_SNIPPET = loadP("../prompts/edit-snippet.md");
68
- const E_GUIDE = loadGuide("../prompts/edit-guidelines.md");
69
- const parameters = editToolSchema;
70
- const tool = createEditTool();
71
- const presenter = createTuiPresenter(
72
- // SAFETY: fire-time read is paired with the arm-time getSessionId below; DebouncedPreview
73
- // SAFETY: drops the compute if the serving session changed between arming and firing.
74
- (req, cwd) => {
75
- // SAFETY: the fire-time read stays inside the call so the ctx names the session serving anchors now.
76
- const sessionManager = getSessionManager?.();
77
- return tool.preview(req, cwd, sessionManager === undefined ? {} : { sessionManager });
78
- },
79
- () => getSessionManager?.()?.getSessionId(),
80
- );
81
- return {
82
- name: "edit",
83
- label: "Edit",
84
- description: E_DESC,
85
- parameters,
86
- promptSnippet: E_SNIPPET,
87
- promptGuidelines: E_GUIDE,
88
- // WHY: an admission refusal raised here carries no subject, so it must name the edit tool.
89
- // WHY: Without the stamp the model reads the neutral wording — the analyzer names no caller.
90
- prepareArguments: (args: unknown) => {
91
- try {
92
- return prepareEditArguments(args);
93
- } catch (error) {
94
- throw withPayloadSubject(error, "edit");
95
- }
96
- },
97
- renderShell: "default",
98
- // SAFETY: presenter owns TUI casts — asToolDef returns ToolDefinition-typed renders, edit.ts has zero direct TUI casts
99
- ...presenter.asToolDef(),
100
- async execute(_toolCallId, params, signal, _onUpdate, ctx) {
101
- // SAFETY: pi execute boundary is untyped — ctx narrowed via sessionKeyFor, signal is AbortSignal validated by engine
102
- try {
103
- const res = await tool.execute(
104
- params,
105
- signal as AbortSignal | undefined,
106
- // SAFETY: ctx is untyped at the pi boundary — cast validated by pi's runtime shape
107
- ctx as unknown as {
108
- cwd: string;
109
- sessionManager?: { getSessionId(): string };
110
- },
111
- );
112
- // SAFETY: res is validated tool result after tool.execute — cast to pi ToolDef return type for registration
113
- return res as unknown as ReturnType<ToolDef["execute"]> extends Promise<infer R>
114
- ? R
115
- : never;
116
- } catch (error) {
117
- throw attributePayloadSubject(error, "edit");
118
- }
119
- },
120
- };
121
- }
122
-
123
- export function regEdit(pi: ExtensionAPI): void {
124
- // WHY: (#165) pi's ToolRenderContext carries no session, so the preview pane's session is
125
- // WHY: captured from the session_start ctx — the same session reads serve anchors to.
126
- // WHY: session_start fires for startup/reload/new/resume/fork, so the capture tracks switches.
127
- // WHY: (#168-class) tracking a switch is only safe if the *pending* compute re-checks it:
128
- // WHY: buildToolDef below exposes getSessionId so DebouncedPreview binds the serving session
129
- // WHY: at arm time and drops (cancels) a compute whose session changed before the timer fires,
130
- // WHY: instead of verifying anchors against a session that never served them.
131
- let sessionManager: { getSessionId(): string } | undefined;
132
- pi.on("session_start", (_event, ctx) => {
133
- sessionManager = ctx.sessionManager;
134
- });
135
- pi.registerTool(buildToolDef(() => sessionManager));
136
- }