@arnilo/prism-coding-agent 0.0.25 → 0.0.26
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 +9 -0
- package/README.md +2 -2
- 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/index.d.ts +10 -2
- package/dist/index.js +5 -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/limits.d.ts +41 -0
- package/dist/limits.js +41 -0
- 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/package.json +3 -3
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { AgentIdentity, ExecutionPolicy, OwnershipScope } from "@arnilo/prism";
|
|
2
|
+
/** Duck-typed long-running sandbox handle (mirrors coding-security SandboxProcessHandle). */
|
|
3
|
+
export interface ProcessSandboxHandle {
|
|
4
|
+
write(data: Uint8Array): Promise<void>;
|
|
5
|
+
signal(name: string): Promise<void>;
|
|
6
|
+
kill(): Promise<void>;
|
|
7
|
+
release(): Promise<void>;
|
|
8
|
+
wait(options?: {
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
exitCode: number | null;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
export interface ProcessSandboxStartRequest {
|
|
16
|
+
readonly file: string;
|
|
17
|
+
readonly args: readonly string[];
|
|
18
|
+
readonly cwd?: string;
|
|
19
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
20
|
+
readonly onData?: (data: Buffer) => void;
|
|
21
|
+
readonly signal?: AbortSignal;
|
|
22
|
+
readonly timeout?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Optional sandbox backend for ProcessSessions.
|
|
26
|
+
* Presence of `startProcess` = long-running capable; absence fails closed.
|
|
27
|
+
*/
|
|
28
|
+
export interface ProcessSandboxBackend {
|
|
29
|
+
startProcess?(request: ProcessSandboxStartRequest): Promise<ProcessSandboxHandle>;
|
|
30
|
+
status?(): Promise<{
|
|
31
|
+
readonly state: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
export type ProcessSessionState = "starting" | "running" | "exited" | "killed" | "released" | "expired" | "unknown";
|
|
35
|
+
export type ProcessSessionErrorCode = "ERR_PRISM_PROCESS_POLICY" | "ERR_PRISM_PROCESS_OWNERSHIP" | "ERR_PRISM_PROCESS_STATE" | "ERR_PRISM_PROCESS_LIMIT" | "ERR_PRISM_PROCESS_PTY_UNSUPPORTED" | "ERR_PRISM_PROCESS_UNSUPPORTED";
|
|
36
|
+
export declare class ProcessSessionError extends Error {
|
|
37
|
+
readonly code: ProcessSessionErrorCode;
|
|
38
|
+
constructor(code: ProcessSessionErrorCode, message: string);
|
|
39
|
+
}
|
|
40
|
+
export interface ProcessSessionLimits {
|
|
41
|
+
readonly maxSessions?: number;
|
|
42
|
+
readonly maxInputBytes?: number;
|
|
43
|
+
readonly maxLifetimeMs?: number;
|
|
44
|
+
readonly maxOutputChunkBytes?: number;
|
|
45
|
+
readonly maxTotalOutputBytes?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface ResolvedProcessSessionLimits {
|
|
48
|
+
readonly maxSessions: number;
|
|
49
|
+
readonly maxInputBytes: number;
|
|
50
|
+
readonly maxLifetimeMs: number;
|
|
51
|
+
readonly maxOutputChunkBytes: number;
|
|
52
|
+
readonly maxTotalOutputBytes: number;
|
|
53
|
+
}
|
|
54
|
+
export declare function resolveProcessSessionLimits(limits?: ProcessSessionLimits): ResolvedProcessSessionLimits;
|
|
55
|
+
export interface ProcessStartRequest {
|
|
56
|
+
readonly command: string;
|
|
57
|
+
readonly args?: readonly string[];
|
|
58
|
+
readonly cwd?: string;
|
|
59
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
60
|
+
/** Default false. true on unsupported platform → ERR_PRISM_PROCESS_PTY_UNSUPPORTED. */
|
|
61
|
+
readonly pty?: boolean;
|
|
62
|
+
readonly lifetimeMs?: number;
|
|
63
|
+
/** Owner string for this session; defaults to registry ownership key. */
|
|
64
|
+
readonly owner?: string;
|
|
65
|
+
/** When true, run cancel releases instead of killing (default kill). */
|
|
66
|
+
readonly releaseOnCancel?: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface ProcessOutputChunk {
|
|
69
|
+
readonly data: string;
|
|
70
|
+
/** Next byte cursor for paging. */
|
|
71
|
+
readonly cursor: number;
|
|
72
|
+
readonly eof: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface ProcessExitResult {
|
|
75
|
+
readonly exitCode: number | null;
|
|
76
|
+
readonly state: ProcessSessionState;
|
|
77
|
+
}
|
|
78
|
+
export interface ProcessSessionMetadata {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
readonly commandFingerprint: string;
|
|
81
|
+
readonly owner: string;
|
|
82
|
+
readonly workspace: string;
|
|
83
|
+
readonly policyDecision: string;
|
|
84
|
+
readonly startedAt: string;
|
|
85
|
+
readonly exitedAt?: string;
|
|
86
|
+
readonly state: ProcessSessionState;
|
|
87
|
+
readonly releaseOnCancel: boolean;
|
|
88
|
+
}
|
|
89
|
+
export interface ProcessSession {
|
|
90
|
+
readonly id: string;
|
|
91
|
+
readonly state: ProcessSessionState;
|
|
92
|
+
readonly owner: string;
|
|
93
|
+
metadata(): ProcessSessionMetadata;
|
|
94
|
+
output(request?: {
|
|
95
|
+
cursor?: number;
|
|
96
|
+
maxBytes?: number;
|
|
97
|
+
}): Promise<ProcessOutputChunk>;
|
|
98
|
+
input(data: string | Uint8Array): Promise<void>;
|
|
99
|
+
wait(options?: {
|
|
100
|
+
timeoutMs?: number;
|
|
101
|
+
signal?: AbortSignal;
|
|
102
|
+
}): Promise<ProcessExitResult>;
|
|
103
|
+
signal(name: "SIGTERM" | "SIGINT" | "SIGHUP"): Promise<void>;
|
|
104
|
+
kill(): Promise<void>;
|
|
105
|
+
release(): Promise<void>;
|
|
106
|
+
}
|
|
107
|
+
export type CodingProcessEvent = {
|
|
108
|
+
readonly type: "process_started" | "process_exited" | "process_killed" | "process_released" | "process_expired" | "process_unknown";
|
|
109
|
+
readonly sessionId: string;
|
|
110
|
+
readonly processId: string;
|
|
111
|
+
readonly owner: string;
|
|
112
|
+
readonly exitCode?: number | null;
|
|
113
|
+
readonly at: string;
|
|
114
|
+
};
|
|
115
|
+
export interface ProcessSessions {
|
|
116
|
+
start(request: ProcessStartRequest): Promise<ProcessSession>;
|
|
117
|
+
get(sessionId: string, owner?: string): ProcessSession;
|
|
118
|
+
/** Kill (default) or release all sessions for `owner`. */
|
|
119
|
+
cancelOwned(owner: string, options?: {
|
|
120
|
+
release?: boolean;
|
|
121
|
+
}): Promise<void>;
|
|
122
|
+
/** Mark a running session unknown (backend loss); never fabricates exitCode. */
|
|
123
|
+
markUnknown(sessionId: string, owner?: string): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Host resume / sandbox-loss reconciliation: mark every running/starting session unknown.
|
|
126
|
+
* Never fabricates exitCode. O(owned sessions).
|
|
127
|
+
*/
|
|
128
|
+
reconcile(): Promise<{
|
|
129
|
+
readonly markedUnknown: number;
|
|
130
|
+
}>;
|
|
131
|
+
dispose(): Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
export interface CreateProcessSessionsOptions {
|
|
134
|
+
readonly cwd: string;
|
|
135
|
+
readonly policy?: ExecutionPolicy;
|
|
136
|
+
readonly limits?: ProcessSessionLimits;
|
|
137
|
+
readonly onEvent?: (event: CodingProcessEvent) => void;
|
|
138
|
+
readonly ownership?: OwnershipScope;
|
|
139
|
+
/** Host-verified identity; projects onto default owner when ownership omitted. */
|
|
140
|
+
readonly identity?: AgentIdentity;
|
|
141
|
+
/**
|
|
142
|
+
* When set: use `startProcess` if present; otherwise start() fails closed
|
|
143
|
+
* (`ERR_PRISM_PROCESS_UNSUPPORTED`). Native spawn only when sandbox omitted.
|
|
144
|
+
*/
|
|
145
|
+
readonly sandbox?: ProcessSandboxBackend;
|
|
146
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { 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, 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, validateCodingLimit, } from "../limits.js";
|
|
2
|
+
export class ProcessSessionError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "ProcessSessionError";
|
|
7
|
+
this.code = code;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function resolveProcessSessionLimits(limits) {
|
|
11
|
+
return {
|
|
12
|
+
maxSessions: validateCodingLimit("maxSessions", limits?.maxSessions ?? DEFAULT_MAX_PROCESS_SESSIONS, HARD_MAX_PROCESS_SESSIONS),
|
|
13
|
+
maxInputBytes: validateCodingLimit("maxInputBytes", limits?.maxInputBytes ?? DEFAULT_MAX_PROCESS_INPUT_BYTES, HARD_MAX_PROCESS_INPUT_BYTES),
|
|
14
|
+
maxLifetimeMs: validateCodingLimit("maxLifetimeMs", limits?.maxLifetimeMs ?? DEFAULT_MAX_PROCESS_LIFETIME_MS, HARD_MAX_PROCESS_LIFETIME_MS),
|
|
15
|
+
maxOutputChunkBytes: validateCodingLimit("maxOutputChunkBytes", limits?.maxOutputChunkBytes ?? DEFAULT_MAX_PROCESS_OUTPUT_CHUNK_BYTES, HARD_MAX_PROCESS_OUTPUT_CHUNK_BYTES),
|
|
16
|
+
maxTotalOutputBytes: validateCodingLimit("maxTotalOutputBytes", limits?.maxTotalOutputBytes ?? DEFAULT_MAX_PROCESS_TOTAL_OUTPUT_BYTES, HARD_MAX_PROCESS_TOTAL_OUTPUT_BYTES),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=types.js.map
|
package/dist/repository.d.ts
CHANGED
|
@@ -146,5 +146,25 @@ export declare function compileSearchPattern(query: string, caseSensitive: boole
|
|
|
146
146
|
} | null;
|
|
147
147
|
patternBytes: number;
|
|
148
148
|
};
|
|
149
|
+
export interface RepositoryWalkLimits {
|
|
150
|
+
maxDepth: number;
|
|
151
|
+
maxEntries: number;
|
|
152
|
+
maxFiles: number;
|
|
153
|
+
exclude: ReadonlySet<string>;
|
|
154
|
+
includeHidden: boolean;
|
|
155
|
+
signal?: AbortSignal;
|
|
156
|
+
deadlineAt?: number;
|
|
157
|
+
}
|
|
158
|
+
export type RepositoryWalkEvent = {
|
|
159
|
+
type: "entry";
|
|
160
|
+
entry: RepoListEntry;
|
|
161
|
+
absolutePath: string;
|
|
162
|
+
depth: number;
|
|
163
|
+
} | {
|
|
164
|
+
type: "limit";
|
|
165
|
+
truncatedBy: "entries" | "files" | "depth";
|
|
166
|
+
};
|
|
167
|
+
/** Injectable enumerator for list/search/glob. Default is the native opendir walker. */
|
|
168
|
+
export type RepositoryWalk = (rootReal: string, startAbsolute: string, limits: RepositoryWalkLimits) => AsyncGenerator<RepositoryWalkEvent>;
|
|
149
169
|
/** Local filesystem repository operations (default backend). */
|
|
150
|
-
export declare function createLocalRepositoryOperations(limits?: RepositoryLimitOptions): RepositoryOperations;
|
|
170
|
+
export declare function createLocalRepositoryOperations(limits?: RepositoryLimitOptions, walk?: RepositoryWalk): RepositoryOperations;
|
package/dist/repository.js
CHANGED
|
@@ -239,7 +239,7 @@ async function* walkRepository(rootReal, startAbsolute, limits) {
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
|
-
async function listLocal(request, defaults) {
|
|
242
|
+
async function listLocal(request, defaults, walk) {
|
|
243
243
|
const resolved = await resolveRepoPath(request.root, request.path);
|
|
244
244
|
const maxResults = validateCodingLimit("maxResults", request.maxResults ?? defaults.maxResults, HARD_MAX_REPO_RESULTS);
|
|
245
245
|
const offset = validateCodingLimitAllowZero("offset", request.offset ?? 0, HARD_MAX_REPO_ENTRIES);
|
|
@@ -286,7 +286,7 @@ async function listLocal(request, defaults) {
|
|
|
286
286
|
throw new RepositoryError(`cannot open path: ${message}`);
|
|
287
287
|
}
|
|
288
288
|
try {
|
|
289
|
-
for await (const event of
|
|
289
|
+
for await (const event of walk(resolved.rootReal, resolved.absolute, {
|
|
290
290
|
maxDepth,
|
|
291
291
|
maxEntries: defaults.maxEntries,
|
|
292
292
|
maxFiles: defaults.maxFiles,
|
|
@@ -458,7 +458,7 @@ async function searchFileLines(absolutePath, relativePath, testLine, options) {
|
|
|
458
458
|
await handle.close();
|
|
459
459
|
}
|
|
460
460
|
}
|
|
461
|
-
async function searchLocal(request, defaults) {
|
|
461
|
+
async function searchLocal(request, defaults, walk) {
|
|
462
462
|
const mode = request.mode ?? "literal";
|
|
463
463
|
if (mode !== "literal") {
|
|
464
464
|
throw new RepositoryError(`unsupported search mode: ${String(mode)} (literal only)`);
|
|
@@ -519,7 +519,7 @@ async function searchLocal(request, defaults) {
|
|
|
519
519
|
await runFile(resolved.absolute, resolved.relative);
|
|
520
520
|
}
|
|
521
521
|
else if (startStat.isDirectory()) {
|
|
522
|
-
for await (const event of
|
|
522
|
+
for await (const event of walk(resolved.rootReal, resolved.absolute, {
|
|
523
523
|
maxDepth: defaults.maxDepth,
|
|
524
524
|
maxEntries: defaults.maxEntries,
|
|
525
525
|
maxFiles: defaults.maxFiles,
|
|
@@ -603,7 +603,7 @@ async function searchLocal(request, defaults) {
|
|
|
603
603
|
filesSkippedOversize,
|
|
604
604
|
};
|
|
605
605
|
}
|
|
606
|
-
async function globLocal(request, defaults) {
|
|
606
|
+
async function globLocal(request, defaults, walk) {
|
|
607
607
|
try {
|
|
608
608
|
validateGlobPattern(request.pattern, defaults.maxPatternBytes);
|
|
609
609
|
}
|
|
@@ -669,7 +669,7 @@ async function globLocal(request, defaults) {
|
|
|
669
669
|
throw new RepositoryError(`cannot open path: ${message}`);
|
|
670
670
|
}
|
|
671
671
|
try {
|
|
672
|
-
for await (const event of
|
|
672
|
+
for await (const event of walk(resolved.rootReal, resolved.absolute, {
|
|
673
673
|
maxDepth,
|
|
674
674
|
maxEntries: defaults.maxEntries,
|
|
675
675
|
maxFiles: defaults.maxFiles,
|
|
@@ -728,12 +728,12 @@ async function globLocal(request, defaults) {
|
|
|
728
728
|
};
|
|
729
729
|
}
|
|
730
730
|
/** Local filesystem repository operations (default backend). */
|
|
731
|
-
export function createLocalRepositoryOperations(limits) {
|
|
731
|
+
export function createLocalRepositoryOperations(limits, walk = walkRepository) {
|
|
732
732
|
const resolved = resolveRepositoryLimits(limits);
|
|
733
733
|
return {
|
|
734
|
-
list: (request) => listLocal(request, resolved),
|
|
735
|
-
search: (request) => searchLocal(request, resolved),
|
|
736
|
-
glob: (request) => globLocal(request, resolved),
|
|
734
|
+
list: (request) => listLocal(request, resolved, walk),
|
|
735
|
+
search: (request) => searchLocal(request, resolved, walk),
|
|
736
|
+
glob: (request) => globLocal(request, resolved, walk),
|
|
737
737
|
};
|
|
738
738
|
}
|
|
739
739
|
//# sourceMappingURL=repository.js.map
|
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.26",
|
|
4
4
|
"description": "Optional coding-agent tools (shell, read, write, edit, repo_list, repo_search, glob, delete, move, 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.26",
|
|
32
|
+
"@arnilo/prism-workflows": "0.0.26"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@arnilo/prism": "file:../..",
|