@arnilo/prism-coding-agent 0.0.19 → 0.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,6 +3,8 @@ export type { AskUserDecisionAnswer, AskUserDecisionHandler, AskUserDecisionOpti
3
3
  export { ASK_USER_DECISION_RATIONALE_COUNT, ASK_USER_DECISION_SUSPEND_REASON, ASK_USER_DECISION_TOOL_NAME, askUserDecisionResumeSchema, createAskUserDecisionResumeValidator, createAskUserDecisionTool, DEFAULT_MAX_ASK_USER_DECISION_BULLET_BYTES, DEFAULT_MAX_ASK_USER_DECISION_CUSTOM_BYTES, DEFAULT_MAX_ASK_USER_DECISION_LABEL_BYTES, DEFAULT_MAX_ASK_USER_DECISION_OPTIONS, DEFAULT_MAX_ASK_USER_DECISION_QUESTION_BYTES, HARD_MAX_ASK_USER_DECISION_BULLET_BYTES, HARD_MAX_ASK_USER_DECISION_CUSTOM_BYTES, HARD_MAX_ASK_USER_DECISION_LABEL_BYTES, HARD_MAX_ASK_USER_DECISION_OPTIONS, HARD_MAX_ASK_USER_DECISION_QUESTION_BYTES, parseAskUserDecisionArgs, resolveAskUserDecisionAnswer, resolveAskUserDecisionLimits, suspendAskUserDecision, toAskUserDecisionSuspendData, validateAskUserDecisionAgentResume, validateAskUserDecisionResume, } from "./ask-user-decision.js";
4
4
  export type { CodingCheckToolOptions, NamedCheckDefinition } from "./checks.js";
5
5
  export { createCodingCheckTool } from "./checks.js";
6
+ export type { DeleteOperations, DeleteToolOptions, MutationStat } from "./delete.js";
7
+ export { createDeleteTool } from "./delete.js";
6
8
  export type { CodingArtifactKind, CodingArtifactRef, CodingCheckpointLimitOptions, CodingCheckpointMetadata, CodingCheckSummary, CodingFingerprints, CodingHandoffSummary, CodingTaskStatus, CodingTodoItem, ResolvedCodingCheckpointLimits, } from "./coding-checkpoint.js";
7
9
  export { assertCodingResumeAllowed, buildCodingCheckpointMetadata, CODING_CHECKPOINT_SCHEMA_VERSION, CODING_STATE_KEY, CodingCheckpointError, codingCheckpointStatePatch, codingPlanPathForTask, createCodingArtifactRef, createCodingPlanMarkdown, fingerprintJson, parseCodingPlanTodos, readCodingCheckpointFromState, readCodingPlanFile, resolveCodingCheckpointLimits, validateCodingCheckpointMetadata, verifyCodingArtifactBytes, writeCodingPlanFile, } from "./coding-checkpoint.js";
8
10
  export type { Edit, EditOperations, EditToolDetails, EditToolOptions } from "./edit.js";
@@ -13,11 +15,18 @@ export type { GitToolsOptions } from "./git-tools.js";
13
15
  export { createGitApplyTool, createGitBranchTool, createGitCommitTool, createGitDiffTool, createGitPrHandoffTool, createGitStatusTool, createGitTools, createGitWorktreeTool, } from "./git-tools.js";
14
16
  export type { CodingGoalVerifyApproval, RunCodingGoalVerifyOptions, } from "./goal-verify.js";
15
17
  export { CODING_GOAL_VERIFY_REVISION, CODING_GOAL_VERIFY_SUSPEND_REASON, CODING_GOAL_VERIFY_WORKFLOW_ID, CodingGoalVerifyError, createCodingGoalVerifyWorkflow, runCodingGoalVerify, } from "./goal-verify.js";
18
+ export type { GlobToolOptions } from "./glob.js";
19
+ export { createGlobTool } from "./glob.js";
20
+ export { matchGlobPattern, validateGlobPattern } from "./glob-match.js";
16
21
  export type { ListToolOptions } from "./list.js";
17
22
  export { createRepoListTool } from "./list.js";
23
+ export type { MoveOperations, MoveToolOptions } from "./move.js";
24
+ export { createMoveTool } from "./move.js";
18
25
  export type { ReadOperations, ReadTextOptions, ReadTextResult, ReadToolOptions, TransformImage, TransformImageInput, } from "./read.js";
19
26
  export { createReadTool, DEFAULT_MAX_IMAGE_BYTES, detectSupportedImageMimeType, detectSupportedImageMimeTypeFromFile, } from "./read.js";
20
- export type { RepoEntryKind, RepoListEntry, RepositoryLimitOptions, RepositoryListRequest, RepositoryListResult, RepositoryOperations, RepositorySearchMatch, RepositorySearchRequest, RepositorySearchResult, ResolvedRepositoryLimits, } from "./repository.js";
27
+ export type { ReadPathSet } from "./read-path-set.js";
28
+ export { createReadPathSet } from "./read-path-set.js";
29
+ export type { RepoEntryKind, RepoListEntry, RepositoryGlobRequest, RepositoryGlobResult, RepositoryLimitOptions, RepositoryListRequest, RepositoryListResult, RepositoryOperations, RepoSearchOutputMode, RepositorySearchMatch, RepositorySearchRequest, RepositorySearchResult, ResolvedRepositoryLimits, } from "./repository.js";
21
30
  export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
22
31
  export type { SearchToolOptions } from "./search.js";
23
32
  export { createRepoSearchTool } from "./search.js";
@@ -29,8 +38,11 @@ export { enforceExecutionPolicy } from "./execution-policy.js";
29
38
  export { withFileMutationQueue } from "./file-mutation-queue.js";
30
39
  export { DEFAULT_CHECK_TIMEOUT_MS, DEFAULT_GIT_TIMEOUT_MS, DEFAULT_MAX_BYTES, DEFAULT_MAX_CHECK_CONCURRENCY, DEFAULT_MAX_CHECK_DIAGNOSTIC_LINES, DEFAULT_MAX_CHECK_NAMES, DEFAULT_MAX_CHECK_OUTPUT_BYTES, DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_CODING_ARTIFACT_BYTES, DEFAULT_MAX_CODING_ARTIFACTS, DEFAULT_MAX_CODING_CHECKPOINT_BYTES, DEFAULT_MAX_EDIT_FILE_BYTES, DEFAULT_MAX_EDIT_INPUT_BYTES, DEFAULT_MAX_EDITS, DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_GIT_PATCH_BYTES, DEFAULT_MAX_GIT_PATHS, DEFAULT_MAX_GIT_REF_BYTES, DEFAULT_MAX_GIT_WORKTREES, DEFAULT_MAX_LINES, DEFAULT_MAX_PLAN_BYTES, DEFAULT_MAX_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, DEFAULT_MAX_REPO_CONCURRENCY, DEFAULT_MAX_REPO_DEPTH, DEFAULT_MAX_REPO_ENTRIES, DEFAULT_MAX_REPO_FILES, DEFAULT_MAX_REPO_RESULTS, DEFAULT_MAX_SEARCH_CONTEXT_LINES, DEFAULT_MAX_SEARCH_FILE_BYTES, DEFAULT_MAX_SEARCH_LINE_BYTES, DEFAULT_MAX_SEARCH_MATCHES, DEFAULT_MAX_SEARCH_PATTERN_BYTES, DEFAULT_MAX_SEARCH_SCAN_BYTES, DEFAULT_MAX_SEARCH_TIME_MS, DEFAULT_MAX_TEXT_SCAN_BYTES, DEFAULT_MAX_TODO_TEXT_BYTES, DEFAULT_MAX_TODOS, DEFAULT_MAX_TOTAL_OUTPUT_BYTES, DEFAULT_MAX_WRITE_BYTES, DEFAULT_SHELL_TIMEOUT_SECONDS, HARD_CHECK_TIMEOUT_MS, HARD_GIT_TIMEOUT_MS, HARD_MAX_BYTES, HARD_MAX_CHECK_CONCURRENCY, HARD_MAX_CHECK_DIAGNOSTIC_LINES, HARD_MAX_CHECK_NAMES, HARD_MAX_CHECK_OUTPUT_BYTES, HARD_MAX_CHECK_SUMMARY_BYTES, HARD_MAX_CODING_ARTIFACT_BYTES, HARD_MAX_CODING_ARTIFACTS, HARD_MAX_CODING_CHECKPOINT_BYTES, HARD_MAX_EDIT_FILE_BYTES, HARD_MAX_EDIT_INPUT_BYTES, HARD_MAX_EDITS, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_GIT_PATCH_BYTES, HARD_MAX_GIT_PATHS, HARD_MAX_GIT_REF_BYTES, HARD_MAX_GIT_WORKTREES, HARD_MAX_IMAGE_BYTES, HARD_MAX_LINES, HARD_MAX_PLAN_BYTES, HARD_MAX_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, HARD_MAX_REPO_CONCURRENCY, HARD_MAX_REPO_DEPTH, HARD_MAX_REPO_ENTRIES, HARD_MAX_REPO_FILES, HARD_MAX_REPO_RESULTS, HARD_MAX_SEARCH_CONTEXT_LINES, HARD_MAX_SEARCH_FILE_BYTES, HARD_MAX_SEARCH_LINE_BYTES, HARD_MAX_SEARCH_MATCHES, HARD_MAX_SEARCH_PATTERN_BYTES, HARD_MAX_SEARCH_SCAN_BYTES, HARD_MAX_SEARCH_TIME_MS, HARD_MAX_TEXT_SCAN_BYTES, HARD_MAX_TODO_TEXT_BYTES, HARD_MAX_TODOS, HARD_MAX_TOTAL_OUTPUT_BYTES, HARD_MAX_WRITE_BYTES, HARD_SHELL_TIMEOUT_SECONDS, } from "./limits.js";
31
40
  import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
41
+ import type { DeleteToolOptions } from "./delete.js";
32
42
  import type { EditToolOptions } from "./edit.js";
43
+ import type { GlobToolOptions } from "./glob.js";
33
44
  import type { ListToolOptions } from "./list.js";
45
+ import type { MoveToolOptions } from "./move.js";
34
46
  import type { ReadToolOptions } from "./read.js";
35
47
  import type { RepositoryLimitOptions, RepositoryOperations } from "./repository.js";
36
48
  import type { SearchToolOptions } from "./search.js";
@@ -44,24 +56,27 @@ export interface ToolsOptions {
44
56
  read?: ReadToolOptions;
45
57
  write?: WriteToolOptions;
46
58
  edit?: EditToolOptions;
59
+ delete?: DeleteToolOptions;
60
+ move?: MoveToolOptions;
47
61
  list?: ListToolOptions;
48
62
  search?: SearchToolOptions;
63
+ glob?: GlobToolOptions;
49
64
  /**
50
- * Shared repository limits/backends for `repo_list` / `repo_search`.
51
- * Per-tool `list` / `search` options override these when both are set.
65
+ * Shared repository limits/backends for `repo_list` / `repo_search` / `glob`.
66
+ * Per-tool `list` / `search` / `glob` options override these when both are set.
52
67
  */
53
68
  repository?: RepositoryLimitOptions & {
54
69
  operations?: RepositoryOperations;
55
70
  };
56
71
  }
57
72
  /**
58
- * Full coding tool set: `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`.
73
+ * Full coding tool set: `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, `move`.
59
74
  * Opt-in tools (`createGitTools`, `createAskUserDecisionTool`, `createCodingCheckTool`)
60
75
  * stay out — hosts register them explicitly.
61
76
  */
62
77
  export declare function createCodingTools(cwd: string, options?: ToolsOptions): readonly ToolDefinition[];
63
78
  /**
64
- * Read-only subset: `read`, `repo_list`, `repo_search`.
79
+ * Read-only subset: `read`, `repo_list`, `repo_search`, `glob`.
65
80
  * Deliberate 0.0.9 expansion from the previous `read`-only set.
66
81
  */
67
82
  export declare function createReadOnlyTools(cwd: string, options?: ToolsOptions): readonly ToolDefinition[];
package/dist/index.js CHANGED
@@ -7,13 +7,18 @@
7
7
  export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } from "./artifacts.js";
8
8
  export { ASK_USER_DECISION_RATIONALE_COUNT, ASK_USER_DECISION_SUSPEND_REASON, ASK_USER_DECISION_TOOL_NAME, askUserDecisionResumeSchema, createAskUserDecisionResumeValidator, createAskUserDecisionTool, DEFAULT_MAX_ASK_USER_DECISION_BULLET_BYTES, DEFAULT_MAX_ASK_USER_DECISION_CUSTOM_BYTES, DEFAULT_MAX_ASK_USER_DECISION_LABEL_BYTES, DEFAULT_MAX_ASK_USER_DECISION_OPTIONS, DEFAULT_MAX_ASK_USER_DECISION_QUESTION_BYTES, HARD_MAX_ASK_USER_DECISION_BULLET_BYTES, HARD_MAX_ASK_USER_DECISION_CUSTOM_BYTES, HARD_MAX_ASK_USER_DECISION_LABEL_BYTES, HARD_MAX_ASK_USER_DECISION_OPTIONS, HARD_MAX_ASK_USER_DECISION_QUESTION_BYTES, parseAskUserDecisionArgs, resolveAskUserDecisionAnswer, resolveAskUserDecisionLimits, suspendAskUserDecision, toAskUserDecisionSuspendData, validateAskUserDecisionAgentResume, validateAskUserDecisionResume, } from "./ask-user-decision.js";
9
9
  export { createCodingCheckTool } from "./checks.js";
10
+ export { createDeleteTool } from "./delete.js";
10
11
  export { assertCodingResumeAllowed, buildCodingCheckpointMetadata, CODING_CHECKPOINT_SCHEMA_VERSION, CODING_STATE_KEY, CodingCheckpointError, codingCheckpointStatePatch, codingPlanPathForTask, createCodingArtifactRef, createCodingPlanMarkdown, fingerprintJson, parseCodingPlanTodos, readCodingCheckpointFromState, readCodingPlanFile, resolveCodingCheckpointLimits, validateCodingCheckpointMetadata, verifyCodingArtifactBytes, writeCodingPlanFile, } from "./coding-checkpoint.js";
11
12
  export { createEditTool } from "./edit.js";
12
13
  export { createBoundGitRunner, createGitOperations, GitError, parsePorcelainV2, resolveGitLimits, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git.js";
13
14
  export { createGitApplyTool, createGitBranchTool, createGitCommitTool, createGitDiffTool, createGitPrHandoffTool, createGitStatusTool, createGitTools, createGitWorktreeTool, } from "./git-tools.js";
14
15
  export { CODING_GOAL_VERIFY_REVISION, CODING_GOAL_VERIFY_SUSPEND_REASON, CODING_GOAL_VERIFY_WORKFLOW_ID, CodingGoalVerifyError, createCodingGoalVerifyWorkflow, runCodingGoalVerify, } from "./goal-verify.js";
16
+ export { createGlobTool } from "./glob.js";
17
+ export { matchGlobPattern, validateGlobPattern } from "./glob-match.js";
15
18
  export { createRepoListTool } from "./list.js";
19
+ export { createMoveTool } from "./move.js";
16
20
  export { createReadTool, DEFAULT_MAX_IMAGE_BYTES, detectSupportedImageMimeType, detectSupportedImageMimeTypeFromFile, } from "./read.js";
21
+ export { createReadPathSet } from "./read-path-set.js";
17
22
  export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
18
23
  export { createRepoSearchTool } from "./search.js";
19
24
  export { createLocalBashOperations, createShellTool, getShellConfig, killProcessTree, waitForChildProcess, } from "./shell.js";
@@ -22,8 +27,11 @@ export { createWriteTool } from "./write.js";
22
27
  export { enforceExecutionPolicy } from "./execution-policy.js";
23
28
  export { withFileMutationQueue } from "./file-mutation-queue.js";
24
29
  export { DEFAULT_CHECK_TIMEOUT_MS, DEFAULT_GIT_TIMEOUT_MS, DEFAULT_MAX_BYTES, DEFAULT_MAX_CHECK_CONCURRENCY, DEFAULT_MAX_CHECK_DIAGNOSTIC_LINES, DEFAULT_MAX_CHECK_NAMES, DEFAULT_MAX_CHECK_OUTPUT_BYTES, DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_CODING_ARTIFACT_BYTES, DEFAULT_MAX_CODING_ARTIFACTS, DEFAULT_MAX_CODING_CHECKPOINT_BYTES, DEFAULT_MAX_EDIT_FILE_BYTES, DEFAULT_MAX_EDIT_INPUT_BYTES, DEFAULT_MAX_EDITS, DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_GIT_PATCH_BYTES, DEFAULT_MAX_GIT_PATHS, DEFAULT_MAX_GIT_REF_BYTES, DEFAULT_MAX_GIT_WORKTREES, DEFAULT_MAX_LINES, DEFAULT_MAX_PLAN_BYTES, DEFAULT_MAX_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, DEFAULT_MAX_REPO_CONCURRENCY, DEFAULT_MAX_REPO_DEPTH, DEFAULT_MAX_REPO_ENTRIES, DEFAULT_MAX_REPO_FILES, DEFAULT_MAX_REPO_RESULTS, DEFAULT_MAX_SEARCH_CONTEXT_LINES, DEFAULT_MAX_SEARCH_FILE_BYTES, DEFAULT_MAX_SEARCH_LINE_BYTES, DEFAULT_MAX_SEARCH_MATCHES, DEFAULT_MAX_SEARCH_PATTERN_BYTES, DEFAULT_MAX_SEARCH_SCAN_BYTES, DEFAULT_MAX_SEARCH_TIME_MS, DEFAULT_MAX_TEXT_SCAN_BYTES, DEFAULT_MAX_TODO_TEXT_BYTES, DEFAULT_MAX_TODOS, DEFAULT_MAX_TOTAL_OUTPUT_BYTES, DEFAULT_MAX_WRITE_BYTES, DEFAULT_SHELL_TIMEOUT_SECONDS, HARD_CHECK_TIMEOUT_MS, HARD_GIT_TIMEOUT_MS, HARD_MAX_BYTES, HARD_MAX_CHECK_CONCURRENCY, HARD_MAX_CHECK_DIAGNOSTIC_LINES, HARD_MAX_CHECK_NAMES, HARD_MAX_CHECK_OUTPUT_BYTES, HARD_MAX_CHECK_SUMMARY_BYTES, HARD_MAX_CODING_ARTIFACT_BYTES, HARD_MAX_CODING_ARTIFACTS, HARD_MAX_CODING_CHECKPOINT_BYTES, HARD_MAX_EDIT_FILE_BYTES, HARD_MAX_EDIT_INPUT_BYTES, HARD_MAX_EDITS, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_GIT_PATCH_BYTES, HARD_MAX_GIT_PATHS, HARD_MAX_GIT_REF_BYTES, HARD_MAX_GIT_WORKTREES, HARD_MAX_IMAGE_BYTES, HARD_MAX_LINES, HARD_MAX_PLAN_BYTES, HARD_MAX_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, HARD_MAX_REPO_CONCURRENCY, HARD_MAX_REPO_DEPTH, HARD_MAX_REPO_ENTRIES, HARD_MAX_REPO_FILES, HARD_MAX_REPO_RESULTS, HARD_MAX_SEARCH_CONTEXT_LINES, HARD_MAX_SEARCH_FILE_BYTES, HARD_MAX_SEARCH_LINE_BYTES, HARD_MAX_SEARCH_MATCHES, HARD_MAX_SEARCH_PATTERN_BYTES, HARD_MAX_SEARCH_SCAN_BYTES, HARD_MAX_SEARCH_TIME_MS, HARD_MAX_TEXT_SCAN_BYTES, HARD_MAX_TODO_TEXT_BYTES, HARD_MAX_TODOS, HARD_MAX_TOTAL_OUTPUT_BYTES, HARD_MAX_WRITE_BYTES, HARD_SHELL_TIMEOUT_SECONDS, } from "./limits.js";
30
+ import { createDeleteTool } from "./delete.js";
25
31
  import { createEditTool } from "./edit.js";
32
+ import { createGlobTool } from "./glob.js";
26
33
  import { createRepoListTool } from "./list.js";
34
+ import { createMoveTool } from "./move.js";
27
35
  import { createReadTool } from "./read.js";
28
36
  import { createRepoSearchTool } from "./search.js";
29
37
  import { createShellTool } from "./shell.js";
@@ -44,7 +52,7 @@ function withRepositoryDefaults(toolOptions, shared) {
44
52
  };
45
53
  }
46
54
  /**
47
- * Full coding tool set: `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`.
55
+ * Full coding tool set: `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, `move`.
48
56
  * Opt-in tools (`createGitTools`, `createAskUserDecisionTool`, `createCodingCheckTool`)
49
57
  * stay out — hosts register them explicitly.
50
58
  */
@@ -52,6 +60,7 @@ export function createCodingTools(cwd, options) {
52
60
  const policy = options?.executionPolicy;
53
61
  const listOpts = withRepositoryDefaults(options?.list, options?.repository);
54
62
  const searchOpts = withRepositoryDefaults(options?.search, options?.repository);
63
+ const globOpts = withRepositoryDefaults(options?.glob, options?.repository);
55
64
  return [
56
65
  createShellTool(cwd, withSharedExecutionPolicy(options?.shell, policy)),
57
66
  createReadTool(cwd, withSharedExecutionPolicy(options?.read, policy)),
@@ -59,20 +68,25 @@ export function createCodingTools(cwd, options) {
59
68
  createEditTool(cwd, withSharedExecutionPolicy(options?.edit, policy)),
60
69
  createRepoListTool(cwd, withSharedExecutionPolicy(listOpts, policy)),
61
70
  createRepoSearchTool(cwd, withSharedExecutionPolicy(searchOpts, policy)),
71
+ createGlobTool(cwd, withSharedExecutionPolicy(globOpts, policy)),
72
+ createDeleteTool(cwd, withSharedExecutionPolicy(options?.delete, policy)),
73
+ createMoveTool(cwd, withSharedExecutionPolicy(options?.move, policy)),
62
74
  ];
63
75
  }
64
76
  /**
65
- * Read-only subset: `read`, `repo_list`, `repo_search`.
77
+ * Read-only subset: `read`, `repo_list`, `repo_search`, `glob`.
66
78
  * Deliberate 0.0.9 expansion from the previous `read`-only set.
67
79
  */
68
80
  export function createReadOnlyTools(cwd, options) {
69
81
  const policy = options?.executionPolicy;
70
82
  const listOpts = withRepositoryDefaults(options?.list, options?.repository);
71
83
  const searchOpts = withRepositoryDefaults(options?.search, options?.repository);
84
+ const globOpts = withRepositoryDefaults(options?.glob, options?.repository);
72
85
  return [
73
86
  createReadTool(cwd, withSharedExecutionPolicy(options?.read, policy)),
74
87
  createRepoListTool(cwd, withSharedExecutionPolicy(listOpts, policy)),
75
88
  createRepoSearchTool(cwd, withSharedExecutionPolicy(searchOpts, policy)),
89
+ createGlobTool(cwd, withSharedExecutionPolicy(globOpts, policy)),
76
90
  ];
77
91
  }
78
92
  /** Every tool this package provides — identical to {@link createCodingTools}. */
package/dist/list.js CHANGED
@@ -33,7 +33,7 @@ export function createRepoListTool(cwd, options) {
33
33
  const ops = options?.operations ?? createLocalRepositoryOperations(limits);
34
34
  return {
35
35
  name: "repo_list",
36
- description: `List repository entries under the workspace with deterministic relative paths. Skips hidden names and excluded basenames (default: ${limits.exclude.join(", ")}) unless overridden. Does not follow symlinks. Results paginate with offset/maxResults (default ${limits.maxResults}). Depth default ${limits.maxDepth}.`,
36
+ description: `List repository entries under the workspace with deterministic relative paths. Prefer glob when you already know a filename pattern (*.ts, **/src/**). Prefer repo_search to find text inside files. Skips hidden names and excluded basenames (default: ${limits.exclude.join(", ")}) unless overridden. Does not follow symlinks. Results paginate with offset/maxResults (default ${limits.maxResults}). Depth default ${limits.maxDepth}.`,
37
37
  parameters: {
38
38
  type: "object",
39
39
  properties: {
package/dist/move.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
2
+ import type { MutationStat } from "./delete.js";
3
+ export interface MoveOperations {
4
+ lstat: (absolutePath: string, options?: {
5
+ signal?: AbortSignal;
6
+ }) => Promise<MutationStat>;
7
+ rename: (from: string, to: string, options?: {
8
+ signal?: AbortSignal;
9
+ }) => Promise<void>;
10
+ unlink: (absolutePath: string, options?: {
11
+ signal?: AbortSignal;
12
+ }) => Promise<void>;
13
+ access: (absolutePath: string, options?: {
14
+ signal?: AbortSignal;
15
+ }) => Promise<void>;
16
+ }
17
+ export interface MoveToolOptions {
18
+ executionPolicy?: ExecutionPolicy;
19
+ operations?: MoveOperations;
20
+ }
21
+ export declare function createMoveTool(cwd: string, options?: MoveToolOptions): ToolDefinition;
package/dist/move.js ADDED
@@ -0,0 +1,147 @@
1
+ import { access, constants } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { lstat, rename, unlink } from "node:fs/promises";
4
+ import { promisify } from "node:util";
5
+ import { enforceExecutionPolicy } from "./execution-policy.js";
6
+ import { withFileMutationQueue } from "./file-mutation-queue.js";
7
+ import { resolveContainedMutationPath } from "./mutation-path.js";
8
+ const accessAsync = promisify(access);
9
+ const defaultMoveOperations = {
10
+ lstat: async (path) => {
11
+ const st = await lstat(path);
12
+ return {
13
+ isFile: () => st.isFile(),
14
+ isDirectory: () => st.isDirectory(),
15
+ isSymbolicLink: () => st.isSymbolicLink(),
16
+ size: st.size,
17
+ };
18
+ },
19
+ rename: (from, to) => rename(from, to).then(() => { }),
20
+ unlink: (path) => unlink(path).then(() => { }),
21
+ access: (path) => accessAsync(path, constants.F_OK),
22
+ };
23
+ function errorResult(toolCallId, message) {
24
+ return {
25
+ toolCallId,
26
+ name: "move",
27
+ content: [{ type: "text", text: message }],
28
+ error: { message },
29
+ };
30
+ }
31
+ async function withDualFileMutationQueue(pathA, pathB, fn) {
32
+ const [first, second] = pathA <= pathB ? [pathA, pathB] : [pathB, pathA];
33
+ return withFileMutationQueue(first, () => withFileMutationQueue(second, fn));
34
+ }
35
+ export function createMoveTool(cwd, options) {
36
+ const ops = options?.operations ?? defaultMoveOperations;
37
+ return {
38
+ name: "move",
39
+ description: "High-risk: move or rename a file within the workspace. Set overwrite=true to replace an existing destination file only (directories/non-empty dest rejected). Does not create parent directories. No trash — host undo is not automatic.",
40
+ parameters: {
41
+ type: "object",
42
+ properties: {
43
+ from: { type: "string", description: "Source path (relative or absolute)" },
44
+ to: { type: "string", description: "Destination path (relative or absolute)" },
45
+ overwrite: {
46
+ type: "boolean",
47
+ description: "Replace an existing destination file when true (default false).",
48
+ },
49
+ },
50
+ required: ["from", "to"],
51
+ additionalProperties: false,
52
+ },
53
+ async execute(args, context) {
54
+ const toolCallId = context.toolCallId;
55
+ const from = typeof args.from === "string" ? args.from : "";
56
+ const to = typeof args.to === "string" ? args.to : "";
57
+ const overwrite = args.overwrite === true;
58
+ if (from.length === 0)
59
+ return errorResult(toolCallId, "from is required and must be a non-empty string.");
60
+ if (to.length === 0)
61
+ return errorResult(toolCallId, "to is required and must be a non-empty string.");
62
+ try {
63
+ let fromPath;
64
+ try {
65
+ fromPath = await resolveContainedMutationPath(cwd, from);
66
+ }
67
+ catch (error) {
68
+ const err = error;
69
+ if (err.code === "ENOENT")
70
+ return errorResult(toolCallId, `Source does not exist: ${from}`);
71
+ throw error;
72
+ }
73
+ const toPath = await resolveContainedMutationPath(cwd, to, { allowMissing: true });
74
+ const policyCheck = await enforceExecutionPolicy(options?.executionPolicy, {
75
+ kind: "move",
76
+ operation: "move",
77
+ paths: [fromPath, toPath],
78
+ risk: "high",
79
+ metadata: { overwrite, sessionId: context.sessionId, runId: context.runId, signal: context.signal },
80
+ }, toolCallId, "move");
81
+ if (!policyCheck.allowed)
82
+ return policyCheck.result;
83
+ const allowedFrom = policyCheck.action.paths?.[0] ?? fromPath;
84
+ const allowedTo = policyCheck.action.paths?.[1] ?? toPath;
85
+ return await withDualFileMutationQueue(allowedFrom, allowedTo, async () => {
86
+ if (context.signal?.aborted)
87
+ return errorResult(toolCallId, "Operation aborted");
88
+ let fromStat;
89
+ try {
90
+ fromStat = await ops.lstat(allowedFrom, { signal: context.signal });
91
+ }
92
+ catch (error) {
93
+ const err = error;
94
+ if (err.code === "ENOENT")
95
+ return errorResult(toolCallId, `Source does not exist: ${from}`);
96
+ const message = error instanceof Error ? error.message : String(error);
97
+ return errorResult(toolCallId, message);
98
+ }
99
+ const destParent = dirname(allowedTo);
100
+ try {
101
+ await ops.access(destParent, { signal: context.signal });
102
+ }
103
+ catch {
104
+ return errorResult(toolCallId, `Destination parent directory does not exist: ${destParent}`);
105
+ }
106
+ let destStat;
107
+ try {
108
+ destStat = await ops.lstat(allowedTo, { signal: context.signal });
109
+ }
110
+ catch (error) {
111
+ const err = error;
112
+ if (err.code !== "ENOENT") {
113
+ const message = error instanceof Error ? error.message : String(error);
114
+ return errorResult(toolCallId, message);
115
+ }
116
+ }
117
+ if (destStat) {
118
+ if (!overwrite)
119
+ return errorResult(toolCallId, `Destination already exists: ${to}. Pass overwrite=true to replace.`);
120
+ if (destStat.isDirectory())
121
+ return errorResult(toolCallId, `Destination is a directory: ${to}`);
122
+ await ops.unlink(allowedTo, { signal: context.signal });
123
+ }
124
+ if (context.signal?.aborted)
125
+ return errorResult(toolCallId, "Operation aborted");
126
+ await ops.rename(allowedFrom, allowedTo, { signal: context.signal });
127
+ return {
128
+ toolCallId,
129
+ name: "move",
130
+ content: [{ type: "text", text: `Successfully moved ${from} to ${allowedTo}` }],
131
+ metadata: {
132
+ from: allowedFrom,
133
+ to: allowedTo,
134
+ bytes: fromStat.isFile() ? fromStat.size : undefined,
135
+ overwrite,
136
+ },
137
+ };
138
+ });
139
+ }
140
+ catch (error) {
141
+ const message = error instanceof Error ? error.message : String(error);
142
+ return errorResult(toolCallId, message);
143
+ }
144
+ },
145
+ };
146
+ }
147
+ //# sourceMappingURL=move.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Resolve a mutation target under `root`. Symlink paths are kept as the link
3
+ * location (not followed). Non-symlink existing paths are realpath'd.
4
+ */
5
+ export declare function resolveContainedMutationPath(root: string, inputPath: string, options?: {
6
+ allowMissing?: boolean;
7
+ }): Promise<string>;
@@ -0,0 +1,51 @@
1
+ import { lstat, realpath } from "node:fs/promises";
2
+ import { isAbsolute, relative, resolve } from "node:path";
3
+ import { resolveToCwd } from "./path-utils.js";
4
+ function isPathInsideRoot(root, target) {
5
+ const from = resolve(root);
6
+ const to = resolve(target);
7
+ if (to === from)
8
+ return true;
9
+ const rel = relative(from, to);
10
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
11
+ }
12
+ function isMissingPathError(error) {
13
+ return (typeof error === "object" &&
14
+ error !== null &&
15
+ "code" in error &&
16
+ (error.code === "ENOENT" || error.code === "ENOTDIR"));
17
+ }
18
+ /**
19
+ * Resolve a mutation target under `root`. Symlink paths are kept as the link
20
+ * location (not followed). Non-symlink existing paths are realpath'd.
21
+ */
22
+ export async function resolveContainedMutationPath(root, inputPath, options) {
23
+ const rootResolved = resolve(root);
24
+ let rootReal;
25
+ try {
26
+ rootReal = await realpath(rootResolved);
27
+ }
28
+ catch {
29
+ throw new Error(`workspace root is missing or unreadable: ${rootResolved}`);
30
+ }
31
+ const candidate = resolveToCwd(inputPath, rootReal);
32
+ if (!isPathInsideRoot(rootReal, candidate)) {
33
+ throw new Error(`path escapes workspace root: ${inputPath}`);
34
+ }
35
+ try {
36
+ const st = await lstat(candidate);
37
+ if (st.isSymbolicLink())
38
+ return candidate;
39
+ const real = await realpath(candidate);
40
+ if (!isPathInsideRoot(rootReal, real)) {
41
+ throw new Error(`path resolves outside workspace root: ${inputPath}`);
42
+ }
43
+ return real;
44
+ }
45
+ catch (error) {
46
+ if (options?.allowMissing && isMissingPathError(error))
47
+ return candidate;
48
+ throw error;
49
+ }
50
+ }
51
+ //# sourceMappingURL=mutation-path.js.map
@@ -0,0 +1,14 @@
1
+ /** Session-scoped paths successfully read via the read tool (host-owned, not checkpointed). */
2
+ export interface ReadPathSet {
3
+ has(path: string): boolean;
4
+ add(path: string): void;
5
+ list(): readonly string[];
6
+ clear(): void;
7
+ }
8
+ export declare function createReadPathSet(): ReadPathSet;
9
+ export interface ReadBeforeWriteOptions {
10
+ requireReadBeforeWrite?: boolean;
11
+ readPathSet?: ReadPathSet;
12
+ }
13
+ /** Returns refusal message, or null when the mutation may proceed. */
14
+ export declare function refuseReadBeforeWrite(operation: "write" | "edit", displayPath: string, absolutePath: string, options: ReadBeforeWriteOptions | undefined, force: boolean): string | null;
@@ -0,0 +1,26 @@
1
+ export function createReadPathSet() {
2
+ const paths = new Set();
3
+ return {
4
+ has(path) {
5
+ return paths.has(path);
6
+ },
7
+ add(path) {
8
+ paths.add(path);
9
+ },
10
+ list() {
11
+ return [...paths];
12
+ },
13
+ clear() {
14
+ paths.clear();
15
+ },
16
+ };
17
+ }
18
+ /** Returns refusal message, or null when the mutation may proceed. */
19
+ export function refuseReadBeforeWrite(operation, displayPath, absolutePath, options, force) {
20
+ if (!options?.requireReadBeforeWrite || force)
21
+ return null;
22
+ if (options.readPathSet?.has(absolutePath))
23
+ return null;
24
+ return `Refusing ${operation} to ${displayPath}: not read in this session. Read first or pass force=true.`;
25
+ }
26
+ //# sourceMappingURL=read-path-set.js.map
package/dist/read.d.ts CHANGED
@@ -21,6 +21,7 @@
21
21
  */
22
22
  import { Buffer } from "node:buffer";
23
23
  import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
24
+ import type { ReadPathSet } from "./read-path-set.js";
24
25
  import { type TruncationResult } from "./truncate.js";
25
26
  /** Detect a supported image MIME type from a buffer's leading bytes. Returns null for non-images. */
26
27
  export declare function detectSupportedImageMimeType(buffer: Buffer): string | null;
@@ -100,6 +101,8 @@ export interface ReadToolOptions {
100
101
  maxLines?: number;
101
102
  /** Max bytes kept from the head (default 50KB). */
102
103
  maxBytes?: number;
104
+ /** When set, successful reads record the resolved absolute path for read-before-write guards. */
105
+ readPathSet?: ReadPathSet;
103
106
  }
104
107
  export declare function createReadTool(cwd: string, options?: ReadToolOptions): ToolDefinition;
105
108
  /** Re-exported for hosts building custom read tools or analyzing truncation metadata. */
package/dist/read.js CHANGED
@@ -307,7 +307,7 @@ export function createReadTool(cwd, options) {
307
307
  const maxScanBytes = validateCodingLimit("maxScanBytes", options?.maxScanBytes ?? DEFAULT_MAX_TEXT_SCAN_BYTES, HARD_MAX_TEXT_SCAN_BYTES);
308
308
  return {
309
309
  name: "read",
310
- description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp); images are returned as image content. For text files, output is truncated to ${maxLines} lines or ${maxBytes / 1024}KB (whichever is hit first). Use offset/limit for large files. When you need the full file, continue with offset until complete.`,
310
+ description: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp, bmp); images are returned as image content. For text files, output is truncated to ${maxLines} lines or ${maxBytes / 1024}KB (whichever is hit first). When truncated, continue with the suggested offset until complete. Prefer repo_search to find text across many files.`,
311
311
  parameters: {
312
312
  type: "object",
313
313
  properties: {
@@ -352,6 +352,7 @@ export function createReadTool(cwd, options) {
352
352
  autoResizeImages: options?.autoResizeImages,
353
353
  signal: context.signal,
354
354
  });
355
+ options?.readPathSet?.add(allowedPath);
355
356
  return {
356
357
  toolCallId,
357
358
  name: "read",
@@ -406,6 +407,7 @@ export function createReadTool(cwd, options) {
406
407
  outputText += `\n\n[Showing lines ${page.startLine}-${endLine}${page.truncatedBy === "bytes" ? ` (${formatSize(maxBytes)} limit)` : ""}. Use offset=${page.nextOffset} to continue.]`;
407
408
  }
408
409
  }
410
+ options?.readPathSet?.add(allowedPath);
409
411
  return {
410
412
  toolCallId,
411
413
  name: "read",
@@ -20,6 +20,16 @@ export interface RepositoryListResult {
20
20
  readonly nextOffset?: number;
21
21
  readonly offset: number;
22
22
  }
23
+ export interface RepositoryGlobResult {
24
+ readonly paths: readonly string[];
25
+ readonly truncated: boolean;
26
+ readonly truncatedBy: RepositoryListResult["truncatedBy"];
27
+ readonly scannedEntries: number;
28
+ readonly scannedFiles: number;
29
+ readonly nextOffset?: number;
30
+ readonly offset: number;
31
+ }
32
+ export type RepoSearchOutputMode = "content" | "files_with_matches" | "count";
23
33
  export interface RepositorySearchMatch {
24
34
  readonly path: string;
25
35
  readonly line: number;
@@ -86,6 +96,7 @@ export interface RepositorySearchRequest {
86
96
  readonly query: string;
87
97
  readonly path?: string;
88
98
  readonly mode?: "literal";
99
+ readonly outputMode?: RepoSearchOutputMode;
89
100
  readonly caseSensitive?: boolean;
90
101
  readonly includeHidden?: boolean;
91
102
  readonly exclude?: readonly string[];
@@ -94,9 +105,22 @@ export interface RepositorySearchRequest {
94
105
  readonly signal?: AbortSignal;
95
106
  readonly deadlineMs?: number;
96
107
  }
108
+ export interface RepositoryGlobRequest {
109
+ readonly root: string;
110
+ readonly pattern: string;
111
+ readonly path?: string;
112
+ readonly includeHidden?: boolean;
113
+ readonly exclude?: readonly string[];
114
+ readonly maxDepth?: number;
115
+ readonly maxResults?: number;
116
+ readonly offset?: number;
117
+ readonly signal?: AbortSignal;
118
+ readonly deadlineMs?: number;
119
+ }
97
120
  export interface RepositoryOperations {
98
121
  list(request: RepositoryListRequest): Promise<RepositoryListResult>;
99
122
  search(request: RepositorySearchRequest): Promise<RepositorySearchResult>;
123
+ glob(request: RepositoryGlobRequest): Promise<RepositoryGlobResult>;
100
124
  }
101
125
  export declare const DEFAULT_REPO_EXCLUDE: readonly string[];
102
126
  export declare class RepositoryError extends Error {