@llm4ts/runner 0.1.0
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/LICENSE +21 -0
- package/README.md +61 -0
- package/dist/Cli.d.ts +5 -0
- package/dist/Cli.d.ts.map +1 -0
- package/dist/Cli.js +36 -0
- package/dist/Cli.js.map +1 -0
- package/dist/CoderPolicy.d.ts +12 -0
- package/dist/CoderPolicy.d.ts.map +1 -0
- package/dist/CoderPolicy.js +59 -0
- package/dist/CoderPolicy.js.map +1 -0
- package/dist/Connectors.d.ts +28 -0
- package/dist/Connectors.d.ts.map +1 -0
- package/dist/Connectors.js +165 -0
- package/dist/Connectors.js.map +1 -0
- package/dist/Doctor.d.ts +4 -0
- package/dist/Doctor.d.ts.map +1 -0
- package/dist/Doctor.js +33 -0
- package/dist/Doctor.js.map +1 -0
- package/dist/FlowArgs.d.ts +34 -0
- package/dist/FlowArgs.d.ts.map +1 -0
- package/dist/FlowArgs.js +136 -0
- package/dist/FlowArgs.js.map +1 -0
- package/dist/FlowRunner.d.ts +48 -0
- package/dist/FlowRunner.d.ts.map +1 -0
- package/dist/FlowRunner.js +97 -0
- package/dist/FlowRunner.js.map +1 -0
- package/dist/McpStdio.d.ts +7 -0
- package/dist/McpStdio.d.ts.map +1 -0
- package/dist/McpStdio.js +19 -0
- package/dist/McpStdio.js.map +1 -0
- package/dist/NodeGeminiCliExecutor.d.ts +7 -0
- package/dist/NodeGeminiCliExecutor.d.ts.map +1 -0
- package/dist/NodeGeminiCliExecutor.js +26 -0
- package/dist/NodeGeminiCliExecutor.js.map +1 -0
- package/dist/NodeHttpClient.d.ts +5 -0
- package/dist/NodeHttpClient.d.ts.map +1 -0
- package/dist/NodeHttpClient.js +109 -0
- package/dist/NodeHttpClient.js.map +1 -0
- package/dist/NodePlainFileStore.d.ts +5 -0
- package/dist/NodePlainFileStore.d.ts.map +1 -0
- package/dist/NodePlainFileStore.js +64 -0
- package/dist/NodePlainFileStore.js.map +1 -0
- package/dist/NodeProcessExecutor.d.ts +5 -0
- package/dist/NodeProcessExecutor.d.ts.map +1 -0
- package/dist/NodeProcessExecutor.js +212 -0
- package/dist/NodeProcessExecutor.js.map +1 -0
- package/dist/NodeRuntime.d.ts +4 -0
- package/dist/NodeRuntime.d.ts.map +1 -0
- package/dist/NodeRuntime.js +11 -0
- package/dist/NodeRuntime.js.map +1 -0
- package/dist/NodeTemporaryFiles.d.ts +5 -0
- package/dist/NodeTemporaryFiles.d.ts.map +1 -0
- package/dist/NodeTemporaryFiles.js +30 -0
- package/dist/NodeTemporaryFiles.js.map +1 -0
- package/dist/NodeWorkspace.d.ts +6 -0
- package/dist/NodeWorkspace.d.ts.map +1 -0
- package/dist/NodeWorkspace.js +231 -0
- package/dist/NodeWorkspace.js.map +1 -0
- package/dist/Package.d.ts +2 -0
- package/dist/Package.d.ts.map +1 -0
- package/dist/Package.js +2 -0
- package/dist/Package.js.map +1 -0
- package/dist/ReviewFingerprint.d.ts +2 -0
- package/dist/ReviewFingerprint.d.ts.map +1 -0
- package/dist/ReviewFingerprint.js +13 -0
- package/dist/ReviewFingerprint.js.map +1 -0
- package/dist/Terminal.d.ts +46 -0
- package/dist/Terminal.d.ts.map +1 -0
- package/dist/Terminal.js +226 -0
- package/dist/Terminal.js.map +1 -0
- package/dist/TerminalInteraction.d.ts +4 -0
- package/dist/TerminalInteraction.d.ts.map +1 -0
- package/dist/TerminalInteraction.js +25 -0
- package/dist/TerminalInteraction.js.map +1 -0
- package/dist/cli-main.d.ts +3 -0
- package/dist/cli-main.d.ts.map +1 -0
- package/dist/cli-main.js +39 -0
- package/dist/cli-main.js.map +1 -0
- package/package.json +74 -0
- package/src/Cli.ts +51 -0
- package/src/CoderPolicy.ts +82 -0
- package/src/Connectors.ts +225 -0
- package/src/Doctor.ts +44 -0
- package/src/FlowArgs.ts +167 -0
- package/src/FlowRunner.ts +220 -0
- package/src/McpStdio.ts +41 -0
- package/src/NodeGeminiCliExecutor.ts +56 -0
- package/src/NodeHttpClient.ts +224 -0
- package/src/NodePlainFileStore.ts +75 -0
- package/src/NodeProcessExecutor.ts +331 -0
- package/src/NodeRuntime.ts +19 -0
- package/src/NodeTemporaryFiles.ts +46 -0
- package/src/NodeWorkspace.ts +282 -0
- package/src/Package.ts +1 -0
- package/src/ReviewFingerprint.ts +13 -0
- package/src/Terminal.ts +329 -0
- package/src/TerminalInteraction.ts +43 -0
- package/src/cli-main.ts +53 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type * as Duration from "effect/Duration";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Ref from "effect/Ref";
|
|
4
|
+
import type * as Scope from "effect/Scope";
|
|
5
|
+
import * as Schema from "effect/Schema";
|
|
6
|
+
import type { FlowEvent, FlowEventHub } from "@llm4ts/flow/FlowEvents";
|
|
7
|
+
export declare const Verbosity: Schema.Literals<readonly ["Quiet", "Normal", "Verbose", "Debug"]>;
|
|
8
|
+
export type Verbosity = typeof Verbosity.Type;
|
|
9
|
+
export declare const parseVerbosity: (value: string | undefined) => Verbosity;
|
|
10
|
+
export declare const rendersEvent: (verbosity: Verbosity, event: FlowEvent) => boolean;
|
|
11
|
+
export declare const terminalSafe: (value: string) => string;
|
|
12
|
+
export interface TerminalPalette {
|
|
13
|
+
readonly enabled: boolean;
|
|
14
|
+
readonly stageStart: (label: string) => string;
|
|
15
|
+
readonly stageDone: (label: string) => string;
|
|
16
|
+
readonly fail: (label: string) => string;
|
|
17
|
+
readonly info: (label: string) => string;
|
|
18
|
+
readonly assistant: (text: string) => string;
|
|
19
|
+
readonly toolCall: (tool: string, args: string) => string;
|
|
20
|
+
readonly status: (frame: string, label: string) => string;
|
|
21
|
+
}
|
|
22
|
+
export declare const makeTerminalPalette: (enabled: boolean) => TerminalPalette;
|
|
23
|
+
export declare const plainTerminalPalette: TerminalPalette;
|
|
24
|
+
export declare const terminalLine: (event: FlowEvent, palette?: TerminalPalette) => string;
|
|
25
|
+
export declare const indentBlock: (depth: number, rendered: string) => string;
|
|
26
|
+
export declare const indentDepths: (events: ReadonlyArray<FlowEvent>) => ReadonlyArray<number>;
|
|
27
|
+
export interface TerminalSurface {
|
|
28
|
+
readonly palette: TerminalPalette;
|
|
29
|
+
readonly log: (line: string) => Effect.Effect<void>;
|
|
30
|
+
readonly setStatus: (label: string | undefined) => Effect.Effect<void>;
|
|
31
|
+
readonly suspend: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>;
|
|
32
|
+
}
|
|
33
|
+
export declare const makePlainTerminalSurface: (write?: (line: string) => void) => TerminalSurface;
|
|
34
|
+
export interface TerminalOutput {
|
|
35
|
+
readonly isTTY?: boolean;
|
|
36
|
+
readonly write: (text: string) => unknown;
|
|
37
|
+
}
|
|
38
|
+
export declare const terminalSupportsColor: (output: TerminalOutput, environment: Readonly<Record<string, string | undefined>>) => boolean;
|
|
39
|
+
export declare const makeLiveTerminalSurface: (write?: ((text: string) => void) | undefined, palette?: TerminalPalette | undefined, tick?: Duration.Input | undefined) => Effect.Effect<TerminalSurface, never, Scope.Scope>;
|
|
40
|
+
export declare const makeTerminalSurface: (environment?: Readonly<Record<string, string | undefined>>, output?: TerminalOutput) => Effect.Effect<TerminalSurface, never, Scope.Scope>;
|
|
41
|
+
export interface TerminalConsumer {
|
|
42
|
+
readonly consumed: Ref.Ref<number>;
|
|
43
|
+
readonly awaitDrained: (timeout?: Duration.Input) => Effect.Effect<void>;
|
|
44
|
+
}
|
|
45
|
+
export declare const consumeTerminalEvents: (events: FlowEventHub, surface: TerminalSurface, verbosity?: "Debug" | "Quiet" | "Normal" | "Verbose" | undefined) => Effect.Effect<TerminalConsumer, never, Scope.Scope>;
|
|
46
|
+
//# sourceMappingURL=Terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Terminal.d.ts","sourceRoot":"","sources":["../src/Terminal.ts"],"names":[],"mappings":"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"}
|
package/dist/Terminal.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as Ref from "effect/Ref";
|
|
3
|
+
import * as Semaphore from "effect/Semaphore";
|
|
4
|
+
import * as Schema from "effect/Schema";
|
|
5
|
+
import * as Stream from "effect/Stream";
|
|
6
|
+
export const Verbosity = Schema.Literals(["Quiet", "Normal", "Verbose", "Debug"]);
|
|
7
|
+
export const parseVerbosity = (value) => {
|
|
8
|
+
switch (value?.trim().toLowerCase()) {
|
|
9
|
+
case "quiet":
|
|
10
|
+
return "Quiet";
|
|
11
|
+
case "verbose":
|
|
12
|
+
return "Verbose";
|
|
13
|
+
case "debug":
|
|
14
|
+
return "Debug";
|
|
15
|
+
default:
|
|
16
|
+
return "Normal";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
export const rendersEvent = (verbosity, event) => {
|
|
20
|
+
switch (event._tag) {
|
|
21
|
+
case "StageStarted":
|
|
22
|
+
case "StageCompleted":
|
|
23
|
+
case "StageFailed":
|
|
24
|
+
case "Aborted":
|
|
25
|
+
case "CapabilityDenied":
|
|
26
|
+
case "CapabilityUnenforceable":
|
|
27
|
+
return true;
|
|
28
|
+
case "TokensUsed":
|
|
29
|
+
return verbosity === "Verbose" || verbosity === "Debug";
|
|
30
|
+
default:
|
|
31
|
+
return verbosity !== "Quiet";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
export const terminalSafe = (value) => {
|
|
35
|
+
let safe = "";
|
|
36
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
37
|
+
const code = value.charCodeAt(index);
|
|
38
|
+
const escapedCsi = code === 27 && value.charAt(index + 1) === "[";
|
|
39
|
+
if (escapedCsi || code === 155) {
|
|
40
|
+
index += escapedCsi ? 2 : 1;
|
|
41
|
+
while (index < value.length) {
|
|
42
|
+
const terminator = value.charCodeAt(index);
|
|
43
|
+
if (terminator >= 64 && terminator <= 126) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
index += 1;
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const escapedOsc = code === 27 && value.charAt(index + 1) === "]";
|
|
51
|
+
if (escapedOsc || code === 157) {
|
|
52
|
+
index += escapedOsc ? 2 : 1;
|
|
53
|
+
while (index < value.length) {
|
|
54
|
+
const current = value.charCodeAt(index);
|
|
55
|
+
if (current === 7) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
if (current === 27 && value.charAt(index + 1) === "\\") {
|
|
59
|
+
index += 1;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
index += 1;
|
|
63
|
+
}
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const allowedWhitespace = code === 9 || code === 10 || code === 13;
|
|
67
|
+
if (allowedWhitespace || (code >= 32 && !(code >= 127 && code <= 159))) {
|
|
68
|
+
safe += value.charAt(index);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return safe;
|
|
72
|
+
};
|
|
73
|
+
const Ansi = Object.freeze({
|
|
74
|
+
reset: "\u001b[0m",
|
|
75
|
+
boldMagenta: "\u001b[1;35m",
|
|
76
|
+
green: "\u001b[32m",
|
|
77
|
+
red: "\u001b[31m",
|
|
78
|
+
yellowBold: "\u001b[1;33m",
|
|
79
|
+
darkGray: "\u001b[90m"
|
|
80
|
+
});
|
|
81
|
+
export const makeTerminalPalette = (enabled) => {
|
|
82
|
+
const paint = (code, text) => enabled ? `${code}${text}${Ansi.reset}` : text;
|
|
83
|
+
return {
|
|
84
|
+
enabled,
|
|
85
|
+
stageStart: (label) => `${paint(Ansi.boldMagenta, "▶ ")}${label}`,
|
|
86
|
+
stageDone: (label) => `${paint(Ansi.green, "✔ ")}${label}`,
|
|
87
|
+
fail: (label) => `${paint(Ansi.red, "✖ ")}${label}`,
|
|
88
|
+
info: (label) => paint(Ansi.darkGray, `· ${label}`),
|
|
89
|
+
assistant: (text) => `${paint(Ansi.boldMagenta, "● ")}${text}`,
|
|
90
|
+
toolCall: (tool, args) => {
|
|
91
|
+
const head = paint(Ansi.yellowBold, `● ${tool}`);
|
|
92
|
+
return args.length === 0 ? head : `${head} ${paint(Ansi.darkGray, args)}`;
|
|
93
|
+
},
|
|
94
|
+
status: (frame, label) => `${paint(Ansi.boldMagenta, frame)} ${label}`
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
export const plainTerminalPalette = makeTerminalPalette(false);
|
|
98
|
+
export const terminalLine = (event, palette = plainTerminalPalette) => {
|
|
99
|
+
const safe = terminalSafe;
|
|
100
|
+
switch (event._tag) {
|
|
101
|
+
case "StageStarted":
|
|
102
|
+
return palette.stageStart(safe(event.stage));
|
|
103
|
+
case "StageCompleted":
|
|
104
|
+
return palette.stageDone(safe(event.stage));
|
|
105
|
+
case "StageFailed":
|
|
106
|
+
return palette.fail(`${safe(event.stage)} — ${safe(event.message)}`);
|
|
107
|
+
case "Aborted":
|
|
108
|
+
return palette.fail(`aborted: ${safe(event.message)}`);
|
|
109
|
+
case "Info":
|
|
110
|
+
return palette.info(safe(event.message));
|
|
111
|
+
case "ToolUse":
|
|
112
|
+
return palette.toolCall(safe(event.tool), safe(event.args));
|
|
113
|
+
case "AssistantMessage":
|
|
114
|
+
return palette.assistant(safe(event.text).trim());
|
|
115
|
+
case "TokensUsed":
|
|
116
|
+
return palette.info(`tokens: ${safe(event.agent)} ${event.usage.prompt} in / ${event.usage.completion} out`);
|
|
117
|
+
case "CapabilityUsed":
|
|
118
|
+
return palette.info(`capability ${safe(event.capability)}: ${safe(event.operation)}`);
|
|
119
|
+
case "CapabilityDenied":
|
|
120
|
+
return palette.fail(`capability denied: ${safe(event.capability)} for ${safe(event.operation)}`);
|
|
121
|
+
case "CapabilityUnenforceable":
|
|
122
|
+
return palette.fail(`capability unenforceable: ${safe(event.detail)}`);
|
|
123
|
+
case "Declassified":
|
|
124
|
+
return palette.info(`declassified: ${safe(event.label)}`);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
export const indentBlock = (depth, rendered) => {
|
|
128
|
+
const padding = " ".repeat(Math.max(0, depth));
|
|
129
|
+
const lines = rendered.split("\n");
|
|
130
|
+
return lines.map((line, index) => `${padding}${index === 0 ? "" : " "}${line}`).join("\n");
|
|
131
|
+
};
|
|
132
|
+
const closesChild = (event) => event._tag === "StageCompleted" || event._tag === "StageFailed" || event._tag === "Aborted";
|
|
133
|
+
export const indentDepths = (events) => {
|
|
134
|
+
let depth = 0;
|
|
135
|
+
return events.map((event) => {
|
|
136
|
+
if (closesChild(event)) {
|
|
137
|
+
depth = Math.max(0, depth - 1);
|
|
138
|
+
return depth;
|
|
139
|
+
}
|
|
140
|
+
const current = depth;
|
|
141
|
+
if (event._tag === "StageStarted") {
|
|
142
|
+
depth += 1;
|
|
143
|
+
}
|
|
144
|
+
return current;
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
export const makePlainTerminalSurface = (write = (line) => process.stdout.write(`${line}\n`)) => ({
|
|
148
|
+
palette: plainTerminalPalette,
|
|
149
|
+
log: (line) => Effect.sync(() => write(line)),
|
|
150
|
+
setStatus: (_label) => Effect.void,
|
|
151
|
+
suspend: (effect) => effect
|
|
152
|
+
});
|
|
153
|
+
const spinnerFrames = Object.freeze(["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]);
|
|
154
|
+
const clearLine = "\r\u001b[2K";
|
|
155
|
+
export const terminalSupportsColor = (output, environment) => output.isTTY === true && environment.NO_COLOR === undefined;
|
|
156
|
+
export const makeLiveTerminalSurface = Effect.fn("@llm4ts/runner/Terminal.makeLive")(function* (write = (text) => {
|
|
157
|
+
process.stdout.write(text);
|
|
158
|
+
}, palette = makeTerminalPalette(true), tick = "100 millis") {
|
|
159
|
+
const lock = yield* Semaphore.make(1);
|
|
160
|
+
const status = yield* Ref.make(undefined);
|
|
161
|
+
const frame = yield* Ref.make(0);
|
|
162
|
+
const suspended = yield* Ref.make(false);
|
|
163
|
+
const emit = (text) => Effect.sync(() => write(text));
|
|
164
|
+
const drawStatus = Effect.gen(function* () {
|
|
165
|
+
if (yield* Ref.get(suspended)) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const label = yield* Ref.get(status);
|
|
169
|
+
if (label !== undefined) {
|
|
170
|
+
const currentFrame = yield* Ref.get(frame);
|
|
171
|
+
yield* emit(`${clearLine}${palette.status(spinnerFrames[currentFrame % spinnerFrames.length], label)}`);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
const surface = {
|
|
175
|
+
palette,
|
|
176
|
+
log: (line) => lock.withPermit(emit(clearLine).pipe(Effect.andThen(emit(`${line}\n`)), Effect.andThen(drawStatus))),
|
|
177
|
+
setStatus: (label) => lock.withPermit(Ref.set(status, label).pipe(Effect.andThen(emit(clearLine)), Effect.andThen(drawStatus))),
|
|
178
|
+
suspend: (effect) => lock
|
|
179
|
+
.withPermit(Ref.set(suspended, true).pipe(Effect.andThen(emit(clearLine))))
|
|
180
|
+
.pipe(Effect.andThen(effect), Effect.ensuring(lock.withPermit(Ref.set(suspended, false).pipe(Effect.andThen(drawStatus)))))
|
|
181
|
+
};
|
|
182
|
+
yield* Effect.sleep(tick).pipe(Effect.andThen(Ref.update(frame, (current) => current + 1)), Effect.andThen(lock.withPermit(drawStatus)), Effect.forever, Effect.forkScoped);
|
|
183
|
+
yield* Effect.addFinalizer(() => lock.withPermit(emit(clearLine)));
|
|
184
|
+
return surface;
|
|
185
|
+
});
|
|
186
|
+
export const makeTerminalSurface = (environment = process.env, output = process.stdout) => {
|
|
187
|
+
const write = (text) => {
|
|
188
|
+
output.write(text);
|
|
189
|
+
};
|
|
190
|
+
return terminalSupportsColor(output, environment)
|
|
191
|
+
? makeLiveTerminalSurface(write)
|
|
192
|
+
: Effect.succeed(makePlainTerminalSurface((line) => write(`${line}\n`)));
|
|
193
|
+
};
|
|
194
|
+
export const consumeTerminalEvents = Effect.fn("@llm4ts/runner/Terminal.consume")(function* (events, surface, verbosity = "Normal") {
|
|
195
|
+
const depth = yield* Ref.make(0);
|
|
196
|
+
const stages = yield* Ref.make([]);
|
|
197
|
+
const consumed = yield* Ref.make(0);
|
|
198
|
+
const subscription = yield* events.subscribe;
|
|
199
|
+
const palette = surface.palette;
|
|
200
|
+
yield* Stream.fromSubscription(subscription).pipe(Stream.runForEach((event) => Effect.gen(function* () {
|
|
201
|
+
const currentDepth = closesChild(event)
|
|
202
|
+
? yield* Ref.updateAndGet(depth, (value) => Math.max(0, value - 1))
|
|
203
|
+
: yield* Ref.get(depth);
|
|
204
|
+
if (event._tag === "StageStarted") {
|
|
205
|
+
yield* Ref.update(depth, (value) => value + 1);
|
|
206
|
+
const active = terminalSafe(event.stage);
|
|
207
|
+
yield* Ref.update(stages, (current) => [...current, active]);
|
|
208
|
+
yield* surface.setStatus(active);
|
|
209
|
+
}
|
|
210
|
+
else if (closesChild(event)) {
|
|
211
|
+
const remaining = yield* Ref.updateAndGet(stages, (current) => current.slice(0, -1));
|
|
212
|
+
yield* surface.setStatus(remaining.at(-1));
|
|
213
|
+
}
|
|
214
|
+
if (rendersEvent(verbosity, event)) {
|
|
215
|
+
yield* surface.log(indentBlock(currentDepth, terminalLine(event, palette)));
|
|
216
|
+
}
|
|
217
|
+
yield* Ref.update(consumed, (count) => count + 1);
|
|
218
|
+
})), Effect.forkScoped);
|
|
219
|
+
const awaitDrained = (timeout = "3 seconds") => Effect.gen(function* () {
|
|
220
|
+
const target = yield* events.publishedCount;
|
|
221
|
+
const drain = Effect.suspend(() => Ref.get(consumed).pipe(Effect.flatMap((count) => count >= target ? Effect.void : Effect.yieldNow.pipe(Effect.andThen(drain)))));
|
|
222
|
+
yield* Effect.timeoutOption(drain, timeout);
|
|
223
|
+
});
|
|
224
|
+
return { consumed, awaitDrained };
|
|
225
|
+
});
|
|
226
|
+
//# sourceMappingURL=Terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Terminal.js","sourceRoot":"","sources":["../src/Terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ApprovalPolicy, InteractionShape } from "@llm4ts/flow/Interaction";
|
|
2
|
+
export declare const terminalInteraction: InteractionShape;
|
|
3
|
+
export declare const terminalApprovalPolicy: (interaction?: InteractionShape) => ApprovalPolicy;
|
|
4
|
+
//# sourceMappingURL=TerminalInteraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalInteraction.d.ts","sourceRoot":"","sources":["../src/TerminalInteraction.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAGhF,eAAO,MAAM,mBAAmB,EAAE,gBAoBjC,CAAA;AAED,eAAO,MAAM,sBAAsB,GACjC,cAAa,gBAAsC,KAClD,cAWD,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createInterface } from "node:readline/promises";
|
|
2
|
+
import { stdin, stderr } from "node:process";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import { ProcessError } from "@llm4ts/flow/FlowError";
|
|
5
|
+
import { ApprovalAllowed, ApprovalDenied } from "@llm4ts/flow/Interaction";
|
|
6
|
+
export const terminalInteraction = {
|
|
7
|
+
ask: (question) => Effect.acquireUseRelease(Effect.sync(() => createInterface({
|
|
8
|
+
input: stdin,
|
|
9
|
+
output: stderr
|
|
10
|
+
})), (terminal) => Effect.tryPromise({
|
|
11
|
+
try: () => terminal.question(`❓ ${question}\n> `),
|
|
12
|
+
catch: (error) => ProcessError.make({
|
|
13
|
+
message: "terminal input",
|
|
14
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
15
|
+
})
|
|
16
|
+
}), (terminal) => Effect.sync(() => terminal.close()))
|
|
17
|
+
};
|
|
18
|
+
export const terminalApprovalPolicy = (interaction = terminalInteraction) => ({
|
|
19
|
+
decide: (toolName, input) => interaction
|
|
20
|
+
.ask(`Allow tool '${toolName}' with input ${JSON.stringify(input)}? [y/N]`)
|
|
21
|
+
.pipe(Effect.map((answer) => /^(y|yes)$/iu.test(answer.trim())
|
|
22
|
+
? new ApprovalAllowed()
|
|
23
|
+
: ApprovalDenied.make({ reason: "operator denied" })))
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=TerminalInteraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalInteraction.js","sourceRoot":"","sources":["../src/TerminalInteraction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAErD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAE1E,MAAM,CAAC,MAAM,mBAAmB,GAAqB;IACnD,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAChB,MAAM,CAAC,iBAAiB,CACtB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CACf,eAAe,CAAC;QACd,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;KACf,CAAC,CACH,EACD,CAAC,QAAQ,EAAE,EAAE,CACX,MAAM,CAAC,UAAU,CAAC;QAChB,GAAG,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,QAAQ,MAAM,CAAC;QACjD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CACf,YAAY,CAAC,IAAI,CAAC;YAChB,OAAO,EAAE,gBAAgB;YACzB,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC/D,CAAC;KACL,CAAC,EACJ,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAClD;CACJ,CAAA;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,cAAgC,mBAAmB,EACnC,EAAE,CAAC,CAAC;IACpB,MAAM,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,CAC1B,WAAW;SACR,GAAG,CAAC,eAAe,QAAQ,gBAAgB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC;SAC1E,IAAI,CACH,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACpB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC,CAAC,IAAI,eAAe,EAAE;QACvB,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,CACvD,CACF;CACN,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-main.d.ts","sourceRoot":"","sources":["../src/cli-main.ts"],"names":[],"mappings":""}
|
package/dist/cli-main.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import { makeCliProgram } from "./Cli.js";
|
|
5
|
+
import { makeDoctorProgram } from "./Doctor.js";
|
|
6
|
+
import { FlowHelp, parseFlowArgs } from "./FlowArgs.js";
|
|
7
|
+
const argv = process.argv.slice(2);
|
|
8
|
+
const packageVersion = () => {
|
|
9
|
+
const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
10
|
+
return typeof manifest === "object" &&
|
|
11
|
+
manifest !== null &&
|
|
12
|
+
"version" in manifest &&
|
|
13
|
+
typeof manifest.version === "string"
|
|
14
|
+
? manifest.version
|
|
15
|
+
: "unknown";
|
|
16
|
+
};
|
|
17
|
+
const flowProgram = () => {
|
|
18
|
+
const parsed = parseFlowArgs(argv);
|
|
19
|
+
if (parsed.ok && parsed.value.help === true) {
|
|
20
|
+
return Effect.sync(() => process.stdout.write(FlowHelp));
|
|
21
|
+
}
|
|
22
|
+
if (parsed.ok && parsed.value.version === true) {
|
|
23
|
+
return Effect.sync(() => process.stdout.write(`${packageVersion()}\n`));
|
|
24
|
+
}
|
|
25
|
+
return makeCliProgram(argv).pipe(Effect.match({
|
|
26
|
+
onFailure: (error) => {
|
|
27
|
+
process.stderr.write(`${error.message}\n`);
|
|
28
|
+
return error._tag === "ScriptUsage" ? 2 : 1;
|
|
29
|
+
},
|
|
30
|
+
onSuccess: () => 0
|
|
31
|
+
}), Effect.flatMap((exitCode) => Effect.sync(() => {
|
|
32
|
+
process.exitCode = exitCode;
|
|
33
|
+
})));
|
|
34
|
+
};
|
|
35
|
+
const main = argv[0] === "doctor"
|
|
36
|
+
? makeDoctorProgram().pipe(Effect.flatMap((report) => Effect.sync(() => process.stdout.write(report))))
|
|
37
|
+
: flowProgram();
|
|
38
|
+
Effect.runFork(main);
|
|
39
|
+
//# sourceMappingURL=cli-main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-main.js","sourceRoot":"","sources":["../src/cli-main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAEvD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAElC,MAAM,cAAc,GAAG,GAAW,EAAE;IAClC,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAClC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAClE,CAAA;IACD,OAAO,OAAO,QAAQ,KAAK,QAAQ;QACjC,QAAQ,KAAK,IAAI;QACjB,SAAS,IAAI,QAAQ;QACrB,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ;QACpC,CAAC,CAAC,QAAQ,CAAC,OAAO;QAClB,CAAC,CAAC,SAAS,CAAA;AACf,CAAC,CAAA;AAED,MAAM,WAAW,GAAG,GAAwB,EAAE;IAC5C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;IAClC,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC1D,CAAC;IACD,IAAI,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,cAAc,EAAE,IAAI,CAAC,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAC9B,MAAM,CAAC,KAAK,CAAC;QACX,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;YAC1C,OAAO,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7C,CAAC;QACD,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;KACnB,CAAC,EACF,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC7B,CAAC,CAAC,CACH,CACF,CAAA;AACH,CAAC,CAAA;AAED,MAAM,IAAI,GACR,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;IAClB,CAAC,CAAC,iBAAiB,EAAE,CAAC,IAAI,CACtB,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAC5E;IACH,CAAC,CAAC,WAAW,EAAE,CAAA;AAEnB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@llm4ts/runner",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Node runner, CLI, terminal, and MCP composition for llm4ts",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=22"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"src"
|
|
14
|
+
],
|
|
15
|
+
"bin": {
|
|
16
|
+
"llm4ts": "./dist/cli-main.js"
|
|
17
|
+
},
|
|
18
|
+
"exports": {
|
|
19
|
+
"./Cli": "./dist/Cli.js",
|
|
20
|
+
"./CoderPolicy": "./dist/CoderPolicy.js",
|
|
21
|
+
"./Connectors": "./dist/Connectors.js",
|
|
22
|
+
"./Doctor": "./dist/Doctor.js",
|
|
23
|
+
"./FlowArgs": "./dist/FlowArgs.js",
|
|
24
|
+
"./FlowRunner": "./dist/FlowRunner.js",
|
|
25
|
+
"./McpStdio": "./dist/McpStdio.js",
|
|
26
|
+
"./NodeHttpClient": "./dist/NodeHttpClient.js",
|
|
27
|
+
"./NodeGeminiCliExecutor": "./dist/NodeGeminiCliExecutor.js",
|
|
28
|
+
"./NodePlainFileStore": "./dist/NodePlainFileStore.js",
|
|
29
|
+
"./NodeProcessExecutor": "./dist/NodeProcessExecutor.js",
|
|
30
|
+
"./NodeTemporaryFiles": "./dist/NodeTemporaryFiles.js",
|
|
31
|
+
"./NodeWorkspace": "./dist/NodeWorkspace.js",
|
|
32
|
+
"./NodeRuntime": "./dist/NodeRuntime.js",
|
|
33
|
+
"./ReviewFingerprint": "./dist/ReviewFingerprint.js",
|
|
34
|
+
"./Terminal": "./dist/Terminal.js",
|
|
35
|
+
"./TerminalInteraction": "./dist/TerminalInteraction.js",
|
|
36
|
+
"./Package": "./dist/Package.js",
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public",
|
|
41
|
+
"provenance": true
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/riccardomerolla/llm4ts.git",
|
|
46
|
+
"directory": "packages/runner"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/riccardomerolla/llm4ts#readme",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/riccardomerolla/llm4ts/issues"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"llm",
|
|
54
|
+
"effect",
|
|
55
|
+
"ai",
|
|
56
|
+
"agents",
|
|
57
|
+
"workflow",
|
|
58
|
+
"typescript"
|
|
59
|
+
],
|
|
60
|
+
"dependencies": {
|
|
61
|
+
"@llm4ts/core": "0.1.0",
|
|
62
|
+
"@llm4ts/flow": "0.1.0"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"effect": "^4.0.0-beta.102"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"effect": "^4.0.0-beta.102"
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"clean": "tsc -b tsconfig.json --clean",
|
|
72
|
+
"test": "vitest run test"
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/Cli.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { join } from "node:path"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import { FlowLlmError, type FlowError } from "@llm4ts/flow/FlowError"
|
|
4
|
+
import { AssistantMessage } from "@llm4ts/flow/FlowEvents"
|
|
5
|
+
import { collect } from "@llm4ts/core/Streaming"
|
|
6
|
+
import { CliConnectorConfig } from "@llm4ts/core/ConnectorConfig"
|
|
7
|
+
import { coderFromEnv } from "./Connectors.ts"
|
|
8
|
+
import { parseFlowArgs, readFlowPrompt, resolveFlowRepo, type ScriptUsage } from "./FlowArgs.ts"
|
|
9
|
+
import { runNode } from "./FlowRunner.ts"
|
|
10
|
+
import { parseVerbosity } from "./Terminal.ts"
|
|
11
|
+
|
|
12
|
+
export const makeCliProgram = (
|
|
13
|
+
argv: ReadonlyArray<string>,
|
|
14
|
+
environment: Readonly<Record<string, string | undefined>> = process.env,
|
|
15
|
+
workspace = process.cwd(),
|
|
16
|
+
defaultPrompt?: string
|
|
17
|
+
): Effect.Effect<void, ScriptUsage | FlowError> => {
|
|
18
|
+
const parsed = parseFlowArgs(argv)
|
|
19
|
+
if (!parsed.ok) {
|
|
20
|
+
return Effect.fail(parsed.error)
|
|
21
|
+
}
|
|
22
|
+
return Effect.gen(function* () {
|
|
23
|
+
const prompt = yield* readFlowPrompt(parsed.value, defaultPrompt)
|
|
24
|
+
const workDir = yield* resolveFlowRepo(parsed.value, workspace)
|
|
25
|
+
const selected = coderFromEnv(environment)
|
|
26
|
+
const coder = CliConnectorConfig.make({
|
|
27
|
+
...selected,
|
|
28
|
+
workingDir: workDir
|
|
29
|
+
})
|
|
30
|
+
const timestamp = Date.now()
|
|
31
|
+
yield* runNode(
|
|
32
|
+
{
|
|
33
|
+
workDir,
|
|
34
|
+
workspace,
|
|
35
|
+
userPrompt: prompt,
|
|
36
|
+
coder,
|
|
37
|
+
verbosity: parseVerbosity(environment.LLM4TS_VERBOSITY),
|
|
38
|
+
tracePath: join(workDir, ".llm4ts", `trace-${timestamp}.jsonl`),
|
|
39
|
+
runId: timestamp.toString()
|
|
40
|
+
},
|
|
41
|
+
(context) =>
|
|
42
|
+
collect(context.coder.executeStream(prompt)).pipe(
|
|
43
|
+
Effect.mapError(FlowLlmError.from),
|
|
44
|
+
Effect.tap((response) =>
|
|
45
|
+
context.events.publish(AssistantMessage.make({ text: response.content }))
|
|
46
|
+
),
|
|
47
|
+
Effect.asVoid
|
|
48
|
+
)
|
|
49
|
+
)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema"
|
|
2
|
+
import { Capabilities, type Capability, allows } from "@llm4ts/core/Capability"
|
|
3
|
+
import type { Grants } from "@llm4ts/core/Capability"
|
|
4
|
+
import { CliConnectorConfig } from "@llm4ts/core/ConnectorConfig"
|
|
5
|
+
import { ConnectorIds } from "@llm4ts/core/Models"
|
|
6
|
+
|
|
7
|
+
export class AppliedCoderPolicy extends Schema.Class<AppliedCoderPolicy>("AppliedCoderPolicy")({
|
|
8
|
+
config: CliConnectorConfig,
|
|
9
|
+
unenforceable: Schema.Array(Schema.String)
|
|
10
|
+
}) {}
|
|
11
|
+
|
|
12
|
+
interface DeniedPattern {
|
|
13
|
+
readonly capability: Capability
|
|
14
|
+
readonly pattern: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const patterns: ReadonlyArray<DeniedPattern> = [
|
|
18
|
+
{
|
|
19
|
+
capability: Capabilities.GitPush,
|
|
20
|
+
pattern: "Bash(git push:*)"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
capability: Capabilities.GitWrite,
|
|
24
|
+
pattern: "Bash(git commit:*),Bash(git add:*),Bash(git checkout:*)"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
capability: Capabilities.GhWrite,
|
|
28
|
+
pattern: "Bash(gh pr:*),Bash(gh issue:*),Bash(gh api:*)"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
capability: Capabilities.AdoWrite,
|
|
32
|
+
pattern: "Bash(az repos:*),Bash(az boards:*)"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
const capabilityName = (capability: Capability): string =>
|
|
37
|
+
capability._tag === "Exec" ? `Exec(${capability.command})` : capability._tag
|
|
38
|
+
|
|
39
|
+
const withDisallowed = (
|
|
40
|
+
config: CliConnectorConfig,
|
|
41
|
+
denied: ReadonlyArray<DeniedPattern>
|
|
42
|
+
): CliConnectorConfig => {
|
|
43
|
+
const existing = config.flags["disallowed-tools"]
|
|
44
|
+
const values = [
|
|
45
|
+
...(existing === undefined || existing.length === 0 ? [] : [existing]),
|
|
46
|
+
...denied.map(({ pattern }) => pattern)
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
return new CliConnectorConfig({
|
|
50
|
+
...config,
|
|
51
|
+
flags: {
|
|
52
|
+
...config.flags,
|
|
53
|
+
"disallowed-tools": values.join(",")
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const applyCoderPolicy = (
|
|
59
|
+
config: CliConnectorConfig,
|
|
60
|
+
grants: Grants
|
|
61
|
+
): AppliedCoderPolicy => {
|
|
62
|
+
const denied = patterns.filter(({ capability }) => !allows(grants, capability))
|
|
63
|
+
|
|
64
|
+
if (denied.length === 0) {
|
|
65
|
+
return new AppliedCoderPolicy({ config, unenforceable: [] })
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (config.connectorId.value === ConnectorIds.ClaudeCli.value) {
|
|
69
|
+
return new AppliedCoderPolicy({
|
|
70
|
+
config: withDisallowed(config, denied),
|
|
71
|
+
unenforceable: []
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return new AppliedCoderPolicy({
|
|
76
|
+
config,
|
|
77
|
+
unenforceable: denied.map(
|
|
78
|
+
({ capability }) =>
|
|
79
|
+
`${config.connectorId.value} cannot enforce the missing ${capabilityName(capability)} restriction on the coder`
|
|
80
|
+
)
|
|
81
|
+
})
|
|
82
|
+
}
|