@ai-hero/sandcastle 0.9.0 → 0.10.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/README.md +10 -4
- package/dist/index.d.ts +33 -4
- package/dist/index.js +54 -4
- package/dist/index.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -218,14 +218,20 @@ const result = await run({
|
|
|
218
218
|
type: "file",
|
|
219
219
|
path: ".sandcastle/logs/my-run.log",
|
|
220
220
|
// Optional: forward the agent's output stream to your own observability system.
|
|
221
|
-
// Fires for each text chunk
|
|
222
|
-
// by the callback are swallowed so a broken
|
|
221
|
+
// Fires for each text chunk, tool call, and raw stdout line the agent
|
|
222
|
+
// produces. Errors thrown by the callback are swallowed so a broken
|
|
223
|
+
// forwarder cannot kill the run.
|
|
223
224
|
onAgentStreamEvent: (event) => {
|
|
224
|
-
// event is { type: "text" | "toolCall", iteration, timestamp, ... }
|
|
225
|
+
// event is { type: "text" | "toolCall" | "raw", iteration, timestamp, ... }
|
|
225
226
|
myLogger.info(event);
|
|
226
227
|
},
|
|
228
|
+
// Optional: append every raw stdout line the agent emits to the same
|
|
229
|
+
// log file, interleaved with the human-readable output. Includes lines
|
|
230
|
+
// the provider's stream parser would otherwise drop. Intended for
|
|
231
|
+
// debugging stuck or unexpected agent behaviour.
|
|
232
|
+
verbose: true,
|
|
227
233
|
},
|
|
228
|
-
// logging: { type: "stdout" }, // OR
|
|
234
|
+
// logging: { type: "stdout", verbose: true }, // OR terminal mode (verbose: raw lines to stdout)
|
|
229
235
|
|
|
230
236
|
// String (or array of strings) the agent emits to end the iteration loop early.
|
|
231
237
|
// Default: "<promise>COMPLETE</promise>"
|
package/dist/index.d.ts
CHANGED
|
@@ -246,6 +246,12 @@ declare const claudeCode: (model: string, options?: ClaudeCodeOptions) => AgentP
|
|
|
246
246
|
*
|
|
247
247
|
* Emitted only in log-to-file mode when an `onAgentStreamEvent` callback is
|
|
248
248
|
* provided via `logging`. See `run()`.
|
|
249
|
+
*
|
|
250
|
+
* The `"raw"` variant carries every stdout line the agent emits, verbatim and
|
|
251
|
+
* before parsing — including lines that the provider's stream parser would
|
|
252
|
+
* otherwise drop (e.g. tool-use blocks for unrecognised tools). Intended for
|
|
253
|
+
* debugging when the typed `"text"` / `"toolCall"` events don't surface
|
|
254
|
+
* enough detail.
|
|
249
255
|
*/
|
|
250
256
|
type AgentStreamEvent = {
|
|
251
257
|
readonly type: "text";
|
|
@@ -258,6 +264,11 @@ type AgentStreamEvent = {
|
|
|
258
264
|
readonly formattedArgs: string;
|
|
259
265
|
readonly iteration: number;
|
|
260
266
|
readonly timestamp: Date;
|
|
267
|
+
} | {
|
|
268
|
+
readonly type: "raw";
|
|
269
|
+
readonly line: string;
|
|
270
|
+
readonly iteration: number;
|
|
271
|
+
readonly timestamp: Date;
|
|
261
272
|
};
|
|
262
273
|
|
|
263
274
|
type SandboxHooks = {
|
|
@@ -414,16 +425,34 @@ type LoggingOption =
|
|
|
414
425
|
readonly type: "file";
|
|
415
426
|
readonly path: string;
|
|
416
427
|
/**
|
|
417
|
-
* Optional callback invoked for each agent stream event (text chunk
|
|
418
|
-
* tool call) in addition to being written to the
|
|
419
|
-
* forwarding the agent's output stream to
|
|
420
|
-
* systems. Errors thrown by the callback are
|
|
428
|
+
* Optional callback invoked for each agent stream event (text chunk,
|
|
429
|
+
* tool call, or raw stdout line) in addition to being written to the
|
|
430
|
+
* log file. Intended for forwarding the agent's output stream to
|
|
431
|
+
* external observability systems. Errors thrown by the callback are
|
|
432
|
+
* swallowed.
|
|
421
433
|
*/
|
|
422
434
|
readonly onAgentStreamEvent?: (event: AgentStreamEvent) => void;
|
|
435
|
+
/**
|
|
436
|
+
* When `true`, every raw stdout line the agent emits is appended
|
|
437
|
+
* verbatim to the same log file at `path`, in real time. Includes
|
|
438
|
+
* lines the provider's stream parser would otherwise drop (e.g.
|
|
439
|
+
* tool-use blocks for unrecognised tools). Intended for debugging
|
|
440
|
+
* stuck or unexpected agent behavior — note that the raw JSON is
|
|
441
|
+
* interleaved with the human-readable log output. Default: `false`.
|
|
442
|
+
*/
|
|
443
|
+
readonly verbose?: boolean;
|
|
423
444
|
}
|
|
424
445
|
/** Render progress and agent output as an interactive UI in the terminal (terminal mode). */
|
|
425
446
|
| {
|
|
426
447
|
readonly type: "stdout";
|
|
448
|
+
/**
|
|
449
|
+
* When `true`, every raw stdout line the agent emits is written
|
|
450
|
+
* verbatim to `process.stdout`, in real time. Includes lines the
|
|
451
|
+
* provider's stream parser would otherwise drop. Intended for
|
|
452
|
+
* debugging stuck or unexpected agent behavior. Note: the raw output
|
|
453
|
+
* is interleaved with the interactive terminal UI. Default: `false`.
|
|
454
|
+
*/
|
|
455
|
+
readonly verbose?: boolean;
|
|
427
456
|
};
|
|
428
457
|
/** Override default timeouts for built-in lifecycle steps. Unset keys keep their defaults. */
|
|
429
458
|
interface Timeouts {
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Context_exports, CwdError, Effect_exports, resolveCwd, getCurrentBranch
|
|
|
4
4
|
export { createBindMountSandboxProvider, createIsolatedSandboxProvider } from './chunk-BIWNFKGV.js';
|
|
5
5
|
import { noSandbox } from './chunk-72UVAC7B.js';
|
|
6
6
|
import './chunk-NGBM7T3E.js';
|
|
7
|
+
import { mkdirSync, appendFileSync } from 'fs';
|
|
7
8
|
import path, { join, posix, dirname, relative } from 'path';
|
|
8
9
|
import { styleText } from 'util';
|
|
9
10
|
import * as clack from '@clack/prompts';
|
|
@@ -177,7 +178,7 @@ var TextDeltaBuffer = class {
|
|
|
177
178
|
|
|
178
179
|
// src/Orchestrator.ts
|
|
179
180
|
var IDLE_WARNING_INTERVAL_MS = 6e4;
|
|
180
|
-
var invokeAgent = (sandbox, sandboxRepoDir, prompt, provider, idleTimeoutMs, completionTimeoutMs, completionSignals, onText, onToolCall, onIdleWarning, onCompletionTimeout, idleWarningIntervalMs = IDLE_WARNING_INTERVAL_MS, resumeSession, forkSession, signal) => Effect_exports.gen(function* () {
|
|
181
|
+
var invokeAgent = (sandbox, sandboxRepoDir, prompt, provider, idleTimeoutMs, completionTimeoutMs, completionSignals, onText, onToolCall, onRawLine, onIdleWarning, onCompletionTimeout, idleWarningIntervalMs = IDLE_WARNING_INTERVAL_MS, resumeSession, forkSession, signal) => Effect_exports.gen(function* () {
|
|
181
182
|
let resultText = "";
|
|
182
183
|
let sessionId;
|
|
183
184
|
let usage;
|
|
@@ -256,6 +257,10 @@ var invokeAgent = (sandbox, sandboxRepoDir, prompt, provider, idleTimeoutMs, com
|
|
|
256
257
|
});
|
|
257
258
|
const execResult = yield* sandbox.exec(printCmd.command, {
|
|
258
259
|
onLine: (line) => {
|
|
260
|
+
try {
|
|
261
|
+
onRawLine(line);
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
259
264
|
for (const parsed of provider.parseStreamLine(line)) {
|
|
260
265
|
if (parsed.type === "text") {
|
|
261
266
|
onText(parsed.text);
|
|
@@ -421,6 +426,16 @@ var orchestrate = (options) => {
|
|
|
421
426
|
})
|
|
422
427
|
);
|
|
423
428
|
};
|
|
429
|
+
const onRawLine = (line) => {
|
|
430
|
+
Effect_exports.runPromise(
|
|
431
|
+
streamEmitter.emit({
|
|
432
|
+
type: "raw",
|
|
433
|
+
line,
|
|
434
|
+
iteration: i,
|
|
435
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
436
|
+
})
|
|
437
|
+
);
|
|
438
|
+
};
|
|
424
439
|
const onIdleWarning = (minutes) => {
|
|
425
440
|
const msg = minutes === 1 ? "Agent idle for 1 minute" : `Agent idle for ${minutes} minutes`;
|
|
426
441
|
Effect_exports.runPromise(display.status(label(msg), "warn"));
|
|
@@ -449,6 +464,7 @@ var orchestrate = (options) => {
|
|
|
449
464
|
completionSignals,
|
|
450
465
|
onText,
|
|
451
466
|
onToolCall,
|
|
467
|
+
onRawLine,
|
|
452
468
|
onIdleWarning,
|
|
453
469
|
onCompletionTimeout,
|
|
454
470
|
options._idleWarningIntervalMs,
|
|
@@ -896,6 +912,40 @@ var formatContextWindowSize = (usage) => {
|
|
|
896
912
|
return `${Math.ceil(total / 1e3)}k`;
|
|
897
913
|
};
|
|
898
914
|
var buildContextWindowLines = (iterations) => iterations.filter((it) => it.usage !== void 0).map((it) => `Context window: ${formatContextWindowSize(it.usage)}`);
|
|
915
|
+
var buildAgentStreamHandler = (logging) => {
|
|
916
|
+
const userHandler = logging.type === "file" ? logging.onAgentStreamEvent : void 0;
|
|
917
|
+
const verboseSink = logging.verbose ? buildVerboseRawLineSink(logging) : void 0;
|
|
918
|
+
if (!userHandler && !verboseSink) return void 0;
|
|
919
|
+
return (event) => {
|
|
920
|
+
if (userHandler) {
|
|
921
|
+
try {
|
|
922
|
+
userHandler(event);
|
|
923
|
+
} catch {
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
if (verboseSink && event.type === "raw") {
|
|
927
|
+
verboseSink(event.line);
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
};
|
|
931
|
+
var buildVerboseRawLineSink = (logging) => {
|
|
932
|
+
if (logging.type === "file") {
|
|
933
|
+
const logPath = logging.path;
|
|
934
|
+
try {
|
|
935
|
+
mkdirSync(path.dirname(logPath), { recursive: true });
|
|
936
|
+
} catch {
|
|
937
|
+
}
|
|
938
|
+
return (line) => {
|
|
939
|
+
try {
|
|
940
|
+
appendFileSync(logPath, line + "\n");
|
|
941
|
+
} catch {
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
return (line) => {
|
|
946
|
+
process.stdout.write(line + "\n");
|
|
947
|
+
};
|
|
948
|
+
};
|
|
899
949
|
async function run(options) {
|
|
900
950
|
options.signal?.throwIfAborted();
|
|
901
951
|
const {
|
|
@@ -1013,7 +1063,7 @@ async function run(options) {
|
|
|
1013
1063
|
)
|
|
1014
1064
|
);
|
|
1015
1065
|
const streamEmitterLayer = agentStreamEmitterLayer(
|
|
1016
|
-
resolvedLogging
|
|
1066
|
+
buildAgentStreamHandler(resolvedLogging)
|
|
1017
1067
|
);
|
|
1018
1068
|
const runLayer = Layer_exports.mergeAll(
|
|
1019
1069
|
factoryLayer,
|
|
@@ -1525,7 +1575,7 @@ var buildSandboxHandle = (ctx, close) => {
|
|
|
1525
1575
|
)
|
|
1526
1576
|
});
|
|
1527
1577
|
const streamEmitterLayer = agentStreamEmitterLayer(
|
|
1528
|
-
resolvedLogging
|
|
1578
|
+
buildAgentStreamHandler(resolvedLogging)
|
|
1529
1579
|
);
|
|
1530
1580
|
const runLayer = Layer_exports.mergeAll(
|
|
1531
1581
|
reuseFactoryLayer,
|
|
@@ -2304,7 +2354,7 @@ var createWorktree = async (options) => {
|
|
|
2304
2354
|
)
|
|
2305
2355
|
});
|
|
2306
2356
|
const streamEmitterLayer = agentStreamEmitterLayer(
|
|
2307
|
-
resolvedLogging
|
|
2357
|
+
buildAgentStreamHandler(resolvedLogging)
|
|
2308
2358
|
);
|
|
2309
2359
|
const runLayer = Layer_exports.mergeAll(
|
|
2310
2360
|
reuseFactoryLayer,
|