@agimon-ai/doompi-read 0.0.1-alpha.51 → 0.0.1-alpha.53

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 (90) hide show
  1. package/dist/{src/schemas/apiContracts.cjs → apiContracts.cjs} +5 -1
  2. package/dist/apiContracts.cjs.map +1 -0
  3. package/dist/{src/schemas/apiContracts.d.mts.map → apiContracts.d.mts.map} +1 -1
  4. package/dist/{src/schemas/apiContracts.mjs → apiContracts.mjs} +1 -1
  5. package/dist/apiContracts.mjs.map +1 -0
  6. package/dist/extensions/mcp.cjs +5 -5
  7. package/dist/extensions/mcp.cjs.map +1 -1
  8. package/dist/extensions/mcp.d.mts +1 -1
  9. package/dist/extensions/mcp.d.mts.map +1 -1
  10. package/dist/extensions/mcp.mjs +2 -2
  11. package/dist/extensions/mcp.mjs.map +1 -1
  12. package/dist/extensions/pi.cjs +63 -4
  13. package/dist/extensions/pi.cjs.map +1 -1
  14. package/dist/extensions/pi.d.mts +1 -1
  15. package/dist/extensions/pi.d.mts.map +1 -1
  16. package/dist/extensions/pi.mjs +63 -4
  17. package/dist/extensions/pi.mjs.map +1 -1
  18. package/dist/extensions/server.cjs +7 -4
  19. package/dist/extensions/server.cjs.map +1 -1
  20. package/dist/extensions/server.d.mts +1 -1
  21. package/dist/extensions/server.d.mts.map +1 -1
  22. package/dist/extensions/server.mjs +6 -2
  23. package/dist/extensions/server.mjs.map +1 -1
  24. package/dist/index.cjs +3 -4
  25. package/dist/index.d.mts +34 -3
  26. package/dist/index.d.mts.map +1 -0
  27. package/dist/index.mjs +1 -2
  28. package/dist/{src/services/readTool/index.mjs → readTool-CAFWYKUX.mjs} +63 -15
  29. package/dist/readTool-CAFWYKUX.mjs.map +1 -0
  30. package/dist/{src/services/readTool/index.cjs → readTool-D_FT80m9.cjs} +111 -21
  31. package/dist/readTool-D_FT80m9.cjs.map +1 -0
  32. package/package.json +21 -21
  33. package/dist/api-contracts.cjs +0 -7
  34. package/dist/api-contracts.d.cts +0 -2
  35. package/dist/api-contracts.d.mts +0 -2
  36. package/dist/api-contracts.mjs +0 -2
  37. package/dist/extensions/mcp.d.cts +0 -5
  38. package/dist/extensions/mcp.d.cts.map +0 -1
  39. package/dist/extensions/pi.d.cts +0 -5
  40. package/dist/extensions/pi.d.cts.map +0 -1
  41. package/dist/extensions/server.d.cts +0 -5
  42. package/dist/extensions/server.d.cts.map +0 -1
  43. package/dist/index.d.cts +0 -3
  44. package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.cjs +0 -49
  45. package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.cjs.map +0 -1
  46. package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.mjs +0 -49
  47. package/dist/src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.mjs.map +0 -1
  48. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.cli.cjs +0 -7
  49. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.cli.cjs.map +0 -1
  50. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.cli.mjs +0 -8
  51. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.cli.mjs.map +0 -1
  52. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.server.cjs +0 -7
  53. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.server.cjs.map +0 -1
  54. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.server.mjs +0 -8
  55. package/dist/src/extensions/workspaces/sessions/(backend)/tool/read.server.mjs.map +0 -1
  56. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.cjs +0 -17
  57. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.cjs.map +0 -1
  58. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.mjs +0 -17
  59. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.mjs.map +0 -1
  60. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/read.cli.cjs +0 -7
  61. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/read.cli.cjs.map +0 -1
  62. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/read.cli.mjs +0 -8
  63. package/dist/src/extensions/workspaces/sessions/(frontend)/tool/read.cli.mjs.map +0 -1
  64. package/dist/src/schemas/apiContracts.cjs.map +0 -1
  65. package/dist/src/schemas/apiContracts.d.cts +0 -53
  66. package/dist/src/schemas/apiContracts.d.cts.map +0 -1
  67. package/dist/src/schemas/apiContracts.mjs.map +0 -1
  68. package/dist/src/schemas/readTool.cjs +0 -17
  69. package/dist/src/schemas/readTool.cjs.map +0 -1
  70. package/dist/src/schemas/readTool.d.cts +0 -10
  71. package/dist/src/schemas/readTool.d.cts.map +0 -1
  72. package/dist/src/schemas/readTool.d.mts +0 -10
  73. package/dist/src/schemas/readTool.d.mts.map +0 -1
  74. package/dist/src/schemas/readTool.mjs +0 -17
  75. package/dist/src/schemas/readTool.mjs.map +0 -1
  76. package/dist/src/services/readImage/index.cjs +0 -43
  77. package/dist/src/services/readImage/index.cjs.map +0 -1
  78. package/dist/src/services/readImage/index.d.cts +0 -14
  79. package/dist/src/services/readImage/index.d.cts.map +0 -1
  80. package/dist/src/services/readImage/index.d.mts +0 -14
  81. package/dist/src/services/readImage/index.d.mts.map +0 -1
  82. package/dist/src/services/readImage/index.mjs +0 -42
  83. package/dist/src/services/readImage/index.mjs.map +0 -1
  84. package/dist/src/services/readTool/index.cjs.map +0 -1
  85. package/dist/src/services/readTool/index.d.cts +0 -13
  86. package/dist/src/services/readTool/index.d.cts.map +0 -1
  87. package/dist/src/services/readTool/index.d.mts +0 -13
  88. package/dist/src/services/readTool/index.d.mts.map +0 -1
  89. package/dist/src/services/readTool/index.mjs.map +0 -1
  90. /package/dist/{src/schemas/apiContracts.d.mts → apiContracts.d.mts} +0 -0
@@ -1,6 +1,10 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
1
5
  //#region src/schemas/apiContracts.ts
2
6
  /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
3
- const apiContracts = (0, require("@agimon-ai/doompi-core/api-contracts").defineApiContract)({
7
+ const apiContracts = (0, require("@agimon-ai/doompi-core/apiContracts").defineApiContract)({
4
8
  version: 1,
5
9
  http: [],
6
10
  sockets: [],
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.cjs","names":["defineApiContract"],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;;;;AAGA,MAAa,gBAAA,gDAAeA,CAAAA,CAAAA,kBAAAA,CAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../../../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
1
+ {"version":3,"file":"apiContracts.d.mts","names":[],"sources":["../src/schemas/apiContracts.ts"],"mappings":";;qBAGa"}
@@ -1,4 +1,4 @@
1
- import { defineApiContract } from "@agimon-ai/doompi-core/api-contracts";
1
+ import { defineApiContract } from "@agimon-ai/doompi-core/apiContracts";
2
2
  //#region src/schemas/apiContracts.ts
3
3
  /** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */
4
4
  const apiContracts = defineApiContract({
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiContracts.mjs","names":[],"sources":["../src/schemas/apiContracts.ts"],"sourcesContent":["import { defineApiContract } from '@agimon-ai/doompi-core/apiContracts';\n\n/** This facet contributes agent tools, commands or lifecycle only, with no separate HTTP or socket surface. */\nexport const apiContracts = defineApiContract({ version: 1, http: [], sockets: [], dynamic: [] });\nexport default apiContracts;\n"],"mappings":";;;AAGA,MAAa,eAAe,kBAAkB;CAAE,SAAS;CAAG,MAAM,CAAC;CAAG,SAAS,CAAC;CAAG,SAAS,CAAC;AAAE,CAAC"}
@@ -2,13 +2,13 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- let _agimon_ai_doompi_core_mcp_facet = require("@agimon-ai/doompi-core/mcp-facet");
5
+ let _agimon_ai_doompi_core_mcpFacet = require("@agimon-ai/doompi-core/mcpFacet");
6
6
  let node_fs_promises = require("node:fs/promises");
7
7
  let _agimon_ai_doompi_hashline = require("@agimon-ai/doompi-hashline");
8
8
  let _agimon_ai_doompi_hashline_files = require("@agimon-ai/doompi-hashline/files");
9
9
  let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
10
10
  let typebox = require("typebox");
11
- let _agimon_ai_doompi_config_pi_config = require("@agimon-ai/doompi-config/pi-config");
11
+ let _agimon_ai_doompi_config_piConfig = require("@agimon-ai/doompi-config/piConfig");
12
12
  //#region src/schemas/readTool.ts
13
13
  const ReadParamsSchema = typebox.Type.Object({
14
14
  path: typebox.Type.String({ description: "Path to the file to read." }),
@@ -25,7 +25,7 @@ const ReadParamsSchema = typebox.Type.Object({
25
25
  //#region src/services/readImage/index.ts
26
26
  const OMITTED_NOTE = "[Image omitted: could not be resized below the inline image size limit.]";
27
27
  function imageLimits() {
28
- return (0, _agimon_ai_doompi_config_pi_config.loadPiImageSettings)();
28
+ return (0, _agimon_ai_doompi_config_piConfig.loadPiImageSettings)();
29
29
  }
30
30
  async function applyImageLimits(content, limits, operations) {
31
31
  if (!limits.autoResize || !content.some((part) => part.type === "image")) return content;
@@ -153,7 +153,7 @@ function createHeadlessReadTool() {
153
153
  }
154
154
  //#endregion
155
155
  //#region src/extensions/workspaces/sessions/(backend)/tool/read.mcp.ts
156
- var read_mcp_default = (0, _agimon_ai_doompi_core_mcp_facet.defineMcpTool)(createHeadlessReadTool);
156
+ var read_mcp_default = (0, _agimon_ai_doompi_core_mcpFacet.defineMcpTool)(createHeadlessReadTool);
157
157
  //#endregion
158
158
  //#region generated/mcp.ts
159
159
  const at = (value, context) => typeof value === "function" ? value(context) : value;
@@ -161,7 +161,7 @@ const via = (identity, value) => ({
161
161
  ...identity,
162
162
  ...value
163
163
  });
164
- const mcp = (0, _agimon_ai_doompi_core_mcp_facet.defineMcpPlugin)({
164
+ const mcp = (0, _agimon_ai_doompi_core_mcpFacet.defineMcpPlugin)({
165
165
  name: "@agimon-ai/doompi-read",
166
166
  session: (context) => ({ get tools() {
167
167
  return [via({ name: "read" }, at(read_mcp_default, context))];
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.cjs","names":["Type","loadPiImageSettings","resizeImage","formatDimensionNote","resolveReadInputPath","readFile","displayPath","isWritableFile","decodeUtf8","splitLines","formatFileHeader","computeFileTag","formatTaggedLine","DEFAULT_MAX_BYTES","truncateLine","truncateHead","formatSize","defineMcpTool","defineMcpPlugin","toolRead"],"sources":["../../src/schemas/readTool.ts","../../src/services/readImage/index.ts","../../src/services/readTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nexport const ReadParamsSchema = Type.Object({\n path: Type.String({ description: 'Path to the file to read.' }),\n offset: Type.Optional(Type.Integer({ minimum: 1, description: 'One-based line offset.' })),\n limit: Type.Optional(Type.Integer({ minimum: 1, description: 'Maximum number of lines to return.' })),\n});\n\nexport type ReadParams = Static<typeof ReadParamsSchema>;\n","import { loadPiImageSettings, type PiImageSettings } from '@agimon-ai/doompi-config/pi-config';\n\nconst OMITTED_NOTE = '[Image omitted: could not be resized below the inline image size limit.]';\n\nexport interface ReadTextPart {\n type: 'text';\n text: string;\n}\n\nexport interface ReadImagePart {\n type: 'image';\n data: string;\n mimeType: string;\n}\n\nexport type ReadContentPart = ReadTextPart | ReadImagePart;\n\nexport interface ReadImageResizeResult {\n readonly data: string;\n readonly mimeType: string;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly width: number;\n readonly height: number;\n readonly wasResized: boolean;\n}\n\nexport interface ReadImageResizeOperations {\n resize(\n inputBytes: Uint8Array,\n mimeType: string,\n options: { readonly maxWidth: number; readonly maxHeight: number },\n ): Promise<ReadImageResizeResult | null>;\n formatDimensionNote(result: ReadImageResizeResult): string | undefined;\n}\n\nexport function imageLimits(): PiImageSettings {\n return loadPiImageSettings();\n}\n\nexport async function applyImageLimits(\n content: ReadContentPart[],\n limits: PiImageSettings,\n operations: ReadImageResizeOperations,\n): Promise<ReadContentPart[]> {\n if (!limits.autoResize || !content.some((part) => part.type === 'image')) return content;\n const resolved: ReadContentPart[] = [];\n for (const part of content) {\n if (part.type !== 'image') {\n resolved.push(part);\n continue;\n }\n const resized = await operations.resize(Buffer.from(part.data, 'base64'), part.mimeType, {\n maxWidth: limits.maxDimension,\n maxHeight: limits.maxDimension,\n });\n if (!resized) {\n resolved.push({ type: 'text', text: OMITTED_NOTE });\n continue;\n }\n resolved.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });\n const note = operations.formatDimensionNote(resized);\n if (note) resolved.push({ type: 'text', text: note });\n }\n return resolved;\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessTool,\n DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { formatFileHeader, formatTaggedLine, splitLines } from '@agimon-ai/doompi-hashline';\nimport {\n computeFileTag,\n decodeUtf8,\n displayPath,\n isWritableFile,\n resolveReadInputPath,\n} from '@agimon-ai/doompi-hashline/files';\nimport {\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n truncateHead,\n truncateLine,\n type ReadToolDetails,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../schemas/readTool';\nimport {\n applyImageLimits,\n imageLimits,\n type ReadContentPart,\n type ReadImageResizeOperations,\n type ReadTextPart,\n} from '../readImage';\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport interface ReadToolResult {\n content: ReadContentPart[];\n details?: ReadToolDetails;\n}\n\ninterface ReadTextToolResult {\n content: ReadTextPart[];\n details?: ReadToolDetails;\n}\n\nexport function assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error('Operation aborted');\n}\n\nexport function isImagePath(filePath: string): string | undefined {\n const extension = filePath.toLowerCase().match(/\\.([a-z0-9]+)$/u)?.[1];\n if (!extension) return undefined;\n const mimeTypes: Record<string, string> = {\n avif: 'image/avif',\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n webp: 'image/webp',\n };\n return mimeTypes[extension];\n}\n\nexport async function executeHeadlessRead(\n params: ReadParams,\n cwd: string,\n signal: AbortSignal | undefined,\n): Promise<ReadToolResult> {\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(params.path, cwd);\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n const mimeType = isImagePath(absolutePath);\n if (mimeType) {\n const content: ReadContentPart[] = [\n { type: 'text', text: `Read image file ${displayPath(absolutePath, cwd)} [${mimeType}]` },\n { type: 'image', data: bytes.toString('base64'), mimeType },\n ];\n return { content: await applyImageLimits(content, imageLimits(), resizeOperations) };\n }\n if (!(await isWritableFile(absolutePath))) {\n return { content: [{ type: 'text', text: decodeUtf8(bytes, displayPath(absolutePath, cwd)) }] };\n }\n return createTaggedReadResult(bytes, displayPath(absolutePath, cwd), params);\n}\n\nexport function createTaggedReadResult(bytes: Buffer, path: string, params: ReadParams): ReadTextToolResult {\n const lines = splitLines(decodeUtf8(bytes, path));\n const startIndex = params.offset === undefined ? 0 : params.offset - 1;\n if (startIndex >= lines.length) {\n throw new Error(`Offset ${params.offset} is beyond end of file (${lines.length} lines total).`);\n }\n\n const endIndex = params.limit === undefined ? lines.length : Math.min(lines.length, startIndex + params.limit);\n const selected = lines.slice(startIndex, endIndex);\n const header = formatFileHeader(path, computeFileTag(bytes));\n const compactedLines: number[] = [];\n const headerBytes = Buffer.byteLength(header, 'utf8') + 1;\n const tagged = selected.map((line, index) => {\n const lineNumber = startIndex + index + 1;\n const full = formatTaggedLine(line, lineNumber);\n if (Buffer.byteLength(full, 'utf8') <= DEFAULT_MAX_BYTES - headerBytes) return full;\n compactedLines.push(lineNumber);\n return formatTaggedLine(truncateLine(line).text, lineNumber, '', line);\n });\n const truncation = truncateHead([header, ...tagged].join('\\n'));\n let text = truncation.content;\n let details: ReadToolDetails | undefined;\n\n if (truncation.truncated) {\n const shownLines = Math.max(0, truncation.outputLines - 1);\n const nextOffset = startIndex + shownLines + 1;\n const reason = truncation.truncatedBy === 'bytes' ? `, ${formatSize(DEFAULT_MAX_BYTES)} limit` : '';\n text += `\\n\\n[Showing ${shownLines} anchored lines${reason}. Use offset=${nextOffset} to continue.]`;\n details = { truncation };\n } else {\n const notices: string[] = [];\n if (compactedLines.length > 0) {\n notices.push(`Lines ${compactedLines.join(', ')} shown compactly. Their anchors hash the full original lines`);\n }\n if (endIndex < lines.length) {\n notices.push(`${lines.length - endIndex} more lines in file. Use offset=${endIndex + 1} to continue`);\n }\n if (notices.length > 0) text += `\\n\\n[${notices.join('. ')}.]`;\n }\n\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function isImageRead(content: readonly { readonly type: string; readonly text?: string }[]): boolean {\n return content.some((part) => part.type === 'image' || part.text?.startsWith('Read image file') === true);\n}\n\nexport function createHeadlessReadTool(): DoomHeadlessTool<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description:\n 'Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images return native-compatible content. Text is truncated to 50.0KB.',\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n execute: async (\n _toolCallId: string,\n params: ReadParams,\n signal: AbortSignal | undefined,\n _onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ) => executeHeadlessRead(params, context.cwd, signal),\n };\n}\n","import { defineMcpTool } from '@agimon-ai/doompi-core/mcp-facet';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineMcpTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcp-facet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.mcp';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomMcpSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp.cjs","names":["Type","loadPiImageSettings","resizeImage","formatDimensionNote","resolveReadInputPath","readFile","displayPath","isWritableFile","decodeUtf8","splitLines","formatFileHeader","computeFileTag","formatTaggedLine","DEFAULT_MAX_BYTES","truncateLine","truncateHead","formatSize","defineMcpTool","defineMcpPlugin","toolRead"],"sources":["../../src/schemas/readTool.ts","../../src/services/readImage/index.ts","../../src/services/readTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nexport const ReadParamsSchema = Type.Object({\n path: Type.String({ description: 'Path to the file to read.' }),\n offset: Type.Optional(Type.Integer({ minimum: 1, description: 'One-based line offset.' })),\n limit: Type.Optional(Type.Integer({ minimum: 1, description: 'Maximum number of lines to return.' })),\n});\n\nexport type ReadParams = Static<typeof ReadParamsSchema>;\n","import { loadPiImageSettings, type PiImageSettings } from '@agimon-ai/doompi-config/piConfig';\n\nconst OMITTED_NOTE = '[Image omitted: could not be resized below the inline image size limit.]';\n\nexport interface ReadTextPart {\n type: 'text';\n text: string;\n}\n\nexport interface ReadImagePart {\n type: 'image';\n data: string;\n mimeType: string;\n}\n\nexport type ReadContentPart = ReadTextPart | ReadImagePart;\n\nexport interface ReadImageResizeResult {\n readonly data: string;\n readonly mimeType: string;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly width: number;\n readonly height: number;\n readonly wasResized: boolean;\n}\n\nexport interface ReadImageResizeOperations {\n resize(\n inputBytes: Uint8Array,\n mimeType: string,\n options: { readonly maxWidth: number; readonly maxHeight: number },\n ): Promise<ReadImageResizeResult | null>;\n formatDimensionNote(result: ReadImageResizeResult): string | undefined;\n}\n\nexport function imageLimits(): PiImageSettings {\n return loadPiImageSettings();\n}\n\nexport async function applyImageLimits(\n content: ReadContentPart[],\n limits: PiImageSettings,\n operations: ReadImageResizeOperations,\n): Promise<ReadContentPart[]> {\n if (!limits.autoResize || !content.some((part) => part.type === 'image')) return content;\n const resolved: ReadContentPart[] = [];\n for (const part of content) {\n if (part.type !== 'image') {\n resolved.push(part);\n continue;\n }\n const resized = await operations.resize(Buffer.from(part.data, 'base64'), part.mimeType, {\n maxWidth: limits.maxDimension,\n maxHeight: limits.maxDimension,\n });\n if (!resized) {\n resolved.push({ type: 'text', text: OMITTED_NOTE });\n continue;\n }\n resolved.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });\n const note = operations.formatDimensionNote(resized);\n if (note) resolved.push({ type: 'text', text: note });\n }\n return resolved;\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessTool,\n DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { formatFileHeader, formatTaggedLine, splitLines } from '@agimon-ai/doompi-hashline';\nimport {\n computeFileTag,\n decodeUtf8,\n displayPath,\n isWritableFile,\n resolveReadInputPath,\n} from '@agimon-ai/doompi-hashline/files';\nimport {\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n truncateHead,\n truncateLine,\n type ReadToolDetails,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../schemas/readTool';\nimport {\n applyImageLimits,\n imageLimits,\n type ReadContentPart,\n type ReadImageResizeOperations,\n type ReadTextPart,\n} from '../readImage';\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport interface ReadToolResult {\n content: ReadContentPart[];\n details?: ReadToolDetails;\n}\n\ninterface ReadTextToolResult {\n content: ReadTextPart[];\n details?: ReadToolDetails;\n}\n\nexport function assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error('Operation aborted');\n}\n\nexport function isImagePath(filePath: string): string | undefined {\n const extension = filePath.toLowerCase().match(/\\.([a-z0-9]+)$/u)?.[1];\n if (!extension) return undefined;\n const mimeTypes: Record<string, string> = {\n avif: 'image/avif',\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n webp: 'image/webp',\n };\n return mimeTypes[extension];\n}\n\nexport async function executeHeadlessRead(\n params: ReadParams,\n cwd: string,\n signal: AbortSignal | undefined,\n): Promise<ReadToolResult> {\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(params.path, cwd);\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n const mimeType = isImagePath(absolutePath);\n if (mimeType) {\n const content: ReadContentPart[] = [\n { type: 'text', text: `Read image file ${displayPath(absolutePath, cwd)} [${mimeType}]` },\n { type: 'image', data: bytes.toString('base64'), mimeType },\n ];\n return { content: await applyImageLimits(content, imageLimits(), resizeOperations) };\n }\n if (!(await isWritableFile(absolutePath))) {\n return { content: [{ type: 'text', text: decodeUtf8(bytes, displayPath(absolutePath, cwd)) }] };\n }\n return createTaggedReadResult(bytes, displayPath(absolutePath, cwd), params);\n}\n\nexport function createTaggedReadResult(bytes: Buffer, path: string, params: ReadParams): ReadTextToolResult {\n const lines = splitLines(decodeUtf8(bytes, path));\n const startIndex = params.offset === undefined ? 0 : params.offset - 1;\n if (startIndex >= lines.length) {\n throw new Error(`Offset ${params.offset} is beyond end of file (${lines.length} lines total).`);\n }\n\n const endIndex = params.limit === undefined ? lines.length : Math.min(lines.length, startIndex + params.limit);\n const selected = lines.slice(startIndex, endIndex);\n const header = formatFileHeader(path, computeFileTag(bytes));\n const compactedLines: number[] = [];\n const headerBytes = Buffer.byteLength(header, 'utf8') + 1;\n const tagged = selected.map((line, index) => {\n const lineNumber = startIndex + index + 1;\n const full = formatTaggedLine(line, lineNumber);\n if (Buffer.byteLength(full, 'utf8') <= DEFAULT_MAX_BYTES - headerBytes) return full;\n compactedLines.push(lineNumber);\n return formatTaggedLine(truncateLine(line).text, lineNumber, '', line);\n });\n const truncation = truncateHead([header, ...tagged].join('\\n'));\n let text = truncation.content;\n let details: ReadToolDetails | undefined;\n\n if (truncation.truncated) {\n const shownLines = Math.max(0, truncation.outputLines - 1);\n const nextOffset = startIndex + shownLines + 1;\n const reason = truncation.truncatedBy === 'bytes' ? `, ${formatSize(DEFAULT_MAX_BYTES)} limit` : '';\n text += `\\n\\n[Showing ${shownLines} anchored lines${reason}. Use offset=${nextOffset} to continue.]`;\n details = { truncation };\n } else {\n const notices: string[] = [];\n if (compactedLines.length > 0) {\n notices.push(`Lines ${compactedLines.join(', ')} shown compactly. Their anchors hash the full original lines`);\n }\n if (endIndex < lines.length) {\n notices.push(`${lines.length - endIndex} more lines in file. Use offset=${endIndex + 1} to continue`);\n }\n if (notices.length > 0) text += `\\n\\n[${notices.join('. ')}.]`;\n }\n\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function isImageRead(content: readonly { readonly type: string; readonly text?: string }[]): boolean {\n return content.some((part) => part.type === 'image' || part.text?.startsWith('Read image file') === true);\n}\n\nexport function createHeadlessReadTool(): DoomHeadlessTool<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description:\n 'Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images return native-compatible content. Text is truncated to 50.0KB.',\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n execute: async (\n _toolCallId: string,\n params: ReadParams,\n signal: AbortSignal | undefined,\n _onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ) => executeHeadlessRead(params, context.cwd, signal),\n };\n}\n","import { defineMcpTool } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineMcpTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.mcp';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomMcpSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  //#region generated/mcp.d.ts
2
- export declare const mcp: import("@agimon-ai/doompi-core/mcp-facet").DoomMcpPluginDefinition;
2
+ export declare const mcp: import("@agimon-ai/doompi-core/mcpFacet").DoomMcpPluginDefinition;
3
3
  //#endregion
4
4
  export { mcp as default };
5
5
  //# sourceMappingURL=mcp.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.mts","names":[],"sources":["../../generated/mcp.ts"],"mappings":";qBAUa,gDAAG"}
1
+ {"version":3,"file":"mcp.d.mts","names":[],"sources":["../../generated/mcp.ts"],"mappings":";qBAUa,+CAAG"}
@@ -1,10 +1,10 @@
1
- import { defineMcpPlugin, defineMcpTool } from "@agimon-ai/doompi-core/mcp-facet";
1
+ import { defineMcpPlugin, defineMcpTool } from "@agimon-ai/doompi-core/mcpFacet";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { formatFileHeader, formatTaggedLine, splitLines } from "@agimon-ai/doompi-hashline";
4
4
  import { computeFileTag, decodeUtf8, displayPath, isWritableFile, resolveReadInputPath } from "@agimon-ai/doompi-hashline/files";
5
5
  import { DEFAULT_MAX_BYTES, formatDimensionNote, formatSize, resizeImage, truncateHead, truncateLine } from "@earendil-works/pi-coding-agent";
6
6
  import { Type } from "typebox";
7
- import { loadPiImageSettings } from "@agimon-ai/doompi-config/pi-config";
7
+ import { loadPiImageSettings } from "@agimon-ai/doompi-config/piConfig";
8
8
  //#region src/schemas/readTool.ts
9
9
  const ReadParamsSchema = Type.Object({
10
10
  path: Type.String({ description: "Path to the file to read." }),
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.mjs","names":["toolRead"],"sources":["../../src/schemas/readTool.ts","../../src/services/readImage/index.ts","../../src/services/readTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nexport const ReadParamsSchema = Type.Object({\n path: Type.String({ description: 'Path to the file to read.' }),\n offset: Type.Optional(Type.Integer({ minimum: 1, description: 'One-based line offset.' })),\n limit: Type.Optional(Type.Integer({ minimum: 1, description: 'Maximum number of lines to return.' })),\n});\n\nexport type ReadParams = Static<typeof ReadParamsSchema>;\n","import { loadPiImageSettings, type PiImageSettings } from '@agimon-ai/doompi-config/pi-config';\n\nconst OMITTED_NOTE = '[Image omitted: could not be resized below the inline image size limit.]';\n\nexport interface ReadTextPart {\n type: 'text';\n text: string;\n}\n\nexport interface ReadImagePart {\n type: 'image';\n data: string;\n mimeType: string;\n}\n\nexport type ReadContentPart = ReadTextPart | ReadImagePart;\n\nexport interface ReadImageResizeResult {\n readonly data: string;\n readonly mimeType: string;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly width: number;\n readonly height: number;\n readonly wasResized: boolean;\n}\n\nexport interface ReadImageResizeOperations {\n resize(\n inputBytes: Uint8Array,\n mimeType: string,\n options: { readonly maxWidth: number; readonly maxHeight: number },\n ): Promise<ReadImageResizeResult | null>;\n formatDimensionNote(result: ReadImageResizeResult): string | undefined;\n}\n\nexport function imageLimits(): PiImageSettings {\n return loadPiImageSettings();\n}\n\nexport async function applyImageLimits(\n content: ReadContentPart[],\n limits: PiImageSettings,\n operations: ReadImageResizeOperations,\n): Promise<ReadContentPart[]> {\n if (!limits.autoResize || !content.some((part) => part.type === 'image')) return content;\n const resolved: ReadContentPart[] = [];\n for (const part of content) {\n if (part.type !== 'image') {\n resolved.push(part);\n continue;\n }\n const resized = await operations.resize(Buffer.from(part.data, 'base64'), part.mimeType, {\n maxWidth: limits.maxDimension,\n maxHeight: limits.maxDimension,\n });\n if (!resized) {\n resolved.push({ type: 'text', text: OMITTED_NOTE });\n continue;\n }\n resolved.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });\n const note = operations.formatDimensionNote(resized);\n if (note) resolved.push({ type: 'text', text: note });\n }\n return resolved;\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessTool,\n DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { formatFileHeader, formatTaggedLine, splitLines } from '@agimon-ai/doompi-hashline';\nimport {\n computeFileTag,\n decodeUtf8,\n displayPath,\n isWritableFile,\n resolveReadInputPath,\n} from '@agimon-ai/doompi-hashline/files';\nimport {\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n truncateHead,\n truncateLine,\n type ReadToolDetails,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../schemas/readTool';\nimport {\n applyImageLimits,\n imageLimits,\n type ReadContentPart,\n type ReadImageResizeOperations,\n type ReadTextPart,\n} from '../readImage';\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport interface ReadToolResult {\n content: ReadContentPart[];\n details?: ReadToolDetails;\n}\n\ninterface ReadTextToolResult {\n content: ReadTextPart[];\n details?: ReadToolDetails;\n}\n\nexport function assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error('Operation aborted');\n}\n\nexport function isImagePath(filePath: string): string | undefined {\n const extension = filePath.toLowerCase().match(/\\.([a-z0-9]+)$/u)?.[1];\n if (!extension) return undefined;\n const mimeTypes: Record<string, string> = {\n avif: 'image/avif',\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n webp: 'image/webp',\n };\n return mimeTypes[extension];\n}\n\nexport async function executeHeadlessRead(\n params: ReadParams,\n cwd: string,\n signal: AbortSignal | undefined,\n): Promise<ReadToolResult> {\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(params.path, cwd);\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n const mimeType = isImagePath(absolutePath);\n if (mimeType) {\n const content: ReadContentPart[] = [\n { type: 'text', text: `Read image file ${displayPath(absolutePath, cwd)} [${mimeType}]` },\n { type: 'image', data: bytes.toString('base64'), mimeType },\n ];\n return { content: await applyImageLimits(content, imageLimits(), resizeOperations) };\n }\n if (!(await isWritableFile(absolutePath))) {\n return { content: [{ type: 'text', text: decodeUtf8(bytes, displayPath(absolutePath, cwd)) }] };\n }\n return createTaggedReadResult(bytes, displayPath(absolutePath, cwd), params);\n}\n\nexport function createTaggedReadResult(bytes: Buffer, path: string, params: ReadParams): ReadTextToolResult {\n const lines = splitLines(decodeUtf8(bytes, path));\n const startIndex = params.offset === undefined ? 0 : params.offset - 1;\n if (startIndex >= lines.length) {\n throw new Error(`Offset ${params.offset} is beyond end of file (${lines.length} lines total).`);\n }\n\n const endIndex = params.limit === undefined ? lines.length : Math.min(lines.length, startIndex + params.limit);\n const selected = lines.slice(startIndex, endIndex);\n const header = formatFileHeader(path, computeFileTag(bytes));\n const compactedLines: number[] = [];\n const headerBytes = Buffer.byteLength(header, 'utf8') + 1;\n const tagged = selected.map((line, index) => {\n const lineNumber = startIndex + index + 1;\n const full = formatTaggedLine(line, lineNumber);\n if (Buffer.byteLength(full, 'utf8') <= DEFAULT_MAX_BYTES - headerBytes) return full;\n compactedLines.push(lineNumber);\n return formatTaggedLine(truncateLine(line).text, lineNumber, '', line);\n });\n const truncation = truncateHead([header, ...tagged].join('\\n'));\n let text = truncation.content;\n let details: ReadToolDetails | undefined;\n\n if (truncation.truncated) {\n const shownLines = Math.max(0, truncation.outputLines - 1);\n const nextOffset = startIndex + shownLines + 1;\n const reason = truncation.truncatedBy === 'bytes' ? `, ${formatSize(DEFAULT_MAX_BYTES)} limit` : '';\n text += `\\n\\n[Showing ${shownLines} anchored lines${reason}. Use offset=${nextOffset} to continue.]`;\n details = { truncation };\n } else {\n const notices: string[] = [];\n if (compactedLines.length > 0) {\n notices.push(`Lines ${compactedLines.join(', ')} shown compactly. Their anchors hash the full original lines`);\n }\n if (endIndex < lines.length) {\n notices.push(`${lines.length - endIndex} more lines in file. Use offset=${endIndex + 1} to continue`);\n }\n if (notices.length > 0) text += `\\n\\n[${notices.join('. ')}.]`;\n }\n\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function isImageRead(content: readonly { readonly type: string; readonly text?: string }[]): boolean {\n return content.some((part) => part.type === 'image' || part.text?.startsWith('Read image file') === true);\n}\n\nexport function createHeadlessReadTool(): DoomHeadlessTool<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description:\n 'Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images return native-compatible content. Text is truncated to 50.0KB.',\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n execute: async (\n _toolCallId: string,\n params: ReadParams,\n signal: AbortSignal | undefined,\n _onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ) => executeHeadlessRead(params, context.cwd, signal),\n };\n}\n","import { defineMcpTool } from '@agimon-ai/doompi-core/mcp-facet';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineMcpTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcp-facet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.mcp';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomMcpSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp.mjs","names":["toolRead"],"sources":["../../src/schemas/readTool.ts","../../src/services/readImage/index.ts","../../src/services/readTool/index.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.mcp.ts","../../generated/mcp.ts"],"sourcesContent":["import { type Static, Type } from 'typebox';\n\nexport const ReadParamsSchema = Type.Object({\n path: Type.String({ description: 'Path to the file to read.' }),\n offset: Type.Optional(Type.Integer({ minimum: 1, description: 'One-based line offset.' })),\n limit: Type.Optional(Type.Integer({ minimum: 1, description: 'Maximum number of lines to return.' })),\n});\n\nexport type ReadParams = Static<typeof ReadParamsSchema>;\n","import { loadPiImageSettings, type PiImageSettings } from '@agimon-ai/doompi-config/piConfig';\n\nconst OMITTED_NOTE = '[Image omitted: could not be resized below the inline image size limit.]';\n\nexport interface ReadTextPart {\n type: 'text';\n text: string;\n}\n\nexport interface ReadImagePart {\n type: 'image';\n data: string;\n mimeType: string;\n}\n\nexport type ReadContentPart = ReadTextPart | ReadImagePart;\n\nexport interface ReadImageResizeResult {\n readonly data: string;\n readonly mimeType: string;\n readonly originalWidth: number;\n readonly originalHeight: number;\n readonly width: number;\n readonly height: number;\n readonly wasResized: boolean;\n}\n\nexport interface ReadImageResizeOperations {\n resize(\n inputBytes: Uint8Array,\n mimeType: string,\n options: { readonly maxWidth: number; readonly maxHeight: number },\n ): Promise<ReadImageResizeResult | null>;\n formatDimensionNote(result: ReadImageResizeResult): string | undefined;\n}\n\nexport function imageLimits(): PiImageSettings {\n return loadPiImageSettings();\n}\n\nexport async function applyImageLimits(\n content: ReadContentPart[],\n limits: PiImageSettings,\n operations: ReadImageResizeOperations,\n): Promise<ReadContentPart[]> {\n if (!limits.autoResize || !content.some((part) => part.type === 'image')) return content;\n const resolved: ReadContentPart[] = [];\n for (const part of content) {\n if (part.type !== 'image') {\n resolved.push(part);\n continue;\n }\n const resized = await operations.resize(Buffer.from(part.data, 'base64'), part.mimeType, {\n maxWidth: limits.maxDimension,\n maxHeight: limits.maxDimension,\n });\n if (!resized) {\n resolved.push({ type: 'text', text: OMITTED_NOTE });\n continue;\n }\n resolved.push({ type: 'image', data: resized.data, mimeType: resized.mimeType });\n const note = operations.formatDimensionNote(resized);\n if (note) resolved.push({ type: 'text', text: note });\n }\n return resolved;\n}\n","import { readFile } from 'node:fs/promises';\n\nimport type {\n DoomHeadlessExecutionContext,\n DoomHeadlessTool,\n DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { formatFileHeader, formatTaggedLine, splitLines } from '@agimon-ai/doompi-hashline';\nimport {\n computeFileTag,\n decodeUtf8,\n displayPath,\n isWritableFile,\n resolveReadInputPath,\n} from '@agimon-ai/doompi-hashline/files';\nimport {\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n truncateHead,\n truncateLine,\n type ReadToolDetails,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../schemas/readTool';\nimport {\n applyImageLimits,\n imageLimits,\n type ReadContentPart,\n type ReadImageResizeOperations,\n type ReadTextPart,\n} from '../readImage';\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport interface ReadToolResult {\n content: ReadContentPart[];\n details?: ReadToolDetails;\n}\n\ninterface ReadTextToolResult {\n content: ReadTextPart[];\n details?: ReadToolDetails;\n}\n\nexport function assertNotAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) throw new Error('Operation aborted');\n}\n\nexport function isImagePath(filePath: string): string | undefined {\n const extension = filePath.toLowerCase().match(/\\.([a-z0-9]+)$/u)?.[1];\n if (!extension) return undefined;\n const mimeTypes: Record<string, string> = {\n avif: 'image/avif',\n gif: 'image/gif',\n jpeg: 'image/jpeg',\n jpg: 'image/jpeg',\n png: 'image/png',\n webp: 'image/webp',\n };\n return mimeTypes[extension];\n}\n\nexport async function executeHeadlessRead(\n params: ReadParams,\n cwd: string,\n signal: AbortSignal | undefined,\n): Promise<ReadToolResult> {\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(params.path, cwd);\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n const mimeType = isImagePath(absolutePath);\n if (mimeType) {\n const content: ReadContentPart[] = [\n { type: 'text', text: `Read image file ${displayPath(absolutePath, cwd)} [${mimeType}]` },\n { type: 'image', data: bytes.toString('base64'), mimeType },\n ];\n return { content: await applyImageLimits(content, imageLimits(), resizeOperations) };\n }\n if (!(await isWritableFile(absolutePath))) {\n return { content: [{ type: 'text', text: decodeUtf8(bytes, displayPath(absolutePath, cwd)) }] };\n }\n return createTaggedReadResult(bytes, displayPath(absolutePath, cwd), params);\n}\n\nexport function createTaggedReadResult(bytes: Buffer, path: string, params: ReadParams): ReadTextToolResult {\n const lines = splitLines(decodeUtf8(bytes, path));\n const startIndex = params.offset === undefined ? 0 : params.offset - 1;\n if (startIndex >= lines.length) {\n throw new Error(`Offset ${params.offset} is beyond end of file (${lines.length} lines total).`);\n }\n\n const endIndex = params.limit === undefined ? lines.length : Math.min(lines.length, startIndex + params.limit);\n const selected = lines.slice(startIndex, endIndex);\n const header = formatFileHeader(path, computeFileTag(bytes));\n const compactedLines: number[] = [];\n const headerBytes = Buffer.byteLength(header, 'utf8') + 1;\n const tagged = selected.map((line, index) => {\n const lineNumber = startIndex + index + 1;\n const full = formatTaggedLine(line, lineNumber);\n if (Buffer.byteLength(full, 'utf8') <= DEFAULT_MAX_BYTES - headerBytes) return full;\n compactedLines.push(lineNumber);\n return formatTaggedLine(truncateLine(line).text, lineNumber, '', line);\n });\n const truncation = truncateHead([header, ...tagged].join('\\n'));\n let text = truncation.content;\n let details: ReadToolDetails | undefined;\n\n if (truncation.truncated) {\n const shownLines = Math.max(0, truncation.outputLines - 1);\n const nextOffset = startIndex + shownLines + 1;\n const reason = truncation.truncatedBy === 'bytes' ? `, ${formatSize(DEFAULT_MAX_BYTES)} limit` : '';\n text += `\\n\\n[Showing ${shownLines} anchored lines${reason}. Use offset=${nextOffset} to continue.]`;\n details = { truncation };\n } else {\n const notices: string[] = [];\n if (compactedLines.length > 0) {\n notices.push(`Lines ${compactedLines.join(', ')} shown compactly. Their anchors hash the full original lines`);\n }\n if (endIndex < lines.length) {\n notices.push(`${lines.length - endIndex} more lines in file. Use offset=${endIndex + 1} to continue`);\n }\n if (notices.length > 0) text += `\\n\\n[${notices.join('. ')}.]`;\n }\n\n return { content: [{ type: 'text', text }], details };\n}\n\nexport function isImageRead(content: readonly { readonly type: string; readonly text?: string }[]): boolean {\n return content.some((part) => part.type === 'image' || part.text?.startsWith('Read image file') === true);\n}\n\nexport function createHeadlessReadTool(): DoomHeadlessTool<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description:\n 'Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images return native-compatible content. Text is truncated to 50.0KB.',\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n execute: async (\n _toolCallId: string,\n params: ReadParams,\n signal: AbortSignal | undefined,\n _onUpdate: ((result: DoomHeadlessToolResult) => void) | undefined,\n context: DoomHeadlessExecutionContext,\n ) => executeHeadlessRead(params, context.cwd, signal),\n };\n}\n","import { defineMcpTool } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineMcpTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineMcpPlugin, type DoomMcpSessionPlugin } from '@agimon-ai/doompi-core/mcpFacet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.mcp';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const mcp = defineMcpPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomMcpSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }) satisfies DoomMcpSessionPlugin,\n});\n\nexport default mcp;\n"],"mappings":"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"}
@@ -2,16 +2,75 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_read_cli = require("../src/extensions/workspaces/sessions/(backend)/tool/read.cli.cjs");
6
- const require_read_cli$1 = require("../src/extensions/workspaces/sessions/(frontend)/tool/read.cli.cjs");
7
- let _agimon_ai_doompi_core_pi_extension = require("@agimon-ai/doompi-core/pi-extension");
5
+ const require_readTool = require("../readTool-D_FT80m9.cjs");
6
+ let node_fs_promises = require("node:fs/promises");
7
+ let _agimon_ai_doompi_hashline_files = require("@agimon-ai/doompi-hashline/files");
8
+ let _earendil_works_pi_coding_agent = require("@earendil-works/pi-coding-agent");
9
+ let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
10
+ let _agimon_ai_doompi_ui_hashlineRendering = require("@agimon-ai/doompi-ui/hashlineRendering");
11
+ //#region src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.ts
12
+ const resizeOperations = {
13
+ resize: _earendil_works_pi_coding_agent.resizeImage,
14
+ formatDimensionNote: (result) => (0, _earendil_works_pi_coding_agent.formatDimensionNote)(result)
15
+ };
16
+ function createHashlineReadTool(writable = _agimon_ai_doompi_hashline_files.isWritableFile) {
17
+ return {
18
+ name: "read",
19
+ label: "read",
20
+ description: `Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images retain Pi's native behavior. Text is truncated to ${(0, _earendil_works_pi_coding_agent.formatSize)(_earendil_works_pi_coding_agent.DEFAULT_MAX_BYTES)}.`,
21
+ promptSnippet: "Read file contents with snapshot-bound line anchors",
22
+ promptGuidelines: ["Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.", "Continue large reads with offset until the required anchored lines are visible."],
23
+ parameters: require_readTool.ReadParamsSchema,
24
+ executionMode: "parallel",
25
+ async execute(toolCallId, params, signal, onUpdate, ctx) {
26
+ const input = params;
27
+ require_readTool.assertNotAborted(signal);
28
+ const absolutePath = await (0, _agimon_ai_doompi_hashline_files.resolveReadInputPath)(input.path, ctx.cwd);
29
+ const nativeResult = await (0, _earendil_works_pi_coding_agent.createReadToolDefinition)(ctx.cwd, { autoResizeImages: false }).execute(toolCallId, {
30
+ ...input,
31
+ path: absolutePath
32
+ }, signal, onUpdate, ctx);
33
+ if (require_readTool.isImageRead(nativeResult.content)) {
34
+ require_readTool.assertNotAborted(signal);
35
+ return {
36
+ ...nativeResult,
37
+ content: await require_readTool.applyImageLimits(nativeResult.content, require_readTool.imageLimits(), resizeOperations)
38
+ };
39
+ }
40
+ require_readTool.assertNotAborted(signal);
41
+ const canEdit = await writable(absolutePath);
42
+ require_readTool.assertNotAborted(signal);
43
+ if (!canEdit) return nativeResult;
44
+ const bytes = await (0, node_fs_promises.readFile)(absolutePath);
45
+ require_readTool.assertNotAborted(signal);
46
+ return require_readTool.createTaggedReadResult(bytes, (0, _agimon_ai_doompi_hashline_files.displayPath)(absolutePath, ctx.cwd), input);
47
+ }
48
+ };
49
+ }
50
+ //#endregion
51
+ //#region src/extensions/workspaces/sessions/(backend)/tool/read.cli.ts
52
+ var read_cli_default$1 = (0, _agimon_ai_doompi_core_piExtension.definePiTool)(createHashlineReadTool(), { overrides: true });
53
+ //#endregion
54
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/read.cli.ts
55
+ var read_cli_default = (0, _agimon_ai_doompi_core_piExtension.definePiToolRenderer)({
56
+ renderShell: "self",
57
+ renderCall(args, theme) {
58
+ const input = args;
59
+ const details = [input.offset === void 0 ? void 0 : `from ${input.offset}`, input.limit === void 0 ? void 0 : `${input.limit} lines`].filter((value) => value !== void 0);
60
+ return (0, _agimon_ai_doompi_ui_hashlineRendering.renderHashlineCall)("read", input.path, details, theme);
61
+ },
62
+ renderResult(result, options, theme, context) {
63
+ return (0, _agimon_ai_doompi_ui_hashlineRendering.renderHashlineResult)(result, options, theme, context, "read");
64
+ }
65
+ });
66
+ //#endregion
8
67
  //#region generated/pi.ts
9
68
  const at = (value, context) => typeof value === "function" ? value(context) : value;
10
69
  const via = (identity, value) => ({
11
70
  ...identity,
12
71
  ...value
13
72
  });
14
- const extension = (0, _agimon_ai_doompi_core_pi_extension.definePiExtension)("@agimon-ai/doompi-read", (context) => ({ ...(0, _agimon_ai_doompi_core_pi_extension.piToolContributions)("@agimon-ai/doompi-read", [via({ name: "read" }, (0, _agimon_ai_doompi_core_pi_extension.withPiRenderers)(at(require_read_cli.default, context), at(require_read_cli$1.default, context)))]) }));
73
+ const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-read", (context) => ({ ...(0, _agimon_ai_doompi_core_piExtension.piToolContributions)("@agimon-ai/doompi-read", [via({ name: "read" }, (0, _agimon_ai_doompi_core_piExtension.withPiRenderers)(at(read_cli_default$1, context), at(read_cli_default, context)))]) }));
15
74
  //#endregion
16
75
  exports.default = extension;
17
76
  exports.extension = extension;
@@ -1 +1 @@
1
- {"version":3,"file":"pi.cjs","names":["definePiExtension","piToolContributions","withPiRenderers","toolRead","renderRead"],"sources":["../../generated/pi.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, withPiRenderers, type PiPluginContext } from '@agimon-ai/doompi-core/pi-extension';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.cli';\nimport renderRead from '../src/extensions/workspaces/sessions/(frontend)/tool/read.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof toolRead>, 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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-read', (context) => ({\n ...piToolContributions('@agimon-ai/doompi-read', [via({ name: 'read' }, withPiRenderers(at(toolRead, context), at(renderRead, context)))]),\n}));\n\nexport default extension;\n"],"mappings":";;;;;;;;AAaA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,aAAA,GAAYA,oCAAAA,kBAAAA,CAAoC,2BAA2B,aAAa,EACnG,IAAA,GAAGC,oCAAAA,oBAAAA,CAAoB,0BAA0B,CAAC,IAAI,EAAE,MAAM,OAAO,IAAA,GAAGC,oCAAAA,gBAAAA,CAAgB,GAAGC,iBAAAA,SAAU,OAAO,GAAG,GAAGC,mBAAAA,SAAY,OAAO,CAAC,CAAC,CAAC,CAAC,EAC3I,EAAE"}
1
+ {"version":3,"file":"pi.cjs","names":["resizeImage","formatDimensionNote","isWritableFile","formatSize","DEFAULT_MAX_BYTES","ReadParamsSchema","resolveReadInputPath","createReadToolDefinition","isImageRead","applyImageLimits","imageLimits","readFile","createTaggedReadResult","displayPath","definePiTool","renderHashlineCall","renderHashlineResult","definePiToolRenderer","definePiExtension","piToolContributions","withPiRenderers","toolRead","renderRead"],"sources":["../../src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.cli.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/read.cli.ts","../../generated/pi.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport { isWritableFile, displayPath, resolveReadInputPath } from '@agimon-ai/doompi-hashline/files';\nimport {\n createReadToolDefinition,\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n type AgentToolResult,\n type ToolDefinition,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../../../../../schemas/readTool';\nimport { applyImageLimits, imageLimits, type ReadImageResizeOperations } from '../../../../../../services/readImage';\nimport { assertNotAborted, createTaggedReadResult, isImageRead } from '../../../../../../services/readTool';\n\ntype WritableCheck = (path: string) => Promise<boolean>;\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport function createHashlineReadTool(\n writable: WritableCheck = isWritableFile,\n): ToolDefinition<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description: `Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images retain Pi's native behavior. Text is truncated to ${formatSize(DEFAULT_MAX_BYTES)}.`,\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n async execute(toolCallId, params, signal, onUpdate, ctx) {\n const input = params as ReadParams;\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(input.path, ctx.cwd);\n const nativeRead = createReadToolDefinition(ctx.cwd, { autoResizeImages: false });\n const nativeResult = await nativeRead.execute(\n toolCallId,\n { ...input, path: absolutePath },\n signal,\n onUpdate,\n ctx,\n );\n if (isImageRead(nativeResult.content)) {\n assertNotAborted(signal);\n return {\n ...nativeResult,\n content: await applyImageLimits(nativeResult.content, imageLimits(), resizeOperations),\n };\n }\n\n assertNotAborted(signal);\n const canEdit = await writable(absolutePath);\n assertNotAborted(signal);\n if (!canEdit) return nativeResult;\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n return createTaggedReadResult(\n bytes,\n displayPath(absolutePath, ctx.cwd),\n input,\n ) as unknown as AgentToolResult<unknown>;\n },\n };\n}\n","import { definePiTool } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createHashlineReadTool } from './_lib/readTool';\n\nexport default definePiTool(createHashlineReadTool(), { overrides: true });\n","import type { PiToolRenderers } from '@agimon-ai/doompi-core/piExtension';\nimport { renderHashlineCall, renderHashlineResult } from '@agimon-ai/doompi-ui/hashlineRendering';\n\nimport { ReadParamsSchema, type ReadParams } from '../../../../../../schemas/readTool';\n\nexport const readRenderer: PiToolRenderers<typeof ReadParamsSchema> = {\n renderShell: 'self',\n renderCall(args, theme) {\n const input = args as ReadParams;\n const details = [\n input.offset === undefined ? undefined : `from ${input.offset}`,\n input.limit === undefined ? undefined : `${input.limit} lines`,\n ].filter((value): value is string => value !== undefined);\n return renderHashlineCall('read', input.path, details, theme);\n },\n renderResult(result, options, theme, context) {\n return renderHashlineResult(result, options, theme, context, 'read');\n },\n};\n","import { definePiToolRenderer } from '@agimon-ai/doompi-core/piExtension';\n\nimport { readRenderer } from './_lib/readRenderer.cli';\n\nexport default definePiToolRenderer(readRenderer);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, withPiRenderers, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.cli';\nimport renderRead from '../src/extensions/workspaces/sessions/(frontend)/tool/read.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof toolRead>, 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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-read', (context) => ({\n ...piToolContributions('@agimon-ai/doompi-read', [via({ name: 'read' }, withPiRenderers(at(toolRead, context), at(renderRead, context)))]),\n}));\n\nexport default extension;\n"],"mappings":";;;;;;;;;;;AAmBA,MAAM,mBAA8C;CAClD,QAAQA,gCAAAA;CACR,sBAAsB,YAAA,GAAWC,gCAAAA,oBAAAA,CAAoB,MAAM;AAC7D;AAEA,SAAgB,uBACd,WAA0BC,iCAAAA,gBACe;CACzC,OAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa,mKAAA,GAAkKC,gCAAAA,WAAAA,CAAWC,gCAAAA,iBAAiB,EAAE;EAC7M,eAAe;EACf,kBAAkB,CAChB,uHACA,iFACF;EACA,YAAYC,iBAAAA;EACZ,eAAe;EACf,MAAM,QAAQ,YAAY,QAAQ,QAAQ,UAAU,KAAK;GACvD,MAAM,QAAQ;GACd,iBAAA,iBAAiB,MAAM;GACvB,MAAM,eAAe,OAAA,GAAMC,iCAAAA,qBAAAA,CAAqB,MAAM,MAAM,IAAI,GAAG;GAEnE,MAAM,eAAe,OAAA,GADFC,gCAAAA,yBAAAA,CAAyB,IAAI,KAAK,EAAE,kBAAkB,MAAM,CAC3C,CAAC,CAAC,QACpC,YACA;IAAE,GAAG;IAAO,MAAM;GAAa,GAC/B,QACA,UACA,GACF;GACA,IAAIC,iBAAAA,YAAY,aAAa,OAAO,GAAG;IACrC,iBAAA,iBAAiB,MAAM;IACvB,OAAO;KACL,GAAG;KACH,SAAS,MAAMC,iBAAAA,iBAAiB,aAAa,SAASC,iBAAAA,YAAY,GAAG,gBAAgB;IACvF;GACF;GAEA,iBAAA,iBAAiB,MAAM;GACvB,MAAM,UAAU,MAAM,SAAS,YAAY;GAC3C,iBAAA,iBAAiB,MAAM;GACvB,IAAI,CAAC,SAAS,OAAO;GACrB,MAAM,QAAQ,OAAA,GAAMC,iBAAAA,SAAAA,CAAS,YAAY;GACzC,iBAAA,iBAAiB,MAAM;GACvB,OAAOC,iBAAAA,uBACL,QAAA,GACAC,iCAAAA,YAAAA,CAAY,cAAc,IAAI,GAAG,GACjC,KACF;EACF;CACF;AACF;;;ACnEA,IAAA,sBAAA,GAAeC,mCAAAA,aAAAA,CAAa,uBAAuB,GAAG,EAAE,WAAW,KAAK,CAAC;;;AEAzE,IAAA,oBAAA,GAAeG,mCAAAA,qBAAAA,CAAqB;CDElC,aAAa;CACb,WAAW,MAAM,OAAO;EACtB,MAAM,QAAQ;EACd,MAAM,UAAU,CACd,MAAM,WAAW,KAAA,IAAY,KAAA,IAAY,QAAQ,MAAM,UACvD,MAAM,UAAU,KAAA,IAAY,KAAA,IAAY,GAAG,MAAM,MAAM,OACzD,CAAC,CAAC,QAAQ,UAA2B,UAAU,KAAA,CAAS;EACxD,QAAA,GAAOF,uCAAAA,mBAAAA,CAAmB,QAAQ,MAAM,MAAM,SAAS,KAAK;CAC9D;CACA,aAAa,QAAQ,SAAS,OAAO,SAAS;EAC5C,QAAA,GAAOC,uCAAAA,qBAAAA,CAAqB,QAAQ,SAAS,OAAO,SAAS,MAAM;CACrE;ACbkC,CAAY;;;ACShD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,aAAA,GAAYE,mCAAAA,kBAAAA,CAAoC,2BAA2B,aAAa,EACnG,IAAA,GAAGC,mCAAAA,oBAAAA,CAAoB,0BAA0B,CAAC,IAAI,EAAE,MAAM,OAAO,IAAA,GAAGC,mCAAAA,gBAAAA,CAAgB,GAAGC,oBAAU,OAAO,GAAG,GAAGC,kBAAY,OAAO,CAAC,CAAC,CAAC,CAAC,EAC3I,EAAE"}
@@ -1,5 +1,5 @@
1
1
  //#region generated/pi.d.ts
2
- export declare const extension: import("@agimon-ai/doompi-core/runtime-pi-extension").DefinedPiExtension<undefined>;
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":";qBAiBa,iEAAS"}
1
+ {"version":3,"file":"pi.d.mts","names":[],"sources":["../../generated/pi.ts"],"mappings":";qBAiBa,+DAAS"}
@@ -1,13 +1,72 @@
1
- import read_cli_default from "../src/extensions/workspaces/sessions/(backend)/tool/read.cli.mjs";
2
- import read_cli_default$1 from "../src/extensions/workspaces/sessions/(frontend)/tool/read.cli.mjs";
3
- import { definePiExtension, piToolContributions, withPiRenderers } from "@agimon-ai/doompi-core/pi-extension";
1
+ import { a as isImageRead, c as ReadParamsSchema, o as applyImageLimits, r as createTaggedReadResult, s as imageLimits, t as assertNotAborted } from "../readTool-CAFWYKUX.mjs";
2
+ import { readFile } from "node:fs/promises";
3
+ import { displayPath, isWritableFile, resolveReadInputPath } from "@agimon-ai/doompi-hashline/files";
4
+ import { DEFAULT_MAX_BYTES, createReadToolDefinition, formatDimensionNote, formatSize, resizeImage } from "@earendil-works/pi-coding-agent";
5
+ import { definePiExtension, definePiTool, definePiToolRenderer, piToolContributions, withPiRenderers } from "@agimon-ai/doompi-core/piExtension";
6
+ import { renderHashlineCall, renderHashlineResult } from "@agimon-ai/doompi-ui/hashlineRendering";
7
+ //#region src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.ts
8
+ const resizeOperations = {
9
+ resize: resizeImage,
10
+ formatDimensionNote: (result) => formatDimensionNote(result)
11
+ };
12
+ function createHashlineReadTool(writable = isWritableFile) {
13
+ return {
14
+ name: "read",
15
+ label: "read",
16
+ description: `Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images retain Pi's native behavior. Text is truncated to ${formatSize(DEFAULT_MAX_BYTES)}.`,
17
+ promptSnippet: "Read file contents with snapshot-bound line anchors",
18
+ promptGuidelines: ["Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.", "Continue large reads with offset until the required anchored lines are visible."],
19
+ parameters: ReadParamsSchema,
20
+ executionMode: "parallel",
21
+ async execute(toolCallId, params, signal, onUpdate, ctx) {
22
+ const input = params;
23
+ assertNotAborted(signal);
24
+ const absolutePath = await resolveReadInputPath(input.path, ctx.cwd);
25
+ const nativeResult = await createReadToolDefinition(ctx.cwd, { autoResizeImages: false }).execute(toolCallId, {
26
+ ...input,
27
+ path: absolutePath
28
+ }, signal, onUpdate, ctx);
29
+ if (isImageRead(nativeResult.content)) {
30
+ assertNotAborted(signal);
31
+ return {
32
+ ...nativeResult,
33
+ content: await applyImageLimits(nativeResult.content, imageLimits(), resizeOperations)
34
+ };
35
+ }
36
+ assertNotAborted(signal);
37
+ const canEdit = await writable(absolutePath);
38
+ assertNotAborted(signal);
39
+ if (!canEdit) return nativeResult;
40
+ const bytes = await readFile(absolutePath);
41
+ assertNotAborted(signal);
42
+ return createTaggedReadResult(bytes, displayPath(absolutePath, ctx.cwd), input);
43
+ }
44
+ };
45
+ }
46
+ //#endregion
47
+ //#region src/extensions/workspaces/sessions/(backend)/tool/read.cli.ts
48
+ var read_cli_default$1 = definePiTool(createHashlineReadTool(), { overrides: true });
49
+ //#endregion
50
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/read.cli.ts
51
+ var read_cli_default = definePiToolRenderer({
52
+ renderShell: "self",
53
+ renderCall(args, theme) {
54
+ const input = args;
55
+ const details = [input.offset === void 0 ? void 0 : `from ${input.offset}`, input.limit === void 0 ? void 0 : `${input.limit} lines`].filter((value) => value !== void 0);
56
+ return renderHashlineCall("read", input.path, details, theme);
57
+ },
58
+ renderResult(result, options, theme, context) {
59
+ return renderHashlineResult(result, options, theme, context, "read");
60
+ }
61
+ });
62
+ //#endregion
4
63
  //#region generated/pi.ts
5
64
  const at = (value, context) => typeof value === "function" ? value(context) : value;
6
65
  const via = (identity, value) => ({
7
66
  ...identity,
8
67
  ...value
9
68
  });
10
- const extension = definePiExtension("@agimon-ai/doompi-read", (context) => ({ ...piToolContributions("@agimon-ai/doompi-read", [via({ name: "read" }, withPiRenderers(at(read_cli_default, context), at(read_cli_default$1, context)))]) }));
69
+ const extension = definePiExtension("@agimon-ai/doompi-read", (context) => ({ ...piToolContributions("@agimon-ai/doompi-read", [via({ name: "read" }, withPiRenderers(at(read_cli_default$1, context), at(read_cli_default, context)))]) }));
11
70
  //#endregion
12
71
  export { extension as default, extension };
13
72
 
@@ -1 +1 @@
1
- {"version":3,"file":"pi.mjs","names":["toolRead","renderRead"],"sources":["../../generated/pi.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, withPiRenderers, type PiPluginContext } from '@agimon-ai/doompi-core/pi-extension';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.cli';\nimport renderRead from '../src/extensions/workspaces/sessions/(frontend)/tool/read.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof toolRead>, 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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-read', (context) => ({\n ...piToolContributions('@agimon-ai/doompi-read', [via({ name: 'read' }, withPiRenderers(at(toolRead, context), at(renderRead, context)))]),\n}));\n\nexport default extension;\n"],"mappings":";;;;AAaA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,YAAY,kBAAoC,2BAA2B,aAAa,EACnG,GAAG,oBAAoB,0BAA0B,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,gBAAgB,GAAGA,kBAAU,OAAO,GAAG,GAAGC,oBAAY,OAAO,CAAC,CAAC,CAAC,CAAC,EAC3I,EAAE"}
1
+ {"version":3,"file":"pi.mjs","names":["toolRead","renderRead"],"sources":["../../src/extensions/workspaces/sessions/(backend)/tool/_lib/readTool.ts","../../src/extensions/workspaces/sessions/(backend)/tool/read.cli.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/readRenderer.cli.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/read.cli.ts","../../generated/pi.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\n\nimport { isWritableFile, displayPath, resolveReadInputPath } from '@agimon-ai/doompi-hashline/files';\nimport {\n createReadToolDefinition,\n DEFAULT_MAX_BYTES,\n formatDimensionNote,\n formatSize,\n resizeImage,\n type AgentToolResult,\n type ToolDefinition,\n} from '@earendil-works/pi-coding-agent';\n\nimport { ReadParamsSchema, type ReadParams } from '../../../../../../schemas/readTool';\nimport { applyImageLimits, imageLimits, type ReadImageResizeOperations } from '../../../../../../services/readImage';\nimport { assertNotAborted, createTaggedReadResult, isImageRead } from '../../../../../../services/readTool';\n\ntype WritableCheck = (path: string) => Promise<boolean>;\n\nconst resizeOperations: ReadImageResizeOperations = {\n resize: resizeImage,\n formatDimensionNote: (result) => formatDimensionNote(result),\n};\n\nexport function createHashlineReadTool(\n writable: WritableCheck = isWritableFile,\n): ToolDefinition<typeof ReadParamsSchema> {\n return {\n name: 'read',\n label: 'read',\n description: `Read a writable text file with an exact-byte file tag and stable line anchors. Non-writable files and images retain Pi's native behavior. Text is truncated to ${formatSize(DEFAULT_MAX_BYTES)}.`,\n promptSnippet: 'Read file contents with snapshot-bound line anchors',\n promptGuidelines: [\n 'Use read before edit. When hashline metadata is present, preserve the @file hash and anchors such as 5#abc exactly.',\n 'Continue large reads with offset until the required anchored lines are visible.',\n ],\n parameters: ReadParamsSchema,\n executionMode: 'parallel',\n async execute(toolCallId, params, signal, onUpdate, ctx) {\n const input = params as ReadParams;\n assertNotAborted(signal);\n const absolutePath = await resolveReadInputPath(input.path, ctx.cwd);\n const nativeRead = createReadToolDefinition(ctx.cwd, { autoResizeImages: false });\n const nativeResult = await nativeRead.execute(\n toolCallId,\n { ...input, path: absolutePath },\n signal,\n onUpdate,\n ctx,\n );\n if (isImageRead(nativeResult.content)) {\n assertNotAborted(signal);\n return {\n ...nativeResult,\n content: await applyImageLimits(nativeResult.content, imageLimits(), resizeOperations),\n };\n }\n\n assertNotAborted(signal);\n const canEdit = await writable(absolutePath);\n assertNotAborted(signal);\n if (!canEdit) return nativeResult;\n const bytes = await readFile(absolutePath);\n assertNotAborted(signal);\n return createTaggedReadResult(\n bytes,\n displayPath(absolutePath, ctx.cwd),\n input,\n ) as unknown as AgentToolResult<unknown>;\n },\n };\n}\n","import { definePiTool } from '@agimon-ai/doompi-core/piExtension';\n\nimport { createHashlineReadTool } from './_lib/readTool';\n\nexport default definePiTool(createHashlineReadTool(), { overrides: true });\n","import type { PiToolRenderers } from '@agimon-ai/doompi-core/piExtension';\nimport { renderHashlineCall, renderHashlineResult } from '@agimon-ai/doompi-ui/hashlineRendering';\n\nimport { ReadParamsSchema, type ReadParams } from '../../../../../../schemas/readTool';\n\nexport const readRenderer: PiToolRenderers<typeof ReadParamsSchema> = {\n renderShell: 'self',\n renderCall(args, theme) {\n const input = args as ReadParams;\n const details = [\n input.offset === undefined ? undefined : `from ${input.offset}`,\n input.limit === undefined ? undefined : `${input.limit} lines`,\n ].filter((value): value is string => value !== undefined);\n return renderHashlineCall('read', input.path, details, theme);\n },\n renderResult(result, options, theme, context) {\n return renderHashlineResult(result, options, theme, context, 'read');\n },\n};\n","import { definePiToolRenderer } from '@agimon-ai/doompi-core/piExtension';\n\nimport { readRenderer } from './_lib/readRenderer.cli';\n\nexport default definePiToolRenderer(readRenderer);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { definePiExtension, piToolContributions, withPiRenderers, type PiPluginContext } from '@agimon-ai/doompi-core/piExtension';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.cli';\nimport renderRead from '../src/extensions/workspaces/sessions/(frontend)/tool/read.cli';\n\ntype OptionsOf<T> = T extends (context: PiPluginContext<infer Options>) => unknown ? Options : never;\ntype InferredOptions = Exclude<OptionsOf<typeof toolRead>, 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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const extension = definePiExtension<ExtensionOptions>('@agimon-ai/doompi-read', (context) => ({\n ...piToolContributions('@agimon-ai/doompi-read', [via({ name: 'read' }, withPiRenderers(at(toolRead, context), at(renderRead, context)))]),\n}));\n\nexport default extension;\n"],"mappings":";;;;;;;AAmBA,MAAM,mBAA8C;CAClD,QAAQ;CACR,sBAAsB,WAAW,oBAAoB,MAAM;AAC7D;AAEA,SAAgB,uBACd,WAA0B,gBACe;CACzC,OAAO;EACL,MAAM;EACN,OAAO;EACP,aAAa,kKAAkK,WAAW,iBAAiB,EAAE;EAC7M,eAAe;EACf,kBAAkB,CAChB,uHACA,iFACF;EACA,YAAY;EACZ,eAAe;EACf,MAAM,QAAQ,YAAY,QAAQ,QAAQ,UAAU,KAAK;GACvD,MAAM,QAAQ;GACd,iBAAiB,MAAM;GACvB,MAAM,eAAe,MAAM,qBAAqB,MAAM,MAAM,IAAI,GAAG;GAEnE,MAAM,eAAe,MADF,yBAAyB,IAAI,KAAK,EAAE,kBAAkB,MAAM,CAC3C,CAAC,CAAC,QACpC,YACA;IAAE,GAAG;IAAO,MAAM;GAAa,GAC/B,QACA,UACA,GACF;GACA,IAAI,YAAY,aAAa,OAAO,GAAG;IACrC,iBAAiB,MAAM;IACvB,OAAO;KACL,GAAG;KACH,SAAS,MAAM,iBAAiB,aAAa,SAAS,YAAY,GAAG,gBAAgB;IACvF;GACF;GAEA,iBAAiB,MAAM;GACvB,MAAM,UAAU,MAAM,SAAS,YAAY;GAC3C,iBAAiB,MAAM;GACvB,IAAI,CAAC,SAAS,OAAO;GACrB,MAAM,QAAQ,MAAM,SAAS,YAAY;GACzC,iBAAiB,MAAM;GACvB,OAAO,uBACL,OACA,YAAY,cAAc,IAAI,GAAG,GACjC,KACF;EACF;CACF;AACF;;;ACnEA,IAAA,qBAAe,aAAa,uBAAuB,GAAG,EAAE,WAAW,KAAK,CAAC;;;AEAzE,IAAA,mBAAe,qBAAqB;CDElC,aAAa;CACb,WAAW,MAAM,OAAO;EACtB,MAAM,QAAQ;EACd,MAAM,UAAU,CACd,MAAM,WAAW,KAAA,IAAY,KAAA,IAAY,QAAQ,MAAM,UACvD,MAAM,UAAU,KAAA,IAAY,KAAA,IAAY,GAAG,MAAM,MAAM,OACzD,CAAC,CAAC,QAAQ,UAA2B,UAAU,KAAA,CAAS;EACxD,OAAO,mBAAmB,QAAQ,MAAM,MAAM,SAAS,KAAK;CAC9D;CACA,aAAa,QAAQ,SAAS,OAAO,SAAS;EAC5C,OAAO,qBAAqB,QAAQ,SAAS,OAAO,SAAS,MAAM;CACrE;ACbkC,CAAY;;;ACShD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,YAAY,kBAAoC,2BAA2B,aAAa,EACnG,GAAG,oBAAoB,0BAA0B,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,gBAAgB,GAAGA,oBAAU,OAAO,GAAG,GAAGC,kBAAY,OAAO,CAAC,CAAC,CAAC,CAAC,EAC3I,EAAE"}
@@ -2,18 +2,21 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_read_server = require("../src/extensions/workspaces/sessions/(backend)/tool/read.server.cjs");
6
- let _agimon_ai_doompi_core_server_facet = require("@agimon-ai/doompi-core/server-facet");
5
+ const require_readTool = require("../readTool-D_FT80m9.cjs");
6
+ let _agimon_ai_doompi_core_serverFacet = require("@agimon-ai/doompi-core/serverFacet");
7
+ //#region src/extensions/workspaces/sessions/(backend)/tool/read.server.ts
8
+ var read_server_default = (0, require("@agimon-ai/doompi-core/extensionFile").defineServerTool)(require_readTool.createHeadlessReadTool);
9
+ //#endregion
7
10
  //#region generated/server.ts
8
11
  const at = (value, context) => typeof value === "function" ? value(context) : value;
9
12
  const via = (identity, value) => ({
10
13
  ...identity,
11
14
  ...value
12
15
  });
13
- const facet = (0, _agimon_ai_doompi_core_server_facet.defineServerPlugin)({
16
+ const facet = (0, _agimon_ai_doompi_core_serverFacet.defineServerPlugin)({
14
17
  name: "@agimon-ai/doompi-read",
15
18
  session: (context) => ({ get tools() {
16
- return [via({ name: "read" }, at(require_read_server.default, context))];
19
+ return [via({ name: "read" }, at(read_server_default, context))];
17
20
  } })
18
21
  });
19
22
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"server.cjs","names":["defineServerPlugin","toolRead"],"sources":["../../generated/server.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.server';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;;;;;AAMA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,SAAA,GAAQA,oCAAAA,mBAAAA,CAAmB;CACtC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,QAA0C;EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,GAAGC,oBAAAA,SAAU,OAAO,CAAC,CAAC;CAAG,EACzG;AACF,CAAC"}
1
+ {"version":3,"file":"server.cjs","names":["defineServerTool","createHeadlessReadTool","defineServerPlugin","toolRead"],"sources":["../../src/extensions/workspaces/sessions/(backend)/tool/read.server.ts","../../generated/server.ts"],"sourcesContent":["import { defineServerTool } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineServerTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.server';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;;;;;AAIA,IAAA,uBAAA,iDAAeA,CAAAA,CAAAA,iBAAAA,CAAiBC,iBAAAA,sBAAsB;;;ACEtD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,SAAA,GAAQC,mCAAAA,mBAAAA,CAAmB;CACtC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,QAA0C;EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,GAAGC,qBAAU,OAAO,CAAC,CAAC;CAAG,EACzG;AACF,CAAC"}
@@ -1,5 +1,5 @@
1
1
  //#region generated/server.d.ts
2
- export declare const facet: import("@agimon-ai/doompi-core/server-facet").DoomServerFacet;
2
+ export declare const facet: import("@agimon-ai/doompi-core/serverFacet").DoomServerFacet;
3
3
  //#endregion
4
4
  export { facet as default };
5
5
  //# sourceMappingURL=server.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAUa,qDAAK"}
1
+ {"version":3,"file":"server.d.mts","names":[],"sources":["../../generated/server.ts"],"mappings":";qBAUa,oDAAK"}
@@ -1,5 +1,9 @@
1
- import read_server_default from "../src/extensions/workspaces/sessions/(backend)/tool/read.server.mjs";
2
- import { defineServerPlugin } from "@agimon-ai/doompi-core/server-facet";
1
+ import { n as createHeadlessReadTool } from "../readTool-CAFWYKUX.mjs";
2
+ import { defineServerPlugin } from "@agimon-ai/doompi-core/serverFacet";
3
+ import { defineServerTool } from "@agimon-ai/doompi-core/extensionFile";
4
+ //#region src/extensions/workspaces/sessions/(backend)/tool/read.server.ts
5
+ var read_server_default = defineServerTool(createHeadlessReadTool);
6
+ //#endregion
3
7
  //#region generated/server.ts
4
8
  const at = (value, context) => typeof value === "function" ? value(context) : value;
5
9
  const via = (identity, value) => ({
@@ -1 +1 @@
1
- {"version":3,"file":"server.mjs","names":["toolRead"],"sources":["../../generated/server.ts"],"sourcesContent":["// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/server-facet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.server';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;AAMA,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,QAAQ,mBAAmB;CACtC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,QAA0C;EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,GAAGA,qBAAU,OAAO,CAAC,CAAC;CAAG,EACzG;AACF,CAAC"}
1
+ {"version":3,"file":"server.mjs","names":["toolRead"],"sources":["../../src/extensions/workspaces/sessions/(backend)/tool/read.server.ts","../../generated/server.ts"],"sourcesContent":["import { defineServerTool } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createHeadlessReadTool } from '../../../../../services/readTool';\n\nexport default defineServerTool(createHeadlessReadTool);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\n\nimport toolRead from '../src/extensions/workspaces/sessions/(backend)/tool/read.server';\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;\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T => ({ ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-read',\n session: (context) => ({\n get tools(): DoomServerSessionPlugin['tools'] { return [via({ name: 'read' }, at(toolRead, context))]; },\n }),\n});\n\nexport default facet;\n"],"mappings":";;;;AAIA,IAAA,sBAAe,iBAAiB,sBAAsB;;;ACEtD,MAAM,MAAY,OAA0B,YAC1C,OAAO,UAAU,aAAc,MAAwB,OAAO,IAAI;AACpE,MAAM,OAAU,UAAmC,WAAuB;CAAE,GAAG;CAAU,GAAI;AAAiB;AAE9G,MAAa,QAAQ,mBAAmB;CACtC,MAAM;CACN,UAAU,aAAa,EACrB,IAAI,QAA0C;EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,OAAO,GAAG,GAAGA,qBAAU,OAAO,CAAC,CAAC;CAAG,EACzG;AACF,CAAC"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_readTool = require("./src/schemas/readTool.cjs");
3
- const require_index = require("./src/services/readTool/index.cjs");
2
+ const require_readTool = require("./readTool-D_FT80m9.cjs");
4
3
  exports.ReadParamsSchema = require_readTool.ReadParamsSchema;
5
- exports.createHeadlessReadTool = require_index.createHeadlessReadTool;
6
- exports.executeHeadlessRead = require_index.executeHeadlessRead;
4
+ exports.createHeadlessReadTool = require_readTool.createHeadlessReadTool;
5
+ exports.executeHeadlessRead = require_readTool.executeHeadlessRead;
package/dist/index.d.mts CHANGED
@@ -1,3 +1,34 @@
1
- import { ReadParams, ReadParamsSchema } from "./src/schemas/readTool.mjs";
2
- import { createHeadlessReadTool, executeHeadlessRead } from "./src/services/readTool/index.mjs";
3
- export { type ReadParams, ReadParamsSchema, createHeadlessReadTool, executeHeadlessRead };
1
+ import { ReadToolDetails } from "@earendil-works/pi-coding-agent";
2
+ import { Static, Type } from "typebox";
3
+ import "@agimon-ai/doompi-config/piConfig";
4
+ import { DoomHeadlessTool } from "@agimon-ai/doompi-core/headless";
5
+ //#region src/schemas/readTool.d.ts
6
+ export declare const ReadParamsSchema: Type.TObject<{
7
+ path: Type.TString;
8
+ offset: Type.TOptional<Type.TInteger>;
9
+ limit: Type.TOptional<Type.TInteger>;
10
+ }>;
11
+ type ReadParams = Static<typeof ReadParamsSchema>;
12
+ //#endregion
13
+ //#region src/services/readImage/index.d.ts
14
+ interface ReadTextPart {
15
+ type: 'text';
16
+ text: string;
17
+ }
18
+ interface ReadImagePart {
19
+ type: 'image';
20
+ data: string;
21
+ mimeType: string;
22
+ }
23
+ type ReadContentPart = ReadTextPart | ReadImagePart;
24
+ //#endregion
25
+ //#region src/services/readTool/index.d.ts
26
+ interface ReadToolResult {
27
+ content: ReadContentPart[];
28
+ details?: ReadToolDetails;
29
+ }
30
+ export declare function executeHeadlessRead(params: ReadParams, cwd: string, signal: AbortSignal | undefined): Promise<ReadToolResult>;
31
+ export declare function createHeadlessReadTool(): DoomHeadlessTool<typeof ReadParamsSchema>;
32
+ //#endregion
33
+ export type { ReadParams };
34
+ //# sourceMappingURL=index.d.mts.map