@volcanic-dev/tephra 0.4.0 → 0.4.1

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 (3) hide show
  1. package/README.md +5 -0
  2. package/package.json +1 -1
  3. package/server.js +3 -2
package/README.md CHANGED
@@ -26,6 +26,11 @@ npx -y @volcanic-dev/tephra
26
26
 
27
27
  The commonest workflows are one call each: relocate code with `move`, overwrite a stale block with a replace-mode `paste`, duplicate with `copy` + `paste`.
28
28
 
29
+ Two semantics worth knowing precisely:
30
+
31
+ - **`move` destinations.** A destination *inside* a moved range is a loud error (a range can't move into itself; nothing is modified). A destination *between* moved ranges is well-defined gather-at-point semantics: unmoved text keeps its relative order and the concatenated payload lands exactly at the destination — moving lines 2–3 and 6–7 of an 8-line file to line 5 yields `1, 4, 2, 3, 6, 7, 5, 8`. A destination at a moved range's own boundary is an in-place move (no change).
32
+ - **`expect` in replace mode anchors at the START of the replaced range.** It is a position check, not a content-of-range check: it verifies the text beginning at the anchor (and may extend past the range's end), so pass the stale block's first characters — you don't need to reproduce the whole span you're overwriting.
33
+
29
34
  ## Named slots
30
35
 
31
36
  Every range and target takes an optional `slot` (default `"default"`). Gather many snippets in one pass — each into its own slot — then paste them in any order, any number of times. Multi-range calls must name a distinct slot per range.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volcanic-dev/tephra",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "MCP server that gives AI agents a clipboard of their own: copy an exact line:char range from a file, paste it anywhere — byte-for-byte, without touching the OS clipboard.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/server.js CHANGED
@@ -237,7 +237,7 @@ async function guarded(fn) {
237
237
  }
238
238
 
239
239
  // @tephra-tools
240
- const server = new McpServer({ name: 'tephra', version: '0.4.0' })
240
+ const server = new McpServer({ name: 'tephra', version: '0.4.1' })
241
241
 
242
242
  const expectSchema = z
243
243
  .string()
@@ -382,7 +382,7 @@ server.registerTool(
382
382
  'By default text is inserted before the character at (line, char) and nothing is overwritten; char defaults to 1 (right for whole lines) and may be one past the end of the line to append to it. ' +
383
383
  'REPLACE MODE: give end_line (plus optional end_char, or whole_lines: true for complete lines) and the slot contents replace that range instead — the result shows exactly what was removed. ' +
384
384
  'Multiple targets are applied bottom-up, so they all use the coordinates of the file as you last read it. ' +
385
- 'Pass `expect` (the text that currently begins at the position) to verify before touching anything.',
385
+ 'Pass `expect` (the text that currently begins at the position) to verify before touching anything; in replace mode it anchors at the START of the replaced range — a position check, which may extend past the range\'s end.',
386
386
  inputSchema: {
387
387
  file: z.string().describe('Absolute path of the file to paste into'),
388
388
  targets: z
@@ -462,6 +462,7 @@ server.registerTool(
462
462
  'Move one or more ranges to a destination in ONE atomic call — the compound of cut and paste. ' +
463
463
  'All coordinates, source ranges AND destination, are addressed against the file(s) exactly as they are right now: do not pre-adjust the destination for the lines the cut removes — the server does that arithmetic. ' +
464
464
  'The destination may be in a different file. Multiple ranges are concatenated at the destination in listed order, and the moved text is also stored in the clipboard slot(s). ' +
465
+ 'The destination may sit between moved ranges (unmoved text keeps its relative order and the payload lands at that point) but never inside one — that is an error. ' +
465
466
  'For whole lines, set whole_lines: true on the range and give the destination as a line number only.',
466
467
  inputSchema: {
467
468
  file: z.string().describe('Absolute path of the source file'),