@arnilo/prism-coding-agent 0.0.15 → 0.0.17
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/CHANGELOG.md +13 -0
- package/dist/ask-user-decision.js +11 -14
- package/dist/checks.js +3 -0
- package/dist/coding-checkpoint.js +6 -15
- package/dist/edit-diff.js +1 -4
- package/dist/edit.js +4 -6
- package/dist/execution-policy.d.ts +1 -2
- package/dist/execution-policy.js +1 -1
- package/dist/file-mutation-queue.js +1 -2
- package/dist/git-exec.js +1 -1
- package/dist/git-tools.d.ts +1 -1
- package/dist/git-tools.js +3 -6
- package/dist/git.d.ts +3 -3
- package/dist/git.js +14 -14
- package/dist/goal-verify.d.ts +1 -1
- package/dist/goal-verify.js +2 -5
- package/dist/index.d.ts +30 -30
- package/dist/index.js +16 -16
- package/dist/list.js +3 -9
- package/dist/path-utils.js +1 -1
- package/dist/read.js +6 -16
- package/dist/repository.d.ts +7 -0
- package/dist/repository.js +2 -4
- package/dist/search.js +4 -10
- package/dist/shell.d.ts +3 -0
- package/dist/shell.js +20 -7
- package/dist/truncate.js +1 -1
- package/dist/write.js +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.17] - 2026-07-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `ShellToolOptions.envAllowlist` restricts the environment the spawn hook and child process see (secret scrubbing without re-implementing the hook).
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- Released with exact 0.0.17 graph.
|
|
10
|
+
|
|
11
|
+
## [0.0.16] - 2026-07-26
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Released with exact 0.0.16 graph.
|
|
15
|
+
|
|
3
16
|
## [0.0.15] - 2026-07-26
|
|
4
17
|
|
|
5
18
|
## [0.0.14] - 2026-07-26
|
|
@@ -210,7 +210,7 @@ export function createAskUserDecisionTool(options) {
|
|
|
210
210
|
selectionMode: {
|
|
211
211
|
type: "string",
|
|
212
212
|
enum: ["single", "multiple"],
|
|
213
|
-
description:
|
|
213
|
+
description: "single (default) or multiple selection",
|
|
214
214
|
},
|
|
215
215
|
allowCustom: {
|
|
216
216
|
type: "boolean",
|
|
@@ -387,11 +387,7 @@ export function askUserDecisionResumeSchema(request) {
|
|
|
387
387
|
maxLength: DEFAULT_MAX_ASK_USER_DECISION_CUSTOM_BYTES,
|
|
388
388
|
},
|
|
389
389
|
},
|
|
390
|
-
anyOf: [
|
|
391
|
-
{ required: ["selectedId"] },
|
|
392
|
-
{ required: ["selectedIds"] },
|
|
393
|
-
{ required: ["customText"] },
|
|
394
|
-
],
|
|
390
|
+
anyOf: [{ required: ["selectedId"] }, { required: ["selectedIds"] }, { required: ["customText"] }],
|
|
395
391
|
};
|
|
396
392
|
}
|
|
397
393
|
export function toAskUserDecisionSuspendData(request) {
|
|
@@ -409,10 +405,10 @@ function isAskUserDecisionSuspendData(value) {
|
|
|
409
405
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
410
406
|
return false;
|
|
411
407
|
const row = value;
|
|
412
|
-
return (typeof row.question === "string"
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
408
|
+
return (typeof row.question === "string" &&
|
|
409
|
+
Array.isArray(row.options) &&
|
|
410
|
+
(row.selectionMode === "single" || row.selectionMode === "multiple") &&
|
|
411
|
+
typeof row.allowCustom === "boolean");
|
|
416
412
|
}
|
|
417
413
|
/**
|
|
418
414
|
* Return from a workflow node to pause for a user decision (opt-in durable path).
|
|
@@ -441,7 +437,10 @@ export function validateAskUserDecisionResume(request, value, limits) {
|
|
|
441
437
|
throw new Error("resume input must be an ask_user_decision answer object");
|
|
442
438
|
}
|
|
443
439
|
const maxCustomTextBytes = limits?.maxCustomTextBytes ?? DEFAULT_MAX_ASK_USER_DECISION_CUSTOM_BYTES;
|
|
444
|
-
return resolveAskUserDecisionAnswer(value, request.selectionMode, request.options, {
|
|
440
|
+
return resolveAskUserDecisionAnswer(value, request.selectionMode, request.options, {
|
|
441
|
+
allowCustom: request.allowCustom,
|
|
442
|
+
maxCustomTextBytes,
|
|
443
|
+
});
|
|
445
444
|
}
|
|
446
445
|
/**
|
|
447
446
|
* Workflow `validateResume` adapter. Reads durable request from `suspension.data`
|
|
@@ -464,8 +463,6 @@ export function createAskUserDecisionResumeValidator(limits) {
|
|
|
464
463
|
* unchanged in 0.0.12). Call after operator supplies an answer.
|
|
465
464
|
*/
|
|
466
465
|
export function validateAskUserDecisionAgentResume(input) {
|
|
467
|
-
return validateAskUserDecisionResume(input.request, input.answer, input.maxCustomTextBytes === undefined
|
|
468
|
-
? undefined
|
|
469
|
-
: { maxCustomTextBytes: input.maxCustomTextBytes });
|
|
466
|
+
return validateAskUserDecisionResume(input.request, input.answer, input.maxCustomTextBytes === undefined ? undefined : { maxCustomTextBytes: input.maxCustomTextBytes });
|
|
470
467
|
}
|
|
471
468
|
//# sourceMappingURL=ask-user-decision.js.map
|
package/dist/checks.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
10
10
|
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
11
|
-
import { DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_CODING_ARTIFACT_BYTES, DEFAULT_MAX_CODING_ARTIFACTS, DEFAULT_MAX_CODING_CHECKPOINT_BYTES, DEFAULT_MAX_PLAN_BYTES, DEFAULT_MAX_TODO_TEXT_BYTES, DEFAULT_MAX_TODOS, HARD_MAX_CHECK_SUMMARY_BYTES, HARD_MAX_CODING_ARTIFACT_BYTES, HARD_MAX_CODING_ARTIFACTS, HARD_MAX_CODING_CHECKPOINT_BYTES, HARD_MAX_PLAN_BYTES, HARD_MAX_TODO_TEXT_BYTES, HARD_MAX_TODOS, validateCodingLimit, } from "./limits.js";
|
|
12
11
|
import { sha256Hex } from "./artifacts.js";
|
|
12
|
+
import { DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_CODING_ARTIFACT_BYTES, DEFAULT_MAX_CODING_ARTIFACTS, DEFAULT_MAX_CODING_CHECKPOINT_BYTES, DEFAULT_MAX_PLAN_BYTES, DEFAULT_MAX_TODO_TEXT_BYTES, DEFAULT_MAX_TODOS, HARD_MAX_CHECK_SUMMARY_BYTES, HARD_MAX_CODING_ARTIFACT_BYTES, HARD_MAX_CODING_ARTIFACTS, HARD_MAX_CODING_CHECKPOINT_BYTES, HARD_MAX_PLAN_BYTES, HARD_MAX_TODO_TEXT_BYTES, HARD_MAX_TODOS, validateCodingLimit, } from "./limits.js";
|
|
13
13
|
export const CODING_CHECKPOINT_SCHEMA_VERSION = 1;
|
|
14
14
|
/** Workflow shared-state key that holds coding checkpoint metadata. */
|
|
15
15
|
export const CODING_STATE_KEY = "coding";
|
|
@@ -217,9 +217,7 @@ export function validateCodingCheckpointMetadata(value, limits) {
|
|
|
217
217
|
const planPath = requireRelativePath(value.planPath, "planPath");
|
|
218
218
|
const plan = validateArtifactRef(value.plan, resolved, { requireKind: "plan" });
|
|
219
219
|
const worktreePath = value.worktreePath === undefined ? undefined : requireAbsolutePath(value.worktreePath, "worktreePath");
|
|
220
|
-
const workspaceExport = value.workspaceExport === undefined
|
|
221
|
-
? undefined
|
|
222
|
-
: validateArtifactRef(value.workspaceExport, resolved);
|
|
220
|
+
const workspaceExport = value.workspaceExport === undefined ? undefined : validateArtifactRef(value.workspaceExport, resolved);
|
|
223
221
|
const artifacts = requireArray(value.artifacts, "artifacts").map((item, index) => validateArtifactRef(item, resolved, { label: `artifacts[${index}]` }));
|
|
224
222
|
if (artifacts.length > resolved.maxArtifacts) {
|
|
225
223
|
throw new CodingCheckpointError(`Coding checkpoint exceeds ${resolved.maxArtifacts} artifact references`);
|
|
@@ -270,8 +268,7 @@ export function validateCodingCheckpointMetadata(value, limits) {
|
|
|
270
268
|
export function assertCodingResumeAllowed(input) {
|
|
271
269
|
const metadata = validateCodingCheckpointMetadata(input.metadata, input.limits);
|
|
272
270
|
assertFingerprintsMatch(metadata.fingerprints, input.expected);
|
|
273
|
-
if (input.expectedWorkspaceRoot !== undefined &&
|
|
274
|
-
resolve(input.expectedWorkspaceRoot) !== resolve(metadata.workspaceRoot)) {
|
|
271
|
+
if (input.expectedWorkspaceRoot !== undefined && resolve(input.expectedWorkspaceRoot) !== resolve(metadata.workspaceRoot)) {
|
|
275
272
|
throw new CodingCheckpointError("Workspace root mismatch on coding resume");
|
|
276
273
|
}
|
|
277
274
|
if (input.expectedBaseBranch !== undefined && input.expectedBaseBranch !== metadata.baseBranch) {
|
|
@@ -326,12 +323,8 @@ function validateFingerprints(value) {
|
|
|
326
323
|
const workflowRevision = requireString(value.workflowRevision, "fingerprints.workflowRevision");
|
|
327
324
|
const toolFingerprint = requireFingerprint(value.toolFingerprint, "fingerprints.toolFingerprint");
|
|
328
325
|
const policyFingerprint = requireFingerprint(value.policyFingerprint, "fingerprints.policyFingerprint");
|
|
329
|
-
const definitionHash = value.definitionHash === undefined
|
|
330
|
-
|
|
331
|
-
: requireFingerprint(value.definitionHash, "fingerprints.definitionHash");
|
|
332
|
-
const imageDigest = value.imageDigest === undefined
|
|
333
|
-
? undefined
|
|
334
|
-
: requireString(value.imageDigest, "fingerprints.imageDigest");
|
|
326
|
+
const definitionHash = value.definitionHash === undefined ? undefined : requireFingerprint(value.definitionHash, "fingerprints.definitionHash");
|
|
327
|
+
const imageDigest = value.imageDigest === undefined ? undefined : requireString(value.imageDigest, "fingerprints.imageDigest");
|
|
335
328
|
if (imageDigest !== undefined && !/sha256:[a-f0-9]{64}/.test(imageDigest) && !SHA256_HEX.test(imageDigest)) {
|
|
336
329
|
// Allow either raw hex or docker digest form.
|
|
337
330
|
if (!imageDigest.includes("@sha256:") && !imageDigest.startsWith("sha256:")) {
|
|
@@ -421,9 +414,7 @@ function validateHandoffSummary(value, limits) {
|
|
|
421
414
|
if (changedPathCount < 0 || checkCount < 0) {
|
|
422
415
|
throw new CodingCheckpointError("handoff counts must be non-negative");
|
|
423
416
|
}
|
|
424
|
-
const artifact = value.artifact === undefined
|
|
425
|
-
? undefined
|
|
426
|
-
: validateArtifactRef(value.artifact, limits, { label: "handoff.artifact" });
|
|
417
|
+
const artifact = value.artifact === undefined ? undefined : validateArtifactRef(value.artifact, limits, { label: "handoff.artifact" });
|
|
427
418
|
return { base, head, changedPathCount, checkCount, artifact };
|
|
428
419
|
}
|
|
429
420
|
function requireStatus(value) {
|
package/dist/edit-diff.js
CHANGED
|
@@ -88,10 +88,7 @@ function applyReplacements(content, replacements, offset = 0) {
|
|
|
88
88
|
for (let i = replacements.length - 1; i >= 0; i--) {
|
|
89
89
|
const replacement = replacements[i];
|
|
90
90
|
const matchIndex = replacement.matchIndex - offset;
|
|
91
|
-
result =
|
|
92
|
-
result.substring(0, matchIndex) +
|
|
93
|
-
replacement.newText +
|
|
94
|
-
result.substring(matchIndex + replacement.matchLength);
|
|
91
|
+
result = result.substring(0, matchIndex) + replacement.newText + result.substring(matchIndex + replacement.matchLength);
|
|
95
92
|
}
|
|
96
93
|
return result;
|
|
97
94
|
}
|
package/dist/edit.js
CHANGED
|
@@ -20,14 +20,14 @@
|
|
|
20
20
|
* completed, the edit is real and is reported as success rather than a misleading "aborted".
|
|
21
21
|
*/
|
|
22
22
|
import { Buffer } from "node:buffer";
|
|
23
|
-
import { access as fsAccess, stat as fsStat, writeFile as fsWriteFile, } from "node:fs/promises";
|
|
24
23
|
import { constants } from "node:fs";
|
|
24
|
+
import { access as fsAccess, stat as fsStat, writeFile as fsWriteFile } from "node:fs/promises";
|
|
25
25
|
import { readFileBounded } from "./bounded-file.js";
|
|
26
|
+
import { applyEditsToNormalizedContent, detectLineEnding, generateDiffString, generateUnifiedPatch, normalizeToLF, restoreLineEndings, stripBom, } from "./edit-diff.js";
|
|
26
27
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
27
|
-
import { resolveToCwd } from "./path-utils.js";
|
|
28
28
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
29
29
|
import { DEFAULT_MAX_EDIT_FILE_BYTES, DEFAULT_MAX_EDIT_INPUT_BYTES, DEFAULT_MAX_EDITS, HARD_MAX_EDIT_FILE_BYTES, HARD_MAX_EDIT_INPUT_BYTES, HARD_MAX_EDITS, validateCodingLimit, } from "./limits.js";
|
|
30
|
-
import {
|
|
30
|
+
import { resolveToCwd } from "./path-utils.js";
|
|
31
31
|
const defaultEditOperations = {
|
|
32
32
|
readFile: (path, options) => readFileBounded(path, options.maxBytes, options.signal),
|
|
33
33
|
writeFile: (path, content, options) => fsWriteFile(path, content, { encoding: "utf-8", signal: options?.signal }),
|
|
@@ -196,9 +196,7 @@ export function createEditTool(cwd, options) {
|
|
|
196
196
|
return {
|
|
197
197
|
toolCallId,
|
|
198
198
|
name: "edit",
|
|
199
|
-
content: [
|
|
200
|
-
{ type: "text", text: `Successfully replaced ${edits.length} block(s) in ${prepared.path}.` },
|
|
201
|
-
],
|
|
199
|
+
content: [{ type: "text", text: `Successfully replaced ${edits.length} block(s) in ${prepared.path}.` }],
|
|
202
200
|
metadata: {
|
|
203
201
|
diff: diffResult.diff,
|
|
204
202
|
patch,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ExecutionAction, ExecutionPolicy } from "@arnilo/prism";
|
|
2
|
-
import type { ToolResult } from "@arnilo/prism";
|
|
1
|
+
import type { ExecutionAction, ExecutionPolicy, ToolResult } from "@arnilo/prism";
|
|
3
2
|
export declare function enforceExecutionPolicy(policy: ExecutionPolicy | undefined, action: ExecutionAction, toolCallId: string, toolName: string): Promise<{
|
|
4
3
|
allowed: true;
|
|
5
4
|
action: ExecutionAction;
|
package/dist/execution-policy.js
CHANGED
|
@@ -8,7 +8,7 @@ export async function enforceExecutionPolicy(policy, action, toolCallId, toolNam
|
|
|
8
8
|
}
|
|
9
9
|
catch (error) {
|
|
10
10
|
const message = error instanceof ExecutionDeniedError
|
|
11
|
-
? error.decision.reason ?? error.message
|
|
11
|
+
? (error.decision.reason ?? error.message)
|
|
12
12
|
: error instanceof Error
|
|
13
13
|
? error.message
|
|
14
14
|
: String(error);
|
|
@@ -19,8 +19,7 @@ function isMissingPathError(error) {
|
|
|
19
19
|
return (typeof error === "object" &&
|
|
20
20
|
error !== null &&
|
|
21
21
|
"code" in error &&
|
|
22
|
-
(error.code === "ENOENT" ||
|
|
23
|
-
error.code === "ENOTDIR"));
|
|
22
|
+
(error.code === "ENOENT" || error.code === "ENOTDIR"));
|
|
24
23
|
}
|
|
25
24
|
async function getMutationQueueKey(filePath) {
|
|
26
25
|
const resolvedPath = resolve(filePath);
|
package/dist/git-exec.js
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* runner (for example a sandbox `execFile` adapter) without changing tool code.
|
|
7
7
|
*/
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
|
-
import { access } from "node:fs/promises";
|
|
10
9
|
import { constants as fsConstants } from "node:fs";
|
|
10
|
+
import { access } from "node:fs/promises";
|
|
11
11
|
import { isAbsolute } from "node:path";
|
|
12
12
|
import { DEFAULT_GIT_TIMEOUT_MS, DEFAULT_MAX_GIT_OUTPUT_BYTES, HARD_GIT_TIMEOUT_MS, HARD_MAX_GIT_OUTPUT_BYTES, validateCodingLimit, } from "./limits.js";
|
|
13
13
|
export class GitError extends Error {
|
package/dist/git-tools.d.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Shell is never used internally; all Git invocations go through typed arg arrays.
|
|
6
6
|
*/
|
|
7
7
|
import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
|
|
8
|
-
import { type ArtifactWriter, type CreateGitOperationsOptions, type GitOperations } from "./git.js";
|
|
9
8
|
import { type CodingCheckToolOptions, type NamedCheckDefinition } from "./checks.js";
|
|
9
|
+
import { type ArtifactWriter, type CreateGitOperationsOptions, type GitOperations } from "./git.js";
|
|
10
10
|
export interface GitToolsOptions {
|
|
11
11
|
readonly executionPolicy?: ExecutionPolicy;
|
|
12
12
|
readonly gitPath?: string;
|
package/dist/git-tools.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { createCodingCheckTool } from "./checks.js";
|
|
1
2
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
2
3
|
import { createGitOperations, GitError, } from "./git.js";
|
|
3
|
-
import { createCodingCheckTool } from "./checks.js";
|
|
4
4
|
function errorResult(toolName, toolCallId, message) {
|
|
5
5
|
return {
|
|
6
6
|
toolCallId,
|
|
@@ -250,8 +250,7 @@ export function createGitWorktreeTool(cwd, options) {
|
|
|
250
250
|
signal: context.signal,
|
|
251
251
|
});
|
|
252
252
|
const text = action === "list"
|
|
253
|
-
? result.worktrees.map((w) => `${w.path}\t${w.branch ?? ""}\t${w.head ?? ""}`).join("\n") ||
|
|
254
|
-
"(no worktrees)"
|
|
253
|
+
? result.worktrees.map((w) => `${w.path}\t${w.branch ?? ""}\t${w.head ?? ""}`).join("\n") || "(no worktrees)"
|
|
255
254
|
: `ok action=${action} path=${result.path ?? ""}`;
|
|
256
255
|
return {
|
|
257
256
|
toolCallId,
|
|
@@ -430,9 +429,7 @@ export function createGitPrHandoffTool(cwd, options) {
|
|
|
430
429
|
const base = typeof args.base === "string" ? args.base : "";
|
|
431
430
|
const head = typeof args.head === "string" ? args.head : undefined;
|
|
432
431
|
const includeBundle = args.includeBundle === true;
|
|
433
|
-
const checks = Array.isArray(args.checks)
|
|
434
|
-
? args.checks
|
|
435
|
-
: undefined;
|
|
432
|
+
const checks = Array.isArray(args.checks) ? args.checks : undefined;
|
|
436
433
|
const policy = await enforceExecutionPolicy(options?.executionPolicy, {
|
|
437
434
|
kind: "git",
|
|
438
435
|
operation: "pr_handoff",
|
package/dist/git.d.ts
CHANGED
|
@@ -133,7 +133,7 @@ export interface CreateGitOperationsOptions extends CreateGitRunnerOptions, GitL
|
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
135
|
export declare function createGitOperations(options: CreateGitOperationsOptions): Promise<GitOperations>;
|
|
136
|
+
export type { BoundGitRunner, CreateGitRunnerOptions, GitExecRequest, GitExecResult, GitRunner } from "./git-exec.js";
|
|
137
|
+
export { createBoundGitRunner, GitError, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git-exec.js";
|
|
138
|
+
export type { GitStatusBranch, GitStatusEntry, GitStatusEntryKind, GitStatusResult } from "./git-status.js";
|
|
136
139
|
export { parsePorcelainV2 } from "./git-status.js";
|
|
137
|
-
export type { GitStatusResult, GitStatusEntry, GitStatusBranch, GitStatusEntryKind } from "./git-status.js";
|
|
138
|
-
export { GitError, SAFE_GIT_ENV, SAFE_GIT_CONFIG_ARGS, createBoundGitRunner, runGitCli, } from "./git-exec.js";
|
|
139
|
-
export type { GitRunner, GitExecRequest, GitExecResult, BoundGitRunner, CreateGitRunnerOptions } from "./git-exec.js";
|
package/dist/git.js
CHANGED
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
* `git check-ref-format` for refs, and safe config that disables hooks,
|
|
6
6
|
* external diff/textconv, pagers, and credential prompts by default.
|
|
7
7
|
*/
|
|
8
|
-
import { mkdtemp,
|
|
8
|
+
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
-
import { 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_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, 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_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, validateCodingLimit, } from "./limits.js";
|
|
12
11
|
import { createBoundGitRunner, GitError, gitRequireOk, gitText, } from "./git-exec.js";
|
|
13
12
|
import { parsePorcelainV2 } from "./git-status.js";
|
|
13
|
+
import { 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_PR_COMMITS, DEFAULT_MAX_PR_HANDOFF_BYTES, 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_PR_COMMITS, HARD_MAX_PR_HANDOFF_BYTES, validateCodingLimit, } from "./limits.js";
|
|
14
14
|
import { resolveToCwd } from "./path-utils.js";
|
|
15
15
|
export function resolveGitLimits(options) {
|
|
16
16
|
return {
|
|
@@ -77,7 +77,7 @@ function truncateLines(text, maxLines) {
|
|
|
77
77
|
const lineCount = lines.length;
|
|
78
78
|
if (lineCount <= maxLines)
|
|
79
79
|
return { text, truncated: false, lineCount };
|
|
80
|
-
const kept = lines.slice(0, maxLines).join("\n")
|
|
80
|
+
const kept = `${lines.slice(0, maxLines).join("\n")}\n`;
|
|
81
81
|
return { text: kept, truncated: true, lineCount };
|
|
82
82
|
}
|
|
83
83
|
async function withTempFile(prefix, contents, fn) {
|
|
@@ -292,9 +292,7 @@ export async function createGitOperations(options) {
|
|
|
292
292
|
? await ensureCleanOrCheckpoint(request.createCheckpoint, request.signal, `git apply ${request.action}`)
|
|
293
293
|
: undefined;
|
|
294
294
|
// Always check first for apply/reverse.
|
|
295
|
-
const checkArgs = request.action === "reverse"
|
|
296
|
-
? ["apply", "--reverse", "--check"]
|
|
297
|
-
: ["apply", "--check"];
|
|
295
|
+
const checkArgs = request.action === "reverse" ? ["apply", "--reverse", "--check"] : ["apply", "--check"];
|
|
298
296
|
const check = await runApply(checkArgs, filePath);
|
|
299
297
|
if (check.exitCode !== 0) {
|
|
300
298
|
const output = (gitText(check, "stderr") || gitText(check)).trim();
|
|
@@ -302,9 +300,7 @@ export async function createGitOperations(options) {
|
|
|
302
300
|
await restoreCheckpoint(checkpoint, request.signal).catch(() => undefined);
|
|
303
301
|
return { ok: false, checkpoint, restored: Boolean(checkpoint), output: output || "patch check failed" };
|
|
304
302
|
}
|
|
305
|
-
const applyArgs = request.action === "reverse"
|
|
306
|
-
? ["apply", "--reverse"]
|
|
307
|
-
: ["apply"];
|
|
303
|
+
const applyArgs = request.action === "reverse" ? ["apply", "--reverse"] : ["apply"];
|
|
308
304
|
const result = await runApply(applyArgs, filePath);
|
|
309
305
|
if (result.exitCode !== 0) {
|
|
310
306
|
const output = (gitText(result, "stderr") || gitText(result)).trim();
|
|
@@ -314,12 +310,14 @@ export async function createGitOperations(options) {
|
|
|
314
310
|
}
|
|
315
311
|
else {
|
|
316
312
|
// Best-effort restore of tracked files when no checkpoint was taken (clean tree).
|
|
317
|
-
await runner
|
|
313
|
+
await runner
|
|
314
|
+
.exec({
|
|
318
315
|
args: ["checkout", "--", "."],
|
|
319
316
|
cwd,
|
|
320
317
|
signal: request.signal,
|
|
321
318
|
maxOutputBytes: limits.maxOutputBytes,
|
|
322
|
-
})
|
|
319
|
+
})
|
|
320
|
+
.catch(() => undefined);
|
|
323
321
|
restored = true;
|
|
324
322
|
}
|
|
325
323
|
return { ok: false, checkpoint, restored, output: output || `apply failed with exit ${result.exitCode}` };
|
|
@@ -378,12 +376,14 @@ export async function createGitOperations(options) {
|
|
|
378
376
|
}
|
|
379
377
|
catch (error) {
|
|
380
378
|
// Reset index for the attempted paths; never drop pre-existing dirty work unless checkpointed.
|
|
381
|
-
await runner
|
|
379
|
+
await runner
|
|
380
|
+
.exec({
|
|
382
381
|
args: ["reset", "-q", "HEAD", "--", ...paths],
|
|
383
382
|
cwd,
|
|
384
383
|
signal: request.signal,
|
|
385
384
|
maxOutputBytes: limits.maxOutputBytes,
|
|
386
|
-
})
|
|
385
|
+
})
|
|
386
|
+
.catch(() => undefined);
|
|
387
387
|
if (checkpoint)
|
|
388
388
|
await restoreCheckpoint(checkpoint, request.signal).catch(() => undefined);
|
|
389
389
|
throw error;
|
|
@@ -490,6 +490,6 @@ export async function createGitOperations(options) {
|
|
|
490
490
|
}
|
|
491
491
|
return { status, diff, branch, worktree, apply, commit, prHandoff };
|
|
492
492
|
}
|
|
493
|
+
export { createBoundGitRunner, GitError, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git-exec.js";
|
|
493
494
|
export { parsePorcelainV2 } from "./git-status.js";
|
|
494
|
-
export { GitError, SAFE_GIT_ENV, SAFE_GIT_CONFIG_ARGS, createBoundGitRunner, runGitCli, } from "./git-exec.js";
|
|
495
495
|
//# sourceMappingURL=git.js.map
|
package/dist/goal-verify.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { OwnershipScope, SecretRedactor } from "@arnilo/prism";
|
|
6
6
|
import { type WorkflowCheckpointAdapter, type WorkflowEvent, type WorkflowResumeValidator, type WorkflowRunResult } from "@arnilo/prism-workflows";
|
|
7
|
-
import { type
|
|
7
|
+
import { type CodingCheckpointMetadata, type CodingCheckSummary, type CodingHandoffSummary } from "./coding-checkpoint.js";
|
|
8
8
|
export declare const CODING_GOAL_VERIFY_WORKFLOW_ID: "coding-goal-verify";
|
|
9
9
|
export declare const CODING_GOAL_VERIFY_REVISION: "1";
|
|
10
10
|
export declare const CODING_GOAL_VERIFY_SUSPEND_REASON: "approve-coding-goal-verify";
|
package/dist/goal-verify.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineWorkflow, functionNode, resumeWorkflow, runWorkflow, suspend, } from "@arnilo/prism-workflows";
|
|
2
|
-
import {
|
|
2
|
+
import { assertCodingResumeAllowed, buildCodingCheckpointMetadata, CODING_STATE_KEY, codingCheckpointStatePatch, codingPlanPathForTask, createCodingPlanMarkdown, fingerprintJson, parseCodingPlanTodos, readCodingCheckpointFromState, readCodingPlanFile, writeCodingPlanFile, } from "./coding-checkpoint.js";
|
|
3
3
|
import { DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_PR_HANDOFF_BYTES } from "./limits.js";
|
|
4
4
|
export const CODING_GOAL_VERIFY_WORKFLOW_ID = "coding-goal-verify";
|
|
5
5
|
export const CODING_GOAL_VERIFY_REVISION = "1";
|
|
@@ -93,10 +93,7 @@ export function createCodingGoalVerifyWorkflow(options) {
|
|
|
93
93
|
const coding = requireCoding(ctx.state);
|
|
94
94
|
const checks = normalizeChecks(await Promise.all(options.checks.map((name) => options.runCheck(name))));
|
|
95
95
|
const failed = checks.some((check) => check.exitCode !== 0);
|
|
96
|
-
const done = new Set([
|
|
97
|
-
"plan",
|
|
98
|
-
...options.checks.map((name) => `check-${name}`),
|
|
99
|
-
]);
|
|
96
|
+
const done = new Set(["plan", ...options.checks.map((name) => `check-${name}`)]);
|
|
100
97
|
const todos = markTodos(coding.todos.length ? coding.todos : defaultTodos(options.checks), done);
|
|
101
98
|
const markdown = createCodingPlanMarkdown({
|
|
102
99
|
title: options.title,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
6
|
-
export type {
|
|
1
|
+
export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } from "./artifacts.js";
|
|
2
|
+
export type { AskUserDecisionAnswer, AskUserDecisionHandler, AskUserDecisionOption, AskUserDecisionRequest, AskUserDecisionSelectionMode, AskUserDecisionSuspendData, AskUserDecisionToolOptions, ResolvedAskUserDecisionAnswer, ResolvedAskUserDecisionLimits, SuspendAskUserDecisionOptions, } from "./ask-user-decision.js";
|
|
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
|
+
export type { CodingCheckToolOptions, NamedCheckDefinition } from "./checks.js";
|
|
5
|
+
export { createCodingCheckTool } from "./checks.js";
|
|
6
|
+
export type { CodingArtifactKind, CodingArtifactRef, CodingCheckpointLimitOptions, CodingCheckpointMetadata, CodingCheckSummary, CodingFingerprints, CodingHandoffSummary, CodingTaskStatus, CodingTodoItem, ResolvedCodingCheckpointLimits, } from "./coding-checkpoint.js";
|
|
7
|
+
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
|
+
export type { Edit, EditOperations, EditToolDetails, EditToolOptions } from "./edit.js";
|
|
7
9
|
export { createEditTool } from "./edit.js";
|
|
8
|
-
export type {
|
|
9
|
-
export {
|
|
10
|
-
export type { ListToolOptions } from "./list.js";
|
|
11
|
-
export { createRepoSearchTool } from "./search.js";
|
|
12
|
-
export type { SearchToolOptions } from "./search.js";
|
|
13
|
-
export { createLocalRepositoryOperations, resolveRepositoryLimits, compileSearchPattern, isBinaryBuffer, resolveRepoPath, toRepoRelative, RepositoryError, DEFAULT_REPO_EXCLUDE, } from "./repository.js";
|
|
14
|
-
export type { RepoEntryKind, RepoListEntry, RepositoryListRequest, RepositoryListResult, RepositorySearchMatch, RepositorySearchRequest, RepositorySearchResult, RepositoryOperations, RepositoryLimitOptions, ResolvedRepositoryLimits, } from "./repository.js";
|
|
15
|
-
export { createGitOperations, resolveGitLimits, parsePorcelainV2, GitError, SAFE_GIT_ENV, SAFE_GIT_CONFIG_ARGS, createBoundGitRunner, runGitCli, } from "./git.js";
|
|
16
|
-
export type { GitOperations, GitLimitOptions, ResolvedGitLimits, ArtifactReference, ArtifactWriter, PrHandoff, CreateGitOperationsOptions, GitStatusResult, GitStatusEntry, GitStatusBranch, GitStatusEntryKind, GitRunner, GitExecRequest, GitExecResult, BoundGitRunner, CreateGitRunnerOptions, } from "./git.js";
|
|
17
|
-
export { createGitTools, createGitStatusTool, createGitDiffTool, createGitBranchTool, createGitWorktreeTool, createGitApplyTool, createGitCommitTool, createGitPrHandoffTool, } from "./git-tools.js";
|
|
10
|
+
export type { ArtifactReference, ArtifactWriter, BoundGitRunner, CreateGitOperationsOptions, CreateGitRunnerOptions, GitExecRequest, GitExecResult, GitLimitOptions, GitOperations, GitRunner, GitStatusBranch, GitStatusEntry, GitStatusEntryKind, GitStatusResult, PrHandoff, ResolvedGitLimits, } from "./git.js";
|
|
11
|
+
export { createBoundGitRunner, createGitOperations, GitError, parsePorcelainV2, resolveGitLimits, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git.js";
|
|
18
12
|
export type { GitToolsOptions } from "./git-tools.js";
|
|
19
|
-
export {
|
|
20
|
-
export type { CodingCheckToolOptions, NamedCheckDefinition } from "./checks.js";
|
|
21
|
-
export { ASK_USER_DECISION_RATIONALE_COUNT, ASK_USER_DECISION_SUSPEND_REASON, ASK_USER_DECISION_TOOL_NAME, 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, askUserDecisionResumeSchema, createAskUserDecisionResumeValidator, createAskUserDecisionTool, parseAskUserDecisionArgs, resolveAskUserDecisionAnswer, resolveAskUserDecisionLimits, suspendAskUserDecision, toAskUserDecisionSuspendData, validateAskUserDecisionAgentResume, validateAskUserDecisionResume, } from "./ask-user-decision.js";
|
|
22
|
-
export type { AskUserDecisionAnswer, AskUserDecisionHandler, AskUserDecisionOption, AskUserDecisionRequest, AskUserDecisionSelectionMode, AskUserDecisionSuspendData, AskUserDecisionToolOptions, ResolvedAskUserDecisionAnswer, ResolvedAskUserDecisionLimits, SuspendAskUserDecisionOptions, } from "./ask-user-decision.js";
|
|
23
|
-
export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } from "./artifacts.js";
|
|
24
|
-
export { CODING_CHECKPOINT_SCHEMA_VERSION, CODING_STATE_KEY, CodingCheckpointError, assertCodingResumeAllowed, buildCodingCheckpointMetadata, codingCheckpointStatePatch, codingPlanPathForTask, createCodingArtifactRef, createCodingPlanMarkdown, fingerprintJson, parseCodingPlanTodos, readCodingCheckpointFromState, readCodingPlanFile, resolveCodingCheckpointLimits, validateCodingCheckpointMetadata, verifyCodingArtifactBytes, writeCodingPlanFile, } from "./coding-checkpoint.js";
|
|
25
|
-
export type { CodingArtifactKind, CodingArtifactRef, CodingCheckSummary, CodingCheckpointLimitOptions, CodingCheckpointMetadata, CodingFingerprints, CodingHandoffSummary, CodingTaskStatus, CodingTodoItem, ResolvedCodingCheckpointLimits, } from "./coding-checkpoint.js";
|
|
26
|
-
export { CODING_GOAL_VERIFY_REVISION, CODING_GOAL_VERIFY_SUSPEND_REASON, CODING_GOAL_VERIFY_WORKFLOW_ID, CodingGoalVerifyError, createCodingGoalVerifyWorkflow, runCodingGoalVerify, } from "./goal-verify.js";
|
|
13
|
+
export { createGitApplyTool, createGitBranchTool, createGitCommitTool, createGitDiffTool, createGitPrHandoffTool, createGitStatusTool, createGitTools, createGitWorktreeTool, } from "./git-tools.js";
|
|
27
14
|
export type { CodingGoalVerifyApproval, RunCodingGoalVerifyOptions, } from "./goal-verify.js";
|
|
28
|
-
export {
|
|
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 type { ListToolOptions } from "./list.js";
|
|
17
|
+
export { createRepoListTool } from "./list.js";
|
|
18
|
+
export type { ReadOperations, ReadTextOptions, ReadTextResult, ReadToolOptions, TransformImage, TransformImageInput, } from "./read.js";
|
|
19
|
+
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";
|
|
21
|
+
export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
|
|
22
|
+
export type { SearchToolOptions } from "./search.js";
|
|
23
|
+
export { createRepoSearchTool } from "./search.js";
|
|
24
|
+
export type { BashExecOptions, BashOperations, BashSpawnContext, BashSpawnHook, ShellConfig, ShellToolOptions, } from "./shell.js";
|
|
25
|
+
export { createLocalBashOperations, createShellTool, getShellConfig, killProcessTree, waitForChildProcess, } from "./shell.js";
|
|
26
|
+
export type { WriteOperations, WriteToolOptions } from "./write.js";
|
|
27
|
+
export { createWriteTool } from "./write.js";
|
|
29
28
|
export { enforceExecutionPolicy } from "./execution-policy.js";
|
|
30
|
-
export {
|
|
29
|
+
export { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
30
|
+
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
31
|
import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
|
|
32
|
-
import type { ShellToolOptions } from "./shell.js";
|
|
33
|
-
import type { ReadToolOptions } from "./read.js";
|
|
34
|
-
import type { WriteToolOptions } from "./write.js";
|
|
35
32
|
import type { EditToolOptions } from "./edit.js";
|
|
36
33
|
import type { ListToolOptions } from "./list.js";
|
|
37
|
-
import type {
|
|
34
|
+
import type { ReadToolOptions } from "./read.js";
|
|
38
35
|
import type { RepositoryLimitOptions, RepositoryOperations } from "./repository.js";
|
|
36
|
+
import type { SearchToolOptions } from "./search.js";
|
|
37
|
+
import type { ShellToolOptions } from "./shell.js";
|
|
38
|
+
import type { WriteToolOptions } from "./write.js";
|
|
39
39
|
/** Per-tool options combined for the aggregator factories. */
|
|
40
40
|
export interface ToolsOptions {
|
|
41
41
|
/** Shared execution policy applied to every coding tool unless overridden per tool. */
|
package/dist/index.js
CHANGED
|
@@ -4,30 +4,30 @@
|
|
|
4
4
|
// `ToolDefinition`s that hosts register into a `ToolRegistry` (e.g.
|
|
5
5
|
// `createToolRegistry(createCodingTools(cwd))`). No tools are auto-registered — import what you need.
|
|
6
6
|
// --- per-tool factories & types ---
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
7
|
+
export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } from "./artifacts.js";
|
|
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
|
+
export { createCodingCheckTool } from "./checks.js";
|
|
10
|
+
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";
|
|
10
11
|
export { createEditTool } from "./edit.js";
|
|
12
|
+
export { createBoundGitRunner, createGitOperations, GitError, parsePorcelainV2, resolveGitLimits, runGitCli, SAFE_GIT_CONFIG_ARGS, SAFE_GIT_ENV, } from "./git.js";
|
|
13
|
+
export { createGitApplyTool, createGitBranchTool, createGitCommitTool, createGitDiffTool, createGitPrHandoffTool, createGitStatusTool, createGitTools, createGitWorktreeTool, } from "./git-tools.js";
|
|
14
|
+
export { CODING_GOAL_VERIFY_REVISION, CODING_GOAL_VERIFY_SUSPEND_REASON, CODING_GOAL_VERIFY_WORKFLOW_ID, CodingGoalVerifyError, createCodingGoalVerifyWorkflow, runCodingGoalVerify, } from "./goal-verify.js";
|
|
11
15
|
export { createRepoListTool } from "./list.js";
|
|
16
|
+
export { createReadTool, DEFAULT_MAX_IMAGE_BYTES, detectSupportedImageMimeType, detectSupportedImageMimeTypeFromFile, } from "./read.js";
|
|
17
|
+
export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
|
|
12
18
|
export { createRepoSearchTool } from "./search.js";
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export { createGitTools, createGitStatusTool, createGitDiffTool, createGitBranchTool, createGitWorktreeTool, createGitApplyTool, createGitCommitTool, createGitPrHandoffTool, } from "./git-tools.js";
|
|
16
|
-
export { createCodingCheckTool } from "./checks.js";
|
|
17
|
-
export { ASK_USER_DECISION_RATIONALE_COUNT, ASK_USER_DECISION_SUSPEND_REASON, ASK_USER_DECISION_TOOL_NAME, 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, askUserDecisionResumeSchema, createAskUserDecisionResumeValidator, createAskUserDecisionTool, parseAskUserDecisionArgs, resolveAskUserDecisionAnswer, resolveAskUserDecisionLimits, suspendAskUserDecision, toAskUserDecisionSuspendData, validateAskUserDecisionAgentResume, validateAskUserDecisionResume, } from "./ask-user-decision.js";
|
|
18
|
-
export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } from "./artifacts.js";
|
|
19
|
-
export { CODING_CHECKPOINT_SCHEMA_VERSION, CODING_STATE_KEY, CodingCheckpointError, assertCodingResumeAllowed, buildCodingCheckpointMetadata, codingCheckpointStatePatch, codingPlanPathForTask, createCodingArtifactRef, createCodingPlanMarkdown, fingerprintJson, parseCodingPlanTodos, readCodingCheckpointFromState, readCodingPlanFile, resolveCodingCheckpointLimits, validateCodingCheckpointMetadata, verifyCodingArtifactBytes, writeCodingPlanFile, } from "./coding-checkpoint.js";
|
|
20
|
-
export { CODING_GOAL_VERIFY_REVISION, CODING_GOAL_VERIFY_SUSPEND_REASON, CODING_GOAL_VERIFY_WORKFLOW_ID, CodingGoalVerifyError, createCodingGoalVerifyWorkflow, runCodingGoalVerify, } from "./goal-verify.js";
|
|
19
|
+
export { createLocalBashOperations, createShellTool, getShellConfig, killProcessTree, waitForChildProcess, } from "./shell.js";
|
|
20
|
+
export { createWriteTool } from "./write.js";
|
|
21
21
|
// --- generic primitives (re-exported for hosts that want them) ---
|
|
22
|
-
export { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
23
22
|
export { enforceExecutionPolicy } from "./execution-policy.js";
|
|
24
|
-
export {
|
|
25
|
-
|
|
26
|
-
import { createReadTool } from "./read.js";
|
|
27
|
-
import { createWriteTool } from "./write.js";
|
|
23
|
+
export { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
24
|
+
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";
|
|
28
25
|
import { createEditTool } from "./edit.js";
|
|
29
26
|
import { createRepoListTool } from "./list.js";
|
|
27
|
+
import { createReadTool } from "./read.js";
|
|
30
28
|
import { createRepoSearchTool } from "./search.js";
|
|
29
|
+
import { createShellTool } from "./shell.js";
|
|
30
|
+
import { createWriteTool } from "./write.js";
|
|
31
31
|
function withSharedExecutionPolicy(toolOptions, shared) {
|
|
32
32
|
if (!shared)
|
|
33
33
|
return (toolOptions ?? {});
|
package/dist/list.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
2
|
-
import { createLocalRepositoryOperations, resolveRepositoryLimits, RepositoryError, } from "./repository.js";
|
|
3
2
|
import { HARD_MAX_REPO_DEPTH, HARD_MAX_REPO_RESULTS, validateCodingLimit, validateCodingLimitAllowZero } from "./limits.js";
|
|
3
|
+
import { createLocalRepositoryOperations, RepositoryError, resolveRepositoryLimits, } from "./repository.js";
|
|
4
4
|
function errorResult(toolCallId, message) {
|
|
5
5
|
return {
|
|
6
6
|
toolCallId,
|
|
@@ -11,9 +11,7 @@ function errorResult(toolCallId, message) {
|
|
|
11
11
|
}
|
|
12
12
|
function formatListText(result) {
|
|
13
13
|
if (result.entries.length === 0) {
|
|
14
|
-
return result.truncated
|
|
15
|
-
? `[truncated by ${result.truncatedBy ?? "limit"} before any entries]`
|
|
16
|
-
: "(no entries)";
|
|
14
|
+
return result.truncated ? `[truncated by ${result.truncatedBy ?? "limit"} before any entries]` : "(no entries)";
|
|
17
15
|
}
|
|
18
16
|
const lines = result.entries.map((entry) => {
|
|
19
17
|
const size = entry.size !== undefined ? `\t${entry.size}` : "";
|
|
@@ -131,11 +129,7 @@ export function createRepoListTool(cwd, options) {
|
|
|
131
129
|
};
|
|
132
130
|
}
|
|
133
131
|
catch (error) {
|
|
134
|
-
const message = error instanceof RepositoryError
|
|
135
|
-
? error.message
|
|
136
|
-
: error instanceof Error
|
|
137
|
-
? error.message
|
|
138
|
-
: String(error);
|
|
132
|
+
const message = error instanceof RepositoryError ? error.message : error instanceof Error ? error.message : String(error);
|
|
139
133
|
return errorResult(toolCallId, message);
|
|
140
134
|
}
|
|
141
135
|
},
|
package/dist/path-utils.js
CHANGED
|
@@ -98,7 +98,7 @@ export function resolveReadPath(filePath, cwd) {
|
|
|
98
98
|
}
|
|
99
99
|
export async function resolveReadPathAsync(filePath, cwd) {
|
|
100
100
|
const resolved = resolveToCwd(filePath, cwd);
|
|
101
|
-
if (
|
|
101
|
+
if (await pathExists(resolved))
|
|
102
102
|
return resolved;
|
|
103
103
|
const amPmVariant = tryMacOSScreenshotPath(resolved);
|
|
104
104
|
if (amPmVariant !== resolved && (await pathExists(amPmVariant)))
|
package/dist/read.js
CHANGED
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import { Buffer } from "node:buffer";
|
|
23
23
|
import { constants } from "node:fs";
|
|
24
|
-
import { access as fsAccess,
|
|
24
|
+
import { access as fsAccess, stat as fsStat, open } from "node:fs/promises";
|
|
25
25
|
import { readFileBounded } from "./bounded-file.js";
|
|
26
26
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
27
|
-
import { resolveReadPathAsync } from "./path-utils.js";
|
|
28
27
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_IMAGE_BYTES, DEFAULT_MAX_LINES, DEFAULT_MAX_TEXT_SCAN_BYTES, HARD_MAX_BYTES, HARD_MAX_IMAGE_BYTES, HARD_MAX_LINES, HARD_MAX_TEXT_SCAN_BYTES, validateCodingLimit, } from "./limits.js";
|
|
28
|
+
import { resolveReadPathAsync } from "./path-utils.js";
|
|
29
29
|
import { formatSize } from "./truncate.js";
|
|
30
30
|
// --- magic-byte image MIME detection (faithful port of pi utils/mime.js, pure JS, no deps) ---
|
|
31
31
|
const IMAGE_TYPE_SNIFF_BYTES = 4100;
|
|
@@ -64,9 +64,7 @@ export async function detectSupportedImageMimeTypeFromFile(filePath) {
|
|
|
64
64
|
}
|
|
65
65
|
function isPng(buffer) {
|
|
66
66
|
// First chunk after the 8-byte signature must be a 13-byte IHDR.
|
|
67
|
-
return
|
|
68
|
-
readUint32BE(buffer, PNG_SIGNATURE.length) === 13 &&
|
|
69
|
-
startsWithAscii(buffer, 12, "IHDR"));
|
|
67
|
+
return buffer.length >= 16 && readUint32BE(buffer, PNG_SIGNATURE.length) === 13 && startsWithAscii(buffer, 12, "IHDR");
|
|
70
68
|
}
|
|
71
69
|
function isAnimatedPng(buffer) {
|
|
72
70
|
// Walk PNG chunks; an acTL chunk before the first IDAT marks an animated (APNG) image.
|
|
@@ -118,16 +116,10 @@ function readUint16LE(buffer, offset) {
|
|
|
118
116
|
return (buffer[offset] ?? 0) + ((buffer[offset + 1] ?? 0) << 8);
|
|
119
117
|
}
|
|
120
118
|
function readUint32BE(buffer, offset) {
|
|
121
|
-
return ((buffer[offset] ?? 0) * 0x1000000 +
|
|
122
|
-
((buffer[offset + 1] ?? 0) << 16) +
|
|
123
|
-
((buffer[offset + 2] ?? 0) << 8) +
|
|
124
|
-
(buffer[offset + 3] ?? 0));
|
|
119
|
+
return ((buffer[offset] ?? 0) * 0x1000000 + ((buffer[offset + 1] ?? 0) << 16) + ((buffer[offset + 2] ?? 0) << 8) + (buffer[offset + 3] ?? 0));
|
|
125
120
|
}
|
|
126
121
|
function readUint32LE(buffer, offset) {
|
|
127
|
-
return ((buffer[offset] ?? 0) +
|
|
128
|
-
((buffer[offset + 1] ?? 0) << 8) +
|
|
129
|
-
((buffer[offset + 2] ?? 0) << 16) +
|
|
130
|
-
(buffer[offset + 3] ?? 0) * 0x1000000);
|
|
122
|
+
return ((buffer[offset] ?? 0) + ((buffer[offset + 1] ?? 0) << 8) + ((buffer[offset + 2] ?? 0) << 16) + (buffer[offset + 3] ?? 0) * 0x1000000);
|
|
131
123
|
}
|
|
132
124
|
function startsWith(buffer, bytes) {
|
|
133
125
|
if (buffer.length < bytes.length)
|
|
@@ -339,9 +331,7 @@ export function createReadTool(cwd, options) {
|
|
|
339
331
|
}
|
|
340
332
|
try {
|
|
341
333
|
const startLine = validateCodingLimit("offset", offset ?? 1, Number.MAX_SAFE_INTEGER);
|
|
342
|
-
const requestedLines = limit === undefined
|
|
343
|
-
? undefined
|
|
344
|
-
: validateCodingLimit("limit", limit, HARD_MAX_LINES);
|
|
334
|
+
const requestedLines = limit === undefined ? undefined : validateCodingLimit("limit", limit, HARD_MAX_LINES);
|
|
345
335
|
const absolutePath = await resolveReadPathAsync(path, cwd);
|
|
346
336
|
const policyCheck = await enforceExecutionPolicy(options?.executionPolicy, {
|
|
347
337
|
kind: "read",
|
package/dist/repository.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded repository walk primitives for list/search tools.
|
|
3
|
+
*
|
|
4
|
+
* Streams the tree with Node `opendir` / `lstat`; never follows symlink escapes,
|
|
5
|
+
* rejects devices/FIFOs/sockets for descent, and charges finite depth/entry/file
|
|
6
|
+
* limits before retaining the next result. No glob/index/watcher dependency.
|
|
7
|
+
*/
|
|
1
8
|
export type RepoEntryKind = "file" | "directory" | "symlink" | "other";
|
|
2
9
|
export interface RepoListEntry {
|
|
3
10
|
readonly path: string;
|
package/dist/repository.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* rejects devices/FIFOs/sockets for descent, and charges finite depth/entry/file
|
|
6
6
|
* limits before retaining the next result. No glob/index/watcher dependency.
|
|
7
7
|
*/
|
|
8
|
-
import { open, opendir,
|
|
8
|
+
import { lstat, open, opendir, realpath } from "node:fs/promises";
|
|
9
9
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
10
10
|
import { DEFAULT_BINARY_SNIFF_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, 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, validateCodingLimit, validateCodingLimitAllowZero, } from "./limits.js";
|
|
11
11
|
import { resolveToCwd } from "./path-utils.js";
|
|
@@ -278,9 +278,7 @@ async function listLocal(request, defaults) {
|
|
|
278
278
|
kind = "symlink";
|
|
279
279
|
else if (startStat.isFile())
|
|
280
280
|
kind = "file";
|
|
281
|
-
const entry = kind === "file"
|
|
282
|
-
? { path: resolved.relative, kind, size: startStat.size }
|
|
283
|
-
: { path: resolved.relative, kind };
|
|
281
|
+
const entry = kind === "file" ? { path: resolved.relative, kind, size: startStat.size } : { path: resolved.relative, kind };
|
|
284
282
|
scannedEntries = 1;
|
|
285
283
|
scannedFiles = kind === "file" ? 1 : 0;
|
|
286
284
|
if (offset === 0 && maxResults > 0)
|
package/dist/search.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
2
|
-
import { HARD_MAX_SEARCH_CONTEXT_LINES, HARD_MAX_SEARCH_MATCHES, validateCodingLimit, validateCodingLimitAllowZero
|
|
3
|
-
import { createLocalRepositoryOperations,
|
|
2
|
+
import { HARD_MAX_SEARCH_CONTEXT_LINES, HARD_MAX_SEARCH_MATCHES, validateCodingLimit, validateCodingLimitAllowZero } from "./limits.js";
|
|
3
|
+
import { createLocalRepositoryOperations, RepositoryError, resolveRepositoryLimits, } from "./repository.js";
|
|
4
4
|
import { truncateLine } from "./truncate.js";
|
|
5
5
|
function errorResult(toolCallId, message) {
|
|
6
6
|
return {
|
|
@@ -26,9 +26,7 @@ function formatMatch(match) {
|
|
|
26
26
|
}
|
|
27
27
|
function formatSearchText(result) {
|
|
28
28
|
if (result.matches.length === 0) {
|
|
29
|
-
return result.truncated
|
|
30
|
-
? `[truncated by ${result.truncatedBy ?? "limit"} before any matches]`
|
|
31
|
-
: "(no matches)";
|
|
29
|
+
return result.truncated ? `[truncated by ${result.truncatedBy ?? "limit"} before any matches]` : "(no matches)";
|
|
32
30
|
}
|
|
33
31
|
const body = result.matches.map(formatMatch).join("\n");
|
|
34
32
|
if (!result.truncated)
|
|
@@ -153,11 +151,7 @@ export function createRepoSearchTool(cwd, options) {
|
|
|
153
151
|
};
|
|
154
152
|
}
|
|
155
153
|
catch (error) {
|
|
156
|
-
const message = error instanceof RepositoryError
|
|
157
|
-
? error.message
|
|
158
|
-
: error instanceof Error
|
|
159
|
-
? error.message
|
|
160
|
-
: String(error);
|
|
154
|
+
const message = error instanceof RepositoryError ? error.message : error instanceof Error ? error.message : String(error);
|
|
161
155
|
return errorResult(toolCallId, message);
|
|
162
156
|
}
|
|
163
157
|
},
|
package/dist/shell.d.ts
CHANGED
|
@@ -55,6 +55,9 @@ export interface ShellToolOptions {
|
|
|
55
55
|
shellPath?: string;
|
|
56
56
|
/** Hook to adjust command, cwd, or env before execution. */
|
|
57
57
|
spawnHook?: BashSpawnHook;
|
|
58
|
+
/** Restrict the process environment cloned for the spawn hook / child process to these
|
|
59
|
+
* names (e.g. scrub secrets). Unset keeps the full `process.env` clone. */
|
|
60
|
+
envAllowlist?: readonly string[];
|
|
58
61
|
/** Max lines kept in the tail snapshot (default 2000). */
|
|
59
62
|
maxLines?: number;
|
|
60
63
|
/** Max bytes kept in the tail snapshot (default 50KB). */
|
package/dist/shell.js
CHANGED
|
@@ -24,11 +24,23 @@ import { spawn } from "node:child_process";
|
|
|
24
24
|
import { constants, existsSync } from "node:fs";
|
|
25
25
|
import { access as fsAccess } from "node:fs/promises";
|
|
26
26
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
27
|
-
import { OutputAccumulator } from "./output-accumulator.js";
|
|
28
27
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, DEFAULT_MAX_TOTAL_OUTPUT_BYTES, DEFAULT_SHELL_TIMEOUT_SECONDS, HARD_MAX_BYTES, HARD_MAX_LINES, HARD_MAX_TOTAL_OUTPUT_BYTES, HARD_SHELL_TIMEOUT_SECONDS, validateCodingLimit, } from "./limits.js";
|
|
28
|
+
import { OutputAccumulator } from "./output-accumulator.js";
|
|
29
29
|
import { formatSize } from "./truncate.js";
|
|
30
30
|
const EXIT_STDIO_GRACE_MS = 100;
|
|
31
31
|
// --- spawn internals (re-ported from pi utils/shell.js + utils/child-process.js) ---
|
|
32
|
+
/** Clone the process environment, optionally restricted to an allowlist of names. */
|
|
33
|
+
function pickSpawnEnv(allowlist) {
|
|
34
|
+
if (!allowlist)
|
|
35
|
+
return { ...process.env };
|
|
36
|
+
const env = {};
|
|
37
|
+
for (const name of allowlist) {
|
|
38
|
+
const value = process.env[name];
|
|
39
|
+
if (value !== undefined)
|
|
40
|
+
env[name] = value;
|
|
41
|
+
}
|
|
42
|
+
return env;
|
|
43
|
+
}
|
|
32
44
|
/** Resolve the shell binary + args. shellPath → SHELL env → /bin/bash → sh. */
|
|
33
45
|
export function getShellConfig(customShellPath) {
|
|
34
46
|
if (customShellPath) {
|
|
@@ -284,9 +296,10 @@ export function createShellTool(cwd, options) {
|
|
|
284
296
|
return { toolCallId, name: "shell", content: [{ type: "text", text: message }], error: { message } };
|
|
285
297
|
}
|
|
286
298
|
const resolvedCommand = commandPrefix ? `${commandPrefix}\n${command}` : command;
|
|
299
|
+
const baseEnv = pickSpawnEnv(options?.envAllowlist);
|
|
287
300
|
let spawnContext = spawnHook
|
|
288
|
-
? spawnHook({ command: resolvedCommand, cwd, env:
|
|
289
|
-
: { command: resolvedCommand, cwd, env:
|
|
301
|
+
? spawnHook({ command: resolvedCommand, cwd, env: baseEnv })
|
|
302
|
+
: { command: resolvedCommand, cwd, env: baseEnv };
|
|
290
303
|
const policyCheck = await enforceExecutionPolicy(options?.executionPolicy, {
|
|
291
304
|
kind: "shell",
|
|
292
305
|
operation: "execute",
|
|
@@ -309,9 +322,7 @@ export function createShellTool(cwd, options) {
|
|
|
309
322
|
onLimit: () => outputAbort.abort("output-limit"),
|
|
310
323
|
onStorageError: () => outputAbort.abort("output-storage-error"),
|
|
311
324
|
});
|
|
312
|
-
const signal = context.signal
|
|
313
|
-
? AbortSignal.any([context.signal, outputAbort.signal])
|
|
314
|
-
: outputAbort.signal;
|
|
325
|
+
const signal = context.signal ? AbortSignal.any([context.signal, outputAbort.signal]) : outputAbort.signal;
|
|
315
326
|
let acceptingOutput = true;
|
|
316
327
|
const handleData = (data) => {
|
|
317
328
|
if (acceptingOutput)
|
|
@@ -399,7 +410,9 @@ export function createShellTool(cwd, options) {
|
|
|
399
410
|
try {
|
|
400
411
|
await output.cleanupTempFile();
|
|
401
412
|
}
|
|
402
|
-
catch {
|
|
413
|
+
catch {
|
|
414
|
+
/* retain primary error */
|
|
415
|
+
}
|
|
403
416
|
const message = err instanceof Error ? err.message : String(err);
|
|
404
417
|
return { toolCallId, name: "shell", content: [{ type: "text", text: message }], error: { message } };
|
|
405
418
|
}
|
package/dist/truncate.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Never returns partial lines (except the documented tail single-line edge case).
|
|
11
11
|
*/
|
|
12
|
-
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, HARD_MAX_BYTES, HARD_MAX_LINES, validateCodingLimit
|
|
12
|
+
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, HARD_MAX_BYTES, HARD_MAX_LINES, validateCodingLimit } from "./limits.js";
|
|
13
13
|
export { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES } from "./limits.js";
|
|
14
14
|
/**
|
|
15
15
|
* Default char cap for {@link truncateLine}. pi names this GREP_MAX_LINE_LENGTH
|
package/dist/write.js
CHANGED
|
@@ -18,9 +18,9 @@ import { Buffer } from "node:buffer";
|
|
|
18
18
|
import { mkdir as fsMkdir, writeFile as fsWriteFile } from "node:fs/promises";
|
|
19
19
|
import { dirname } from "node:path";
|
|
20
20
|
import { enforceExecutionPolicy } from "./execution-policy.js";
|
|
21
|
-
import { resolveToCwd } from "./path-utils.js";
|
|
22
21
|
import { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
23
|
-
import { DEFAULT_MAX_WRITE_BYTES, HARD_MAX_WRITE_BYTES, validateCodingLimit
|
|
22
|
+
import { DEFAULT_MAX_WRITE_BYTES, HARD_MAX_WRITE_BYTES, validateCodingLimit } from "./limits.js";
|
|
23
|
+
import { resolveToCwd } from "./path-utils.js";
|
|
24
24
|
const defaultWriteOperations = {
|
|
25
25
|
writeFile: (path, content, options) => fsWriteFile(path, content, { encoding: "utf-8", signal: options?.signal }),
|
|
26
26
|
mkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => { }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism-coding-agent",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Optional coding-agent tools (shell, read, write, edit, repo_list, repo_search, opt-in Git/check/ask-user-decision, and durable plan/checkpoint helpers) package for Prism.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"diff": "^9.0.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@arnilo/prism": "0.0.
|
|
32
|
-
"@arnilo/prism-workflows": "0.0.
|
|
31
|
+
"@arnilo/prism": "0.0.17",
|
|
32
|
+
"@arnilo/prism-workflows": "0.0.17"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@arnilo/prism": "file:../..",
|