@arnilo/prism-coding-agent 0.0.25 → 0.0.27
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 +16 -0
- package/README.md +2 -2
- package/dist/delete.d.ts +3 -0
- package/dist/delete.js +3 -1
- package/dist/edit.d.ts +3 -0
- package/dist/edit.js +2 -1
- package/dist/execution-policy.d.ts +7 -1
- package/dist/execution-policy.js +4 -1
- package/dist/forge/github.d.ts +2 -0
- package/dist/forge/github.js +554 -0
- package/dist/forge/index.d.ts +3 -0
- package/dist/forge/index.js +3 -0
- package/dist/forge/types.d.ts +150 -0
- package/dist/forge/types.js +19 -0
- package/dist/git-aware-repository.d.ts +25 -0
- package/dist/git-aware-repository.js +268 -0
- package/dist/git-tools.d.ts +3 -0
- package/dist/git-tools.js +4 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +6 -1
- package/dist/language/client.d.ts +44 -0
- package/dist/language/client.js +290 -0
- package/dist/language/framing.d.ts +23 -0
- package/dist/language/framing.js +112 -0
- package/dist/language/index.d.ts +4 -0
- package/dist/language/index.js +4 -0
- package/dist/language/intelligence.d.ts +10 -0
- package/dist/language/intelligence.js +526 -0
- package/dist/language/types.d.ts +106 -0
- package/dist/language/types.js +21 -0
- package/dist/lifecycle.d.ts +75 -0
- package/dist/lifecycle.js +102 -0
- package/dist/limits.d.ts +41 -0
- package/dist/limits.js +41 -0
- package/dist/move.d.ts +3 -0
- package/dist/move.js +2 -1
- package/dist/output-accumulator.d.ts +8 -0
- package/dist/output-accumulator.js +45 -1
- package/dist/process/index.d.ts +3 -0
- package/dist/process/index.js +3 -0
- package/dist/process/sessions.d.ts +2 -0
- package/dist/process/sessions.js +592 -0
- package/dist/process/types.d.ts +146 -0
- package/dist/process/types.js +19 -0
- package/dist/repository.d.ts +21 -1
- package/dist/repository.js +10 -10
- package/dist/write.d.ts +3 -0
- package/dist/write.js +2 -1
- package/package.json +3 -3
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { AgentIdentity, ExecutionPolicy, OwnershipScope, ToolEffectStore } from "@arnilo/prism";
|
|
2
|
+
import type { BoundGitRunner, CreateGitRunnerOptions } from "../git-exec.js";
|
|
3
|
+
/** Read-only context for one GitHub issue, bounded by payload caps. */
|
|
4
|
+
export interface ForgeIssueContext {
|
|
5
|
+
readonly number: number;
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly state: "open" | "closed";
|
|
8
|
+
readonly body: string;
|
|
9
|
+
readonly labels: readonly string[];
|
|
10
|
+
readonly author: string;
|
|
11
|
+
readonly updatedAt: string;
|
|
12
|
+
readonly url: string;
|
|
13
|
+
}
|
|
14
|
+
/** Pull-request state as seen through the forge. */
|
|
15
|
+
export interface ForgePullRequest {
|
|
16
|
+
readonly number: number;
|
|
17
|
+
readonly state: "open" | "closed";
|
|
18
|
+
readonly merged: boolean;
|
|
19
|
+
readonly head: string;
|
|
20
|
+
readonly base: string;
|
|
21
|
+
readonly title: string;
|
|
22
|
+
readonly body: string;
|
|
23
|
+
readonly url: string;
|
|
24
|
+
}
|
|
25
|
+
/** One check run or commit status, normalized. */
|
|
26
|
+
export interface ForgeCheck {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly status: "queued" | "in_progress" | "completed";
|
|
29
|
+
readonly conclusion?: string;
|
|
30
|
+
readonly detailsUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
/** Bounded handoff reconciliation: push/PR/check state, never auto-merged. */
|
|
33
|
+
export interface ForgeHandoffReport {
|
|
34
|
+
readonly base: string;
|
|
35
|
+
readonly head: string;
|
|
36
|
+
/** Whether the head ref exists on the remote. */
|
|
37
|
+
readonly pushed: boolean;
|
|
38
|
+
readonly aheadBy: number;
|
|
39
|
+
readonly behindBy: number;
|
|
40
|
+
/** No commits ahead and no divergence: nothing to push. */
|
|
41
|
+
readonly alreadyUpToDate: boolean;
|
|
42
|
+
readonly alreadyMerged: boolean;
|
|
43
|
+
readonly pullRequest?: ForgePullRequest;
|
|
44
|
+
readonly checks: readonly ForgeCheck[];
|
|
45
|
+
/** Bounded commit list (sha + subject), present only when pushed. */
|
|
46
|
+
readonly commits: readonly {
|
|
47
|
+
sha: string;
|
|
48
|
+
subject: string;
|
|
49
|
+
}[];
|
|
50
|
+
/** Bounded changed paths, present only when pushed. */
|
|
51
|
+
readonly changedPaths: readonly string[];
|
|
52
|
+
readonly diffstat: string;
|
|
53
|
+
readonly warnings: readonly string[];
|
|
54
|
+
}
|
|
55
|
+
export type ForgeErrorCode = "ERR_PRISM_FORGE_AUTH" | "ERR_PRISM_FORGE_API" | "ERR_PRISM_FORGE_STALE" | "ERR_PRISM_FORGE_RATE_LIMIT" | "ERR_PRISM_FORGE_LIMIT" | "ERR_PRISM_FORGE_OWNERSHIP";
|
|
56
|
+
export declare class ForgeError extends Error {
|
|
57
|
+
readonly code: ForgeErrorCode;
|
|
58
|
+
constructor(code: ForgeErrorCode, message: string);
|
|
59
|
+
}
|
|
60
|
+
export interface ForgeLimits {
|
|
61
|
+
readonly pagesPerOperation?: number;
|
|
62
|
+
readonly payloadBytes?: number;
|
|
63
|
+
readonly commentsPerReview?: number;
|
|
64
|
+
readonly requestConcurrency?: number;
|
|
65
|
+
readonly requestTimeoutMs?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface ResolvedForgeLimits {
|
|
68
|
+
readonly pagesPerOperation: number;
|
|
69
|
+
readonly payloadBytes: number;
|
|
70
|
+
readonly commentsPerReview: number;
|
|
71
|
+
readonly requestConcurrency: number;
|
|
72
|
+
readonly requestTimeoutMs: number;
|
|
73
|
+
}
|
|
74
|
+
export declare function resolveForgeLimits(options?: ForgeLimits): ResolvedForgeLimits;
|
|
75
|
+
export interface ForgeOperations {
|
|
76
|
+
issueContext(input: {
|
|
77
|
+
number: number;
|
|
78
|
+
}): Promise<ForgeIssueContext>;
|
|
79
|
+
push(input: {
|
|
80
|
+
refspec?: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
remoteRef: string;
|
|
83
|
+
}>;
|
|
84
|
+
createPullRequest(input: {
|
|
85
|
+
head: string;
|
|
86
|
+
base: string;
|
|
87
|
+
title: string;
|
|
88
|
+
body: string;
|
|
89
|
+
}): Promise<ForgePullRequest>;
|
|
90
|
+
updatePullRequest(input: {
|
|
91
|
+
number: number;
|
|
92
|
+
title?: string;
|
|
93
|
+
body?: string;
|
|
94
|
+
state?: "open" | "closed";
|
|
95
|
+
}): Promise<ForgePullRequest>;
|
|
96
|
+
createReviewComment(input: {
|
|
97
|
+
number: number;
|
|
98
|
+
path: string;
|
|
99
|
+
line: number;
|
|
100
|
+
body: string;
|
|
101
|
+
}): Promise<{
|
|
102
|
+
id: number;
|
|
103
|
+
}>;
|
|
104
|
+
checks(input: {
|
|
105
|
+
ref: string;
|
|
106
|
+
}): Promise<readonly ForgeCheck[]>;
|
|
107
|
+
reconcileHandoff(input: {
|
|
108
|
+
base: string;
|
|
109
|
+
head: string;
|
|
110
|
+
}): Promise<ForgeHandoffReport>;
|
|
111
|
+
}
|
|
112
|
+
/** Structural mirror of the core `CredentialResolverSource` (not barrel-exported). */
|
|
113
|
+
export interface ForgeCredential {
|
|
114
|
+
readonly type: "bearer" | "api_key" | "basic" | "custom";
|
|
115
|
+
readonly value: string;
|
|
116
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
117
|
+
}
|
|
118
|
+
export interface ForgeCredentialResolver {
|
|
119
|
+
resolve(request: {
|
|
120
|
+
readonly name: string;
|
|
121
|
+
readonly provider?: string;
|
|
122
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
123
|
+
}): Promise<ForgeCredential | undefined> | ForgeCredential | undefined;
|
|
124
|
+
}
|
|
125
|
+
export interface ForgeCredentialResolverSource {
|
|
126
|
+
readonly name: string;
|
|
127
|
+
readonly resolver: ForgeCredentialResolver;
|
|
128
|
+
}
|
|
129
|
+
export interface CreateGitHubForgeOptions {
|
|
130
|
+
/** Credential resolver — resolved with provider "github" per call. */
|
|
131
|
+
readonly credentials: ForgeCredentialResolverSource;
|
|
132
|
+
/** "owner/repo", bound per instance. */
|
|
133
|
+
readonly repository: string;
|
|
134
|
+
/** Local checkout the adapter pushes from. */
|
|
135
|
+
readonly cwd: string;
|
|
136
|
+
/** Git runner reused for authenticated push. */
|
|
137
|
+
readonly git: CreateGitRunnerOptions | BoundGitRunner;
|
|
138
|
+
/** Mutations are gated through this policy before any request. */
|
|
139
|
+
readonly policy?: ExecutionPolicy;
|
|
140
|
+
/** REQUIRED: idempotency + unknown-outcome recovery for mutations. */
|
|
141
|
+
readonly effectStore: ToolEffectStore;
|
|
142
|
+
/** Durable context for effect keys; required for mutations. */
|
|
143
|
+
readonly identity?: AgentIdentity;
|
|
144
|
+
readonly ownership?: OwnershipScope;
|
|
145
|
+
readonly sessionId?: string;
|
|
146
|
+
readonly runId?: string;
|
|
147
|
+
readonly limits?: ForgeLimits;
|
|
148
|
+
/** Host-injectable fetch (e.g. routed through an egress proxy); defaults to globalThis.fetch. */
|
|
149
|
+
readonly fetch?: typeof fetch;
|
|
150
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DEFAULT_MAX_FORGE_COMMENTS_PER_REVIEW, DEFAULT_MAX_FORGE_PAGES_PER_OPERATION, DEFAULT_MAX_FORGE_PAYLOAD_BYTES, DEFAULT_MAX_FORGE_REQUEST_CONCURRENCY, DEFAULT_MAX_FORGE_REQUEST_TIMEOUT_MS, HARD_MAX_FORGE_COMMENTS_PER_REVIEW, HARD_MAX_FORGE_PAGES_PER_OPERATION, HARD_MAX_FORGE_PAYLOAD_BYTES, HARD_MAX_FORGE_REQUEST_CONCURRENCY, HARD_MAX_FORGE_REQUEST_TIMEOUT_MS, validateCodingLimit, } from "../limits.js";
|
|
2
|
+
export class ForgeError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "ForgeError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function resolveForgeLimits(options) {
|
|
11
|
+
return {
|
|
12
|
+
pagesPerOperation: validateCodingLimit("forge.pagesPerOperation", options?.pagesPerOperation ?? DEFAULT_MAX_FORGE_PAGES_PER_OPERATION, HARD_MAX_FORGE_PAGES_PER_OPERATION),
|
|
13
|
+
payloadBytes: validateCodingLimit("forge.payloadBytes", options?.payloadBytes ?? DEFAULT_MAX_FORGE_PAYLOAD_BYTES, HARD_MAX_FORGE_PAYLOAD_BYTES),
|
|
14
|
+
commentsPerReview: validateCodingLimit("forge.commentsPerReview", options?.commentsPerReview ?? DEFAULT_MAX_FORGE_COMMENTS_PER_REVIEW, HARD_MAX_FORGE_COMMENTS_PER_REVIEW),
|
|
15
|
+
requestConcurrency: validateCodingLimit("forge.requestConcurrency", options?.requestConcurrency ?? DEFAULT_MAX_FORGE_REQUEST_CONCURRENCY, HARD_MAX_FORGE_REQUEST_CONCURRENCY),
|
|
16
|
+
requestTimeoutMs: validateCodingLimit("forge.requestTimeoutMs", options?.requestTimeoutMs ?? DEFAULT_MAX_FORGE_REQUEST_TIMEOUT_MS, HARD_MAX_FORGE_REQUEST_TIMEOUT_MS),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-aware repository enumeration over `git ls-files`.
|
|
3
|
+
*
|
|
4
|
+
* Detection: `git rev-parse --is-inside-work-tree` (cached per instance).
|
|
5
|
+
* Non-Git / detection failure → native fallback. Post-detection Git failure → fail closed.
|
|
6
|
+
* No hand-rolled `.gitignore` parser; argv is fixed host-side only.
|
|
7
|
+
*/
|
|
8
|
+
import { type BoundGitRunner, type CreateGitRunnerOptions } from "./git-exec.js";
|
|
9
|
+
import { type RepositoryLimitOptions, type RepositoryOperations } from "./repository.js";
|
|
10
|
+
export interface GitAwareRepositoryOptions {
|
|
11
|
+
readonly git?: CreateGitRunnerOptions | BoundGitRunner;
|
|
12
|
+
readonly fallback?: RepositoryOperations;
|
|
13
|
+
/** Host-config only, never model-settable. Default false: ignored paths stay excluded. */
|
|
14
|
+
readonly includeIgnored?: boolean;
|
|
15
|
+
readonly limits?: RepositoryLimitOptions;
|
|
16
|
+
/** Override freeze default/hard `ls-files` stdout cap. */
|
|
17
|
+
readonly maxLsFilesOutputBytes?: number;
|
|
18
|
+
}
|
|
19
|
+
/** Parse NUL-delimited `git ls-files -z` stdout. */
|
|
20
|
+
export declare function parseGitLsFilesZ(buffer: Buffer): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Repository operations that prefer Git tracked/unignored enumeration.
|
|
23
|
+
* Outside a Git work tree (or when detection fails), delegates to `fallback`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createGitAwareRepositoryOperations(cwd: string, options?: GitAwareRepositoryOptions): RepositoryOperations;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git-aware repository enumeration over `git ls-files`.
|
|
3
|
+
*
|
|
4
|
+
* Detection: `git rev-parse --is-inside-work-tree` (cached per instance).
|
|
5
|
+
* Non-Git / detection failure → native fallback. Post-detection Git failure → fail closed.
|
|
6
|
+
* No hand-rolled `.gitignore` parser; argv is fixed host-side only.
|
|
7
|
+
*/
|
|
8
|
+
import { lstat } from "node:fs/promises";
|
|
9
|
+
import { join, resolve } from "node:path";
|
|
10
|
+
import { createBoundGitRunner, gitText, GitError } from "./git-exec.js";
|
|
11
|
+
import { DEFAULT_MAX_LS_FILES_OUTPUT_BYTES, HARD_MAX_LS_FILES_OUTPUT_BYTES, validateCodingLimit } from "./limits.js";
|
|
12
|
+
import { createLocalRepositoryOperations, RepositoryError, toRepoRelative, } from "./repository.js";
|
|
13
|
+
function isBoundGitRunner(value) {
|
|
14
|
+
return typeof value.exec === "function" && typeof value.gitPath === "string";
|
|
15
|
+
}
|
|
16
|
+
function shouldSkipName(name, includeHidden, exclude) {
|
|
17
|
+
if (name === "." || name === "..")
|
|
18
|
+
return true;
|
|
19
|
+
if (exclude.has(name))
|
|
20
|
+
return true;
|
|
21
|
+
if (!includeHidden && name.startsWith("."))
|
|
22
|
+
return true;
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function pathHasSkippedComponent(relativePath, includeHidden, exclude) {
|
|
26
|
+
for (const part of relativePath.split("/")) {
|
|
27
|
+
if (shouldSkipName(part, includeHidden, exclude))
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
/** Parse NUL-delimited `git ls-files -z` stdout. */
|
|
33
|
+
export function parseGitLsFilesZ(buffer) {
|
|
34
|
+
const out = [];
|
|
35
|
+
let start = 0;
|
|
36
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
37
|
+
if (buffer[i] === 0) {
|
|
38
|
+
if (i > start)
|
|
39
|
+
out.push(buffer.subarray(start, i).toString("utf8"));
|
|
40
|
+
start = i + 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (start < buffer.length)
|
|
44
|
+
out.push(buffer.subarray(start).toString("utf8"));
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function depthFromStart(relativePath, startRel) {
|
|
48
|
+
const rel = startRel === "."
|
|
49
|
+
? relativePath
|
|
50
|
+
: relativePath === startRel
|
|
51
|
+
? ""
|
|
52
|
+
: relativePath.startsWith(`${startRel}/`)
|
|
53
|
+
? relativePath.slice(startRel.length + 1)
|
|
54
|
+
: relativePath;
|
|
55
|
+
if (rel === "" || rel === ".")
|
|
56
|
+
return 0;
|
|
57
|
+
return rel.split("/").length - 1;
|
|
58
|
+
}
|
|
59
|
+
function isUnderStart(relativePath, startRel) {
|
|
60
|
+
if (startRel === "." || startRel === "")
|
|
61
|
+
return true;
|
|
62
|
+
return relativePath === startRel || relativePath.startsWith(`${startRel}/`);
|
|
63
|
+
}
|
|
64
|
+
async function* walkGitFiles(rootReal, startAbsolute, limits, files) {
|
|
65
|
+
const startRel = toRepoRelative(rootReal, startAbsolute);
|
|
66
|
+
const dirSeen = new Set();
|
|
67
|
+
const planned = [];
|
|
68
|
+
for (const relativePath of files) {
|
|
69
|
+
if (limits.signal?.aborted)
|
|
70
|
+
throw new RepositoryError("Operation aborted");
|
|
71
|
+
if (limits.deadlineAt !== undefined && Date.now() >= limits.deadlineAt) {
|
|
72
|
+
throw new RepositoryError("Repository operation exceeded time limit");
|
|
73
|
+
}
|
|
74
|
+
if (!relativePath || relativePath.includes("\0"))
|
|
75
|
+
continue;
|
|
76
|
+
if (relativePath === ".git" || relativePath.startsWith(".git/"))
|
|
77
|
+
continue;
|
|
78
|
+
if (!isUnderStart(relativePath, startRel))
|
|
79
|
+
continue;
|
|
80
|
+
if (pathHasSkippedComponent(relativePath, limits.includeHidden, limits.exclude))
|
|
81
|
+
continue;
|
|
82
|
+
const fileDepth = depthFromStart(relativePath, startRel);
|
|
83
|
+
if (fileDepth > limits.maxDepth)
|
|
84
|
+
continue;
|
|
85
|
+
// Synthesize parent directories within the start scope (native walker emits dirs too).
|
|
86
|
+
const parts = relativePath.split("/");
|
|
87
|
+
let acc = "";
|
|
88
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
89
|
+
acc = acc ? `${acc}/${parts[i]}` : parts[i];
|
|
90
|
+
if (!isUnderStart(acc, startRel))
|
|
91
|
+
continue;
|
|
92
|
+
if (pathHasSkippedComponent(acc, limits.includeHidden, limits.exclude))
|
|
93
|
+
break;
|
|
94
|
+
const dirDepth = depthFromStart(acc, startRel);
|
|
95
|
+
if (dirDepth > limits.maxDepth)
|
|
96
|
+
break;
|
|
97
|
+
if (!dirSeen.has(acc)) {
|
|
98
|
+
dirSeen.add(acc);
|
|
99
|
+
planned.push({ path: acc, kind: "directory", depth: dirDepth });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
planned.push({ path: relativePath, kind: "file", depth: fileDepth });
|
|
103
|
+
}
|
|
104
|
+
planned.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
105
|
+
let scannedEntries = 0;
|
|
106
|
+
let scannedFiles = 0;
|
|
107
|
+
for (const item of planned) {
|
|
108
|
+
if (limits.signal?.aborted)
|
|
109
|
+
throw new RepositoryError("Operation aborted");
|
|
110
|
+
if (limits.deadlineAt !== undefined && Date.now() >= limits.deadlineAt) {
|
|
111
|
+
throw new RepositoryError("Repository operation exceeded time limit");
|
|
112
|
+
}
|
|
113
|
+
if (scannedEntries >= limits.maxEntries) {
|
|
114
|
+
yield { type: "limit", truncatedBy: "entries" };
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const absolutePath = join(rootReal, item.path);
|
|
118
|
+
const rootResolved = resolve(rootReal);
|
|
119
|
+
const absResolved = resolve(absolutePath);
|
|
120
|
+
if (absResolved !== rootResolved && !absResolved.startsWith(rootResolved + "/"))
|
|
121
|
+
continue;
|
|
122
|
+
let kind = item.kind;
|
|
123
|
+
let size;
|
|
124
|
+
try {
|
|
125
|
+
const st = await lstat(absolutePath);
|
|
126
|
+
if (st.isSymbolicLink())
|
|
127
|
+
kind = "symlink";
|
|
128
|
+
else if (st.isDirectory())
|
|
129
|
+
kind = "directory";
|
|
130
|
+
else if (st.isFile()) {
|
|
131
|
+
kind = "file";
|
|
132
|
+
size = st.size;
|
|
133
|
+
}
|
|
134
|
+
else
|
|
135
|
+
kind = "other";
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Missing after ls-files (race) — skip.
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (kind === "file") {
|
|
142
|
+
if (scannedFiles >= limits.maxFiles) {
|
|
143
|
+
yield { type: "limit", truncatedBy: "files" };
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
scannedFiles++;
|
|
147
|
+
}
|
|
148
|
+
scannedEntries++;
|
|
149
|
+
const entry = size === undefined ? { path: item.path, kind } : { path: item.path, kind, size };
|
|
150
|
+
yield { type: "entry", entry, absolutePath, depth: item.depth };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Repository operations that prefer Git tracked/unignored enumeration.
|
|
155
|
+
* Outside a Git work tree (or when detection fails), delegates to `fallback`.
|
|
156
|
+
*/
|
|
157
|
+
export function createGitAwareRepositoryOperations(cwd, options) {
|
|
158
|
+
const fallback = options?.fallback ?? createLocalRepositoryOperations(options?.limits);
|
|
159
|
+
const includeIgnored = options?.includeIgnored === true;
|
|
160
|
+
const maxLsBytes = validateCodingLimit("maxLsFilesOutputBytes", options?.maxLsFilesOutputBytes ?? DEFAULT_MAX_LS_FILES_OUTPUT_BYTES, HARD_MAX_LS_FILES_OUTPUT_BYTES);
|
|
161
|
+
let detected;
|
|
162
|
+
let runnerPromise;
|
|
163
|
+
let gitOps;
|
|
164
|
+
function getRunner() {
|
|
165
|
+
if (!runnerPromise) {
|
|
166
|
+
const git = options?.git;
|
|
167
|
+
runnerPromise =
|
|
168
|
+
git && isBoundGitRunner(git)
|
|
169
|
+
? Promise.resolve(git)
|
|
170
|
+
: createBoundGitRunner({
|
|
171
|
+
...git,
|
|
172
|
+
maxOutputBytes: maxLsBytes,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
return runnerPromise;
|
|
176
|
+
}
|
|
177
|
+
async function detect(signal) {
|
|
178
|
+
if (detected !== undefined)
|
|
179
|
+
return detected;
|
|
180
|
+
try {
|
|
181
|
+
const result = await (await getRunner()).exec({
|
|
182
|
+
args: ["rev-parse", "--is-inside-work-tree"],
|
|
183
|
+
cwd,
|
|
184
|
+
signal,
|
|
185
|
+
maxOutputBytes: 64,
|
|
186
|
+
});
|
|
187
|
+
detected = result.exitCode === 0 && gitText(result).trim() === "true";
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
detected = false;
|
|
191
|
+
}
|
|
192
|
+
return detected;
|
|
193
|
+
}
|
|
194
|
+
async function listGitPaths(signal) {
|
|
195
|
+
const runner = await getRunner();
|
|
196
|
+
// Fixed argv only — never model-supplied flags (Task 0 freeze).
|
|
197
|
+
const primary = await runner.exec({
|
|
198
|
+
args: ["ls-files", "--cached", "--others", "--exclude-standard", "-z"],
|
|
199
|
+
cwd,
|
|
200
|
+
signal,
|
|
201
|
+
maxOutputBytes: maxLsBytes,
|
|
202
|
+
});
|
|
203
|
+
if (primary.timedOut)
|
|
204
|
+
throw new RepositoryError("Repository operation exceeded time limit");
|
|
205
|
+
if (primary.aborted)
|
|
206
|
+
throw new RepositoryError("Operation aborted");
|
|
207
|
+
if (primary.exitCode !== 0) {
|
|
208
|
+
throw new RepositoryError(`git ls-files failed (exit ${primary.exitCode})`);
|
|
209
|
+
}
|
|
210
|
+
const paths = new Set(parseGitLsFilesZ(primary.stdout));
|
|
211
|
+
if (includeIgnored) {
|
|
212
|
+
// Second invocation only when host opts into ignored paths (≤ 2 total per freeze).
|
|
213
|
+
const ignored = await runner.exec({
|
|
214
|
+
args: ["ls-files", "-o", "-i", "--exclude-standard", "-z"],
|
|
215
|
+
cwd,
|
|
216
|
+
signal,
|
|
217
|
+
maxOutputBytes: maxLsBytes,
|
|
218
|
+
});
|
|
219
|
+
if (ignored.timedOut)
|
|
220
|
+
throw new RepositoryError("Repository operation exceeded time limit");
|
|
221
|
+
if (ignored.aborted)
|
|
222
|
+
throw new RepositoryError("Operation aborted");
|
|
223
|
+
if (ignored.exitCode !== 0) {
|
|
224
|
+
throw new RepositoryError(`git ls-files (ignored) failed (exit ${ignored.exitCode})`);
|
|
225
|
+
}
|
|
226
|
+
for (const p of parseGitLsFilesZ(ignored.stdout))
|
|
227
|
+
paths.add(p);
|
|
228
|
+
}
|
|
229
|
+
return [...paths].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
230
|
+
}
|
|
231
|
+
function getGitOps() {
|
|
232
|
+
if (!gitOps) {
|
|
233
|
+
const walk = async function* (rootReal, startAbsolute, limits) {
|
|
234
|
+
let files;
|
|
235
|
+
try {
|
|
236
|
+
files = await listGitPaths(limits.signal);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (error instanceof RepositoryError)
|
|
240
|
+
throw error;
|
|
241
|
+
if (error instanceof GitError) {
|
|
242
|
+
if (/abort/i.test(error.message))
|
|
243
|
+
throw new RepositoryError("Operation aborted");
|
|
244
|
+
if (/time|exceeded/i.test(error.message)) {
|
|
245
|
+
throw new RepositoryError("Repository operation exceeded time limit");
|
|
246
|
+
}
|
|
247
|
+
throw new RepositoryError(error.message);
|
|
248
|
+
}
|
|
249
|
+
throw new RepositoryError(error instanceof Error ? error.message : String(error));
|
|
250
|
+
}
|
|
251
|
+
yield* walkGitFiles(rootReal, startAbsolute, limits, files);
|
|
252
|
+
};
|
|
253
|
+
gitOps = createLocalRepositoryOperations(options?.limits, walk);
|
|
254
|
+
}
|
|
255
|
+
return gitOps;
|
|
256
|
+
}
|
|
257
|
+
async function route(signal, gitCall, nativeCall) {
|
|
258
|
+
if (!(await detect(signal)))
|
|
259
|
+
return nativeCall();
|
|
260
|
+
return gitCall();
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
list: (request) => route(request.signal, () => getGitOps().list(request), () => fallback.list(request)),
|
|
264
|
+
search: (request) => route(request.signal, () => getGitOps().search(request), () => fallback.search(request)),
|
|
265
|
+
glob: (request) => route(request.signal, () => getGitOps().glob(request), () => fallback.glob(request)),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=git-aware-repository.js.map
|
package/dist/git-tools.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
|
|
8
8
|
import { type CodingCheckToolOptions, type NamedCheckDefinition } from "./checks.js";
|
|
9
|
+
import type { CodingLifecycleEvent } from "./lifecycle.js";
|
|
9
10
|
import { type ArtifactWriter, type CreateGitOperationsOptions, type GitOperations } from "./git.js";
|
|
10
11
|
export interface GitToolsOptions {
|
|
11
12
|
readonly executionPolicy?: ExecutionPolicy;
|
|
@@ -19,6 +20,8 @@ export interface GitToolsOptions {
|
|
|
19
20
|
/** Optional named checks included by `createGitTools` when provided. */
|
|
20
21
|
readonly checks?: Readonly<Record<string, NamedCheckDefinition>>;
|
|
21
22
|
readonly checkOptions?: Omit<CodingCheckToolOptions, "checks" | "executionPolicy">;
|
|
23
|
+
/** Optional consumer-gated lifecycle listener (worktree_changed / permission_denied). */
|
|
24
|
+
readonly onEvent?: (event: CodingLifecycleEvent) => void;
|
|
22
25
|
}
|
|
23
26
|
export declare function createGitStatusTool(cwd: string, options?: GitToolsOptions): ToolDefinition;
|
|
24
27
|
export declare function createGitDiffTool(cwd: string, options?: GitToolsOptions): ToolDefinition;
|
package/dist/git-tools.js
CHANGED
|
@@ -243,7 +243,7 @@ export function createGitWorktreeTool(cwd, options) {
|
|
|
243
243
|
paths: path ? [path] : [cwd],
|
|
244
244
|
risk: action === "list" ? "low" : "high",
|
|
245
245
|
metadata: { branch, force, sessionId: context.sessionId, runId: context.runId },
|
|
246
|
-
}, toolCallId, "git_worktree");
|
|
246
|
+
}, toolCallId, "git_worktree", (denied) => options?.onEvent?.({ type: "permission_denied", ...denied }));
|
|
247
247
|
if (!policy.allowed)
|
|
248
248
|
return policy.result;
|
|
249
249
|
try {
|
|
@@ -254,6 +254,9 @@ export function createGitWorktreeTool(cwd, options) {
|
|
|
254
254
|
force,
|
|
255
255
|
signal: context.signal,
|
|
256
256
|
});
|
|
257
|
+
if (action !== "list") {
|
|
258
|
+
options?.onEvent?.({ type: "worktree_changed", action, path: result.path ?? path ?? "", toolCallId });
|
|
259
|
+
}
|
|
257
260
|
const text = action === "list"
|
|
258
261
|
? result.worktrees.map((w) => `${w.path}\t${w.branch ?? ""}\t${w.head ?? ""}`).join("\n") || "(no worktrees)"
|
|
259
262
|
: `ok action=${action} path=${result.path ?? ""}`;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type { CodingCheckToolOptions, NamedCheckDefinition } from "./checks.js";
|
|
|
5
5
|
export { createCodingCheckTool } from "./checks.js";
|
|
6
6
|
export type { DeleteOperations, DeleteToolOptions, MutationStat } from "./delete.js";
|
|
7
7
|
export { createDeleteTool } from "./delete.js";
|
|
8
|
+
export type { CodingLifecycleEvent, CodingLifecycleLimits, CodingLifecycleEmitter, CreateCodingLifecycleEmitterOptions, FileChangeOp, FileChangedEvent, WorktreeChangedEvent, PermissionDeniedEvent, ConfigurationChangedEvent, ResolvedCodingLifecycleLimits, } from "./lifecycle.js";
|
|
9
|
+
export { createCodingLifecycleEmitter, CodingLifecycleError, resolveCodingLifecycleLimits, } from "./lifecycle.js";
|
|
8
10
|
export type { CodingArtifactKind, CodingArtifactRef, CodingCheckpointLimitOptions, CodingCheckpointMetadata, CodingCheckSummary, CodingFingerprints, CodingHandoffSummary, CodingTaskStatus, CodingTodoItem, ResolvedCodingCheckpointLimits, } from "./coding-checkpoint.js";
|
|
9
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";
|
|
10
12
|
export type { Edit, EditOperations, EditToolDetails, EditToolOptions } from "./edit.js";
|
|
@@ -28,8 +30,16 @@ export type { ReadOperations, ReadTextOptions, ReadTextResult, ReadToolOptions,
|
|
|
28
30
|
export { createReadTool, DEFAULT_MAX_IMAGE_BYTES, detectSupportedImageMimeType, detectSupportedImageMimeTypeFromFile, } from "./read.js";
|
|
29
31
|
export type { ReadPathSet } from "./read-path-set.js";
|
|
30
32
|
export { createReadPathSet } from "./read-path-set.js";
|
|
31
|
-
export type { RepoEntryKind, RepoListEntry, RepositoryGlobRequest, RepositoryGlobResult, RepositoryLimitOptions, RepositoryListRequest, RepositoryListResult, RepositoryOperations, RepoSearchOutputMode, RepositorySearchMatch, RepositorySearchRequest, RepositorySearchResult, ResolvedRepositoryLimits, } from "./repository.js";
|
|
33
|
+
export type { RepoEntryKind, RepoListEntry, RepositoryGlobRequest, RepositoryGlobResult, RepositoryLimitOptions, RepositoryListRequest, RepositoryListResult, RepositoryOperations, RepoSearchOutputMode, RepositorySearchMatch, RepositorySearchRequest, RepositorySearchResult, ResolvedRepositoryLimits, RepositoryWalk, RepositoryWalkEvent, RepositoryWalkLimits, } from "./repository.js";
|
|
32
34
|
export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
|
|
35
|
+
export type { GitAwareRepositoryOptions } from "./git-aware-repository.js";
|
|
36
|
+
export { createGitAwareRepositoryOperations, parseGitLsFilesZ } from "./git-aware-repository.js";
|
|
37
|
+
export type { CreateLanguageIntelligenceOptions, LanguageDiagnostic, LanguageIntelligence, LanguageIntelligenceLimits, LanguageLocation, LanguageServerSpec, LanguageSymbol, LanguageTextEdit, LanguageWorkspaceEdit, } from "./language/index.js";
|
|
38
|
+
export { applyTextEdits, createLanguageIntelligence, encodeLspFrame, LanguageIntelligenceError, LspFrameError, LspFrameReader, resolveLanguageIntelligenceLimits, } from "./language/index.js";
|
|
39
|
+
export type { CreateGitHubForgeOptions, ForgeCheck, ForgeCredential, ForgeCredentialResolver, ForgeCredentialResolverSource, ForgeErrorCode, ForgeHandoffReport, ForgeIssueContext, ForgeLimits, ForgeOperations, ForgePullRequest, ResolvedForgeLimits, } from "./forge/index.js";
|
|
40
|
+
export { createGitHubForge, ForgeError, resolveForgeLimits } from "./forge/index.js";
|
|
41
|
+
export type { CodingProcessEvent, CreateProcessSessionsOptions, ProcessExitResult, ProcessOutputChunk, ProcessSandboxBackend, ProcessSandboxHandle, ProcessSandboxStartRequest, ProcessSession, ProcessSessionLimits, ProcessSessionMetadata, ProcessSessions, ProcessSessionState, ProcessStartRequest, ResolvedProcessSessionLimits, } from "./process/index.js";
|
|
42
|
+
export { createProcessSessions, ProcessSessionError, resolveProcessSessionLimits, } from "./process/index.js";
|
|
33
43
|
export type { SearchToolOptions } from "./search.js";
|
|
34
44
|
export { createRepoSearchTool } from "./search.js";
|
|
35
45
|
export type { BashExecOptions, BashOperations, BashSpawnContext, BashSpawnHook, ShellConfig, ShellToolOptions, } from "./shell.js";
|
|
@@ -38,7 +48,7 @@ export type { WriteOperations, WriteToolOptions } from "./write.js";
|
|
|
38
48
|
export { createWriteTool } from "./write.js";
|
|
39
49
|
export { enforceExecutionPolicy } from "./execution-policy.js";
|
|
40
50
|
export { withFileMutationQueue } from "./file-mutation-queue.js";
|
|
41
|
-
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";
|
|
51
|
+
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_FORGE_COMMENTS_PER_REVIEW, DEFAULT_MAX_FORGE_PAGES_PER_OPERATION, DEFAULT_MAX_FORGE_PAYLOAD_BYTES, DEFAULT_MAX_FORGE_REQUEST_CONCURRENCY, DEFAULT_MAX_FORGE_REQUEST_TIMEOUT_MS, DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_LS_FILES_OUTPUT_BYTES, DEFAULT_MAX_LSP_DIAGNOSTICS_PER_FILE, DEFAULT_MAX_LSP_MESSAGE_BYTES, DEFAULT_MAX_LSP_PENDING_REQUESTS, DEFAULT_MAX_LSP_RESULTS_PER_QUERY, DEFAULT_MAX_LSP_SERVERS, DEFAULT_MAX_LSP_TIMEOUT_MS, 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_PROCESS_INPUT_BYTES, DEFAULT_MAX_PROCESS_LIFETIME_MS, DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, DEFAULT_MAX_PROCESS_SESSIONS, DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_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_FORGE_COMMENTS_PER_REVIEW, HARD_MAX_FORGE_PAGES_PER_OPERATION, HARD_MAX_FORGE_PAYLOAD_BYTES, HARD_MAX_FORGE_REQUEST_CONCURRENCY, HARD_MAX_FORGE_REQUEST_TIMEOUT_MS, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_LS_FILES_OUTPUT_BYTES, HARD_MAX_LSP_DIAGNOSTICS_PER_FILE, HARD_MAX_LSP_MESSAGE_BYTES, HARD_MAX_LSP_PENDING_REQUESTS, HARD_MAX_LSP_RESULTS_PER_QUERY, HARD_MAX_LSP_SERVERS, HARD_MAX_LSP_TIMEOUT_MS, 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_PROCESS_INPUT_BYTES, HARD_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_SESSIONS, HARD_MAX_PROCESS_TOTAL_OUTPUT_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, LSP_RESTARTS_PER_SERVER, } from "./limits.js";
|
|
42
52
|
import type { ExecutionPolicy, ToolDefinition } from "@arnilo/prism";
|
|
43
53
|
import type { DeleteToolOptions } from "./delete.js";
|
|
44
54
|
import type { EditToolOptions } from "./edit.js";
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { createDirectoryArtifactWriter, createTempArtifactWriter, sha256Hex } fr
|
|
|
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
10
|
export { createDeleteTool } from "./delete.js";
|
|
11
|
+
export { createCodingLifecycleEmitter, CodingLifecycleError, resolveCodingLifecycleLimits, } from "./lifecycle.js";
|
|
11
12
|
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";
|
|
12
13
|
export { createEditTool } from "./edit.js";
|
|
13
14
|
export { classifyGitApplyEffect, classifyGitBranchEffect, classifyGitWorktreeEffect, CODING_LOCAL_EFFECT, CODING_OBSERVATION_EFFECT, CODING_UNSUPPORTED_EFFECT, reconcileCodingToolEffect, } from "./effects.js";
|
|
@@ -21,13 +22,17 @@ export { createMoveTool } from "./move.js";
|
|
|
21
22
|
export { createReadTool, DEFAULT_MAX_IMAGE_BYTES, detectSupportedImageMimeType, detectSupportedImageMimeTypeFromFile, } from "./read.js";
|
|
22
23
|
export { createReadPathSet } from "./read-path-set.js";
|
|
23
24
|
export { compileSearchPattern, createLocalRepositoryOperations, DEFAULT_REPO_EXCLUDE, isBinaryBuffer, RepositoryError, resolveRepoPath, resolveRepositoryLimits, toRepoRelative, } from "./repository.js";
|
|
25
|
+
export { createGitAwareRepositoryOperations, parseGitLsFilesZ } from "./git-aware-repository.js";
|
|
26
|
+
export { applyTextEdits, createLanguageIntelligence, encodeLspFrame, LanguageIntelligenceError, LspFrameError, LspFrameReader, resolveLanguageIntelligenceLimits, } from "./language/index.js";
|
|
27
|
+
export { createGitHubForge, ForgeError, resolveForgeLimits } from "./forge/index.js";
|
|
28
|
+
export { createProcessSessions, ProcessSessionError, resolveProcessSessionLimits, } from "./process/index.js";
|
|
24
29
|
export { createRepoSearchTool } from "./search.js";
|
|
25
30
|
export { createLocalBashOperations, createShellTool, getShellConfig, killProcessTree, waitForChildProcess, } from "./shell.js";
|
|
26
31
|
export { createWriteTool } from "./write.js";
|
|
27
32
|
// --- generic primitives (re-exported for hosts that want them) ---
|
|
28
33
|
export { enforceExecutionPolicy } from "./execution-policy.js";
|
|
29
34
|
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";
|
|
35
|
+
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_FORGE_COMMENTS_PER_REVIEW, DEFAULT_MAX_FORGE_PAGES_PER_OPERATION, DEFAULT_MAX_FORGE_PAYLOAD_BYTES, DEFAULT_MAX_FORGE_REQUEST_CONCURRENCY, DEFAULT_MAX_FORGE_REQUEST_TIMEOUT_MS, DEFAULT_MAX_GIT_CHANGED_FILES, DEFAULT_MAX_GIT_DIFF_LINES, DEFAULT_MAX_GIT_MESSAGE_BYTES, DEFAULT_MAX_GIT_OUTPUT_BYTES, DEFAULT_MAX_LS_FILES_OUTPUT_BYTES, DEFAULT_MAX_LSP_DIAGNOSTICS_PER_FILE, DEFAULT_MAX_LSP_MESSAGE_BYTES, DEFAULT_MAX_LSP_PENDING_REQUESTS, DEFAULT_MAX_LSP_RESULTS_PER_QUERY, DEFAULT_MAX_LSP_SERVERS, DEFAULT_MAX_LSP_TIMEOUT_MS, 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_PROCESS_INPUT_BYTES, DEFAULT_MAX_PROCESS_LIFETIME_MS, DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, DEFAULT_MAX_PROCESS_SESSIONS, DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_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_FORGE_COMMENTS_PER_REVIEW, HARD_MAX_FORGE_PAGES_PER_OPERATION, HARD_MAX_FORGE_PAYLOAD_BYTES, HARD_MAX_FORGE_REQUEST_CONCURRENCY, HARD_MAX_FORGE_REQUEST_TIMEOUT_MS, HARD_MAX_GIT_CHANGED_FILES, HARD_MAX_GIT_DIFF_LINES, HARD_MAX_GIT_MESSAGE_BYTES, HARD_MAX_GIT_OUTPUT_BYTES, HARD_MAX_LS_FILES_OUTPUT_BYTES, HARD_MAX_LSP_DIAGNOSTICS_PER_FILE, HARD_MAX_LSP_MESSAGE_BYTES, HARD_MAX_LSP_PENDING_REQUESTS, HARD_MAX_LSP_RESULTS_PER_QUERY, HARD_MAX_LSP_SERVERS, HARD_MAX_LSP_TIMEOUT_MS, 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_PROCESS_INPUT_BYTES, HARD_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_SESSIONS, HARD_MAX_PROCESS_TOTAL_OUTPUT_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, LSP_RESTARTS_PER_SERVER, } from "./limits.js";
|
|
31
36
|
import { createDeleteTool } from "./delete.js";
|
|
32
37
|
import { createEditTool } from "./edit.js";
|
|
33
38
|
import { createGlobTool } from "./glob.js";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal JSON-RPC LSP client over child stdio (LSP 3.17 framing).
|
|
3
|
+
* Lazy start; bounded pending requests, message bytes, timeout, restart budget.
|
|
4
|
+
*/
|
|
5
|
+
import { type ResolvedLanguageIntelligenceLimits } from "./types.js";
|
|
6
|
+
export interface LspServerSpec {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly command: string;
|
|
9
|
+
readonly args: readonly string[];
|
|
10
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
11
|
+
readonly cwd: string;
|
|
12
|
+
readonly rootUri: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class LspClient {
|
|
15
|
+
readonly spec: LspServerSpec;
|
|
16
|
+
private readonly limits;
|
|
17
|
+
private child;
|
|
18
|
+
private reader;
|
|
19
|
+
private nextId;
|
|
20
|
+
private pending;
|
|
21
|
+
private startPromise;
|
|
22
|
+
private disposed;
|
|
23
|
+
private shuttingDown;
|
|
24
|
+
private capabilities;
|
|
25
|
+
/** file URI → latest diagnostics payload from publishDiagnostics */
|
|
26
|
+
readonly diagnosticsByUri: Map<string, unknown>;
|
|
27
|
+
private readonly onUnexpectedExit;
|
|
28
|
+
constructor(spec: LspServerSpec, limits: ResolvedLanguageIntelligenceLimits, hooks?: {
|
|
29
|
+
onUnexpectedExit?: () => void;
|
|
30
|
+
});
|
|
31
|
+
get started(): boolean;
|
|
32
|
+
ensureStarted(signal?: AbortSignal): Promise<void>;
|
|
33
|
+
request(method: string, params: unknown, signal?: AbortSignal): Promise<unknown>;
|
|
34
|
+
notify(method: string, params: unknown): void;
|
|
35
|
+
hasCapability(key: string): boolean;
|
|
36
|
+
dispose(): Promise<void>;
|
|
37
|
+
private write;
|
|
38
|
+
private spawnAndInitialize;
|
|
39
|
+
/** Internal request used during initialize before ensureStarted recursion. */
|
|
40
|
+
private requestUnlocked;
|
|
41
|
+
private onMessage;
|
|
42
|
+
private failTransport;
|
|
43
|
+
private rejectAll;
|
|
44
|
+
}
|