augure 0.5.1 → 0.6.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/dist/bin.js +482 -5
- package/package.json +21 -20
package/dist/bin.js
CHANGED
|
@@ -135,6 +135,11 @@ var AppConfigSchema = z.object({
|
|
|
135
135
|
checkInterval: z.string().min(1).default("24h"),
|
|
136
136
|
notifyChannel: z.string().min(1).default("telegram")
|
|
137
137
|
}).optional()
|
|
138
|
+
}).optional(),
|
|
139
|
+
codeMode: z.object({
|
|
140
|
+
runtime: z.enum(["vm", "docker", "auto"]).default("auto"),
|
|
141
|
+
timeout: z.number().int().positive().default(30),
|
|
142
|
+
memoryLimit: z.number().int().positive().default(128)
|
|
138
143
|
}).optional()
|
|
139
144
|
});
|
|
140
145
|
function interpolateEnvVars(raw) {
|
|
@@ -267,6 +272,403 @@ ${memoryContent}`;
|
|
|
267
272
|
return messages;
|
|
268
273
|
}
|
|
269
274
|
|
|
275
|
+
// ../code-mode/dist/typegen.js
|
|
276
|
+
var JSON_TO_TS = {
|
|
277
|
+
string: "string",
|
|
278
|
+
number: "number",
|
|
279
|
+
integer: "number",
|
|
280
|
+
boolean: "boolean",
|
|
281
|
+
array: "unknown[]",
|
|
282
|
+
object: "Record<string, unknown>"
|
|
283
|
+
};
|
|
284
|
+
function sanitizeName(name) {
|
|
285
|
+
return name.replace(/[-. ]/g, "_");
|
|
286
|
+
}
|
|
287
|
+
function toPascalCase(name) {
|
|
288
|
+
return sanitizeName(name).split("_").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
289
|
+
}
|
|
290
|
+
function mapType(schema) {
|
|
291
|
+
const t = schema.type;
|
|
292
|
+
if (schema.enum) {
|
|
293
|
+
return schema.enum.map((v) => `"${v}"`).join(" | ");
|
|
294
|
+
}
|
|
295
|
+
return JSON_TO_TS[t ?? "string"] ?? "unknown";
|
|
296
|
+
}
|
|
297
|
+
function generateDeclarations(registry) {
|
|
298
|
+
const tools = registry.list();
|
|
299
|
+
const blocks = [];
|
|
300
|
+
const apiEntries = [];
|
|
301
|
+
for (const tool of tools) {
|
|
302
|
+
const safeName = sanitizeName(tool.name);
|
|
303
|
+
const interfaceName = `${toPascalCase(tool.name)}Input`;
|
|
304
|
+
const params = tool.parameters;
|
|
305
|
+
const properties = params.properties ?? {};
|
|
306
|
+
const required = new Set(params.required ?? []);
|
|
307
|
+
const fields = [];
|
|
308
|
+
for (const [key, schema] of Object.entries(properties)) {
|
|
309
|
+
const optional = required.has(key) ? "" : "?";
|
|
310
|
+
const tsType = mapType(schema);
|
|
311
|
+
const desc = schema.description;
|
|
312
|
+
if (desc) {
|
|
313
|
+
fields.push(` /** ${desc} */
|
|
314
|
+
${key}${optional}: ${tsType};`);
|
|
315
|
+
} else {
|
|
316
|
+
fields.push(` ${key}${optional}: ${tsType};`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
blocks.push(`interface ${interfaceName} {
|
|
320
|
+
${fields.join("\n")}
|
|
321
|
+
}`);
|
|
322
|
+
apiEntries.push(` /** ${tool.description} */
|
|
323
|
+
${safeName}: (input: ${interfaceName}) => Promise<{ success: boolean; output: string }>;`);
|
|
324
|
+
}
|
|
325
|
+
const apiBlock = `declare const api: {
|
|
326
|
+
${apiEntries.join("\n")}
|
|
327
|
+
};`;
|
|
328
|
+
return [...blocks, "", apiBlock].join("\n");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ../code-mode/dist/bridge.js
|
|
332
|
+
function createBridgeHandler(registry) {
|
|
333
|
+
return async (toolName, input) => {
|
|
334
|
+
try {
|
|
335
|
+
return await registry.execute(toolName, input);
|
|
336
|
+
} catch (err2) {
|
|
337
|
+
return {
|
|
338
|
+
success: false,
|
|
339
|
+
output: `Bridge error calling ${toolName}: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function generateHarnessCode(userCode) {
|
|
345
|
+
return `
|
|
346
|
+
const __logs = [];
|
|
347
|
+
const __originalLog = console.log;
|
|
348
|
+
const __originalWarn = console.warn;
|
|
349
|
+
const __originalError = console.error;
|
|
350
|
+
console.log = (...args) => __logs.push(args.map(String).join(" "));
|
|
351
|
+
console.warn = (...args) => __logs.push("[warn] " + args.map(String).join(" "));
|
|
352
|
+
console.error = (...args) => __logs.push("[error] " + args.map(String).join(" "));
|
|
353
|
+
|
|
354
|
+
let __toolCalls = 0;
|
|
355
|
+
|
|
356
|
+
const api = new Proxy({}, {
|
|
357
|
+
get: (_target, toolName) => {
|
|
358
|
+
return async (input) => {
|
|
359
|
+
__toolCalls++;
|
|
360
|
+
return await __bridge(String(toolName), input);
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
async function __run() {
|
|
366
|
+
${userCode}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
try {
|
|
370
|
+
const __result = await __run();
|
|
371
|
+
__originalLog(JSON.stringify({
|
|
372
|
+
success: true,
|
|
373
|
+
output: __result,
|
|
374
|
+
logs: __logs,
|
|
375
|
+
toolCalls: __toolCalls,
|
|
376
|
+
}));
|
|
377
|
+
} catch (err) {
|
|
378
|
+
__originalLog(JSON.stringify({
|
|
379
|
+
success: false,
|
|
380
|
+
error: err.message ?? String(err),
|
|
381
|
+
logs: __logs,
|
|
382
|
+
toolCalls: __toolCalls,
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
`;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// ../code-mode/dist/vm-sandbox.js
|
|
389
|
+
import { createContext, runInContext } from "vm";
|
|
390
|
+
import { transform } from "esbuild";
|
|
391
|
+
var VmExecutor = class {
|
|
392
|
+
registry;
|
|
393
|
+
config;
|
|
394
|
+
constructor(registry, config) {
|
|
395
|
+
this.registry = registry;
|
|
396
|
+
this.config = config;
|
|
397
|
+
}
|
|
398
|
+
async execute(code) {
|
|
399
|
+
const start = performance.now();
|
|
400
|
+
try {
|
|
401
|
+
const harnessTs = generateHarnessCode(code);
|
|
402
|
+
const { code: harnessJs } = await transform(harnessTs, {
|
|
403
|
+
loader: "ts",
|
|
404
|
+
target: "es2024"
|
|
405
|
+
});
|
|
406
|
+
const bridgeHandler = createBridgeHandler(this.registry);
|
|
407
|
+
const consoleLogs = [];
|
|
408
|
+
const captureConsole = {
|
|
409
|
+
log: (...args) => consoleLogs.push(args.map(String).join(" ")),
|
|
410
|
+
warn: (...args) => consoleLogs.push("[warn] " + args.map(String).join(" ")),
|
|
411
|
+
error: (...args) => consoleLogs.push("[error] " + args.map(String).join(" "))
|
|
412
|
+
};
|
|
413
|
+
const context = createContext({
|
|
414
|
+
console: captureConsole,
|
|
415
|
+
__bridge: bridgeHandler,
|
|
416
|
+
JSON,
|
|
417
|
+
String,
|
|
418
|
+
Number,
|
|
419
|
+
Boolean,
|
|
420
|
+
Array,
|
|
421
|
+
Object,
|
|
422
|
+
Error,
|
|
423
|
+
Promise,
|
|
424
|
+
Map,
|
|
425
|
+
Set,
|
|
426
|
+
parseInt,
|
|
427
|
+
parseFloat,
|
|
428
|
+
isNaN,
|
|
429
|
+
isFinite,
|
|
430
|
+
setTimeout,
|
|
431
|
+
Date,
|
|
432
|
+
RegExp,
|
|
433
|
+
Math,
|
|
434
|
+
Symbol,
|
|
435
|
+
Uint8Array,
|
|
436
|
+
TextEncoder,
|
|
437
|
+
TextDecoder,
|
|
438
|
+
Buffer,
|
|
439
|
+
URL,
|
|
440
|
+
URLSearchParams
|
|
441
|
+
});
|
|
442
|
+
const wrappedCode = `(async () => { ${harnessJs} })()`;
|
|
443
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
444
|
+
const timer = setTimeout(() => reject(new Error("Timeout: code execution exceeded time limit")), this.config.timeout);
|
|
445
|
+
timer.unref?.();
|
|
446
|
+
});
|
|
447
|
+
const resultPromise = runInContext(wrappedCode, context, {
|
|
448
|
+
timeout: this.config.timeout
|
|
449
|
+
});
|
|
450
|
+
await Promise.race([resultPromise, timeoutPromise]);
|
|
451
|
+
const durationMs = performance.now() - start;
|
|
452
|
+
const lastLine = consoleLogs[consoleLogs.length - 1];
|
|
453
|
+
if (!lastLine) {
|
|
454
|
+
return {
|
|
455
|
+
success: false,
|
|
456
|
+
output: void 0,
|
|
457
|
+
logs: consoleLogs,
|
|
458
|
+
error: "No output produced by code execution",
|
|
459
|
+
durationMs,
|
|
460
|
+
toolCalls: 0
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const parsed = JSON.parse(lastLine);
|
|
464
|
+
return {
|
|
465
|
+
success: parsed.success,
|
|
466
|
+
output: parsed.output,
|
|
467
|
+
logs: parsed.logs,
|
|
468
|
+
error: parsed.error,
|
|
469
|
+
durationMs,
|
|
470
|
+
toolCalls: parsed.toolCalls
|
|
471
|
+
};
|
|
472
|
+
} catch (err2) {
|
|
473
|
+
const durationMs = performance.now() - start;
|
|
474
|
+
return {
|
|
475
|
+
success: false,
|
|
476
|
+
output: void 0,
|
|
477
|
+
logs: [],
|
|
478
|
+
error: err2 instanceof Error ? err2.message : String(err2),
|
|
479
|
+
durationMs,
|
|
480
|
+
toolCalls: 0
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
// ../code-mode/dist/docker-sandbox.js
|
|
487
|
+
var DOCKER_HARNESS = `
|
|
488
|
+
import { readFile } from "node:fs/promises";
|
|
489
|
+
|
|
490
|
+
const __logs = [];
|
|
491
|
+
const __originalLog = console.log;
|
|
492
|
+
console.log = (...args) => __logs.push(args.map(String).join(" "));
|
|
493
|
+
console.warn = (...args) => __logs.push("[warn] " + args.map(String).join(" "));
|
|
494
|
+
console.error = (...args) => __logs.push("[error] " + args.map(String).join(" "));
|
|
495
|
+
|
|
496
|
+
let __toolCalls = 0;
|
|
497
|
+
|
|
498
|
+
const api = new Proxy({}, {
|
|
499
|
+
get: (_target, toolName) => {
|
|
500
|
+
return async () => {
|
|
501
|
+
__toolCalls++;
|
|
502
|
+
return { success: false, output: "Tool calls not yet supported in Docker executor" };
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
const __userCode = await readFile("/workspace/user-code.js", "utf-8");
|
|
508
|
+
const __fn = new Function("api", "__logs",
|
|
509
|
+
"return (async () => { " + __userCode + " })();"
|
|
510
|
+
);
|
|
511
|
+
|
|
512
|
+
try {
|
|
513
|
+
const __result = await __fn(api, __logs);
|
|
514
|
+
__originalLog(JSON.stringify({
|
|
515
|
+
success: true,
|
|
516
|
+
output: __result,
|
|
517
|
+
logs: __logs,
|
|
518
|
+
toolCalls: __toolCalls,
|
|
519
|
+
}));
|
|
520
|
+
} catch (err) {
|
|
521
|
+
__originalLog(JSON.stringify({
|
|
522
|
+
success: false,
|
|
523
|
+
error: err.message ?? String(err),
|
|
524
|
+
logs: __logs,
|
|
525
|
+
toolCalls: __toolCalls,
|
|
526
|
+
}));
|
|
527
|
+
}
|
|
528
|
+
`;
|
|
529
|
+
var DockerExecutor = class {
|
|
530
|
+
config;
|
|
531
|
+
constructor(config) {
|
|
532
|
+
this.config = config;
|
|
533
|
+
}
|
|
534
|
+
async execute(code) {
|
|
535
|
+
const start = Date.now();
|
|
536
|
+
let container;
|
|
537
|
+
try {
|
|
538
|
+
container = await this.config.pool.acquire({
|
|
539
|
+
trust: "sandboxed",
|
|
540
|
+
timeout: this.config.timeout,
|
|
541
|
+
memory: this.config.memoryLimit,
|
|
542
|
+
cpu: this.config.cpuLimit
|
|
543
|
+
});
|
|
544
|
+
} catch (err2) {
|
|
545
|
+
return {
|
|
546
|
+
success: false,
|
|
547
|
+
output: void 0,
|
|
548
|
+
logs: [],
|
|
549
|
+
toolCalls: 0,
|
|
550
|
+
error: `Failed to acquire container: ${err2 instanceof Error ? err2.message : String(err2)}`,
|
|
551
|
+
durationMs: Date.now() - start
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
try {
|
|
555
|
+
await container.exec("mkdir -p /workspace");
|
|
556
|
+
const codeB64 = Buffer.from(code).toString("base64");
|
|
557
|
+
await container.exec(`sh -c 'echo "${codeB64}" | base64 -d > /workspace/user-code.js'`);
|
|
558
|
+
const harnessB64 = Buffer.from(DOCKER_HARNESS).toString("base64");
|
|
559
|
+
await container.exec(`sh -c 'echo "${harnessB64}" | base64 -d > /workspace/harness.ts'`);
|
|
560
|
+
const execResult = await container.exec("npx tsx /workspace/harness.ts", {
|
|
561
|
+
timeout: this.config.timeout,
|
|
562
|
+
cwd: "/workspace"
|
|
563
|
+
});
|
|
564
|
+
if (execResult.exitCode === 0 && execResult.stdout.trim()) {
|
|
565
|
+
try {
|
|
566
|
+
const lastLine = execResult.stdout.trim().split("\n").pop();
|
|
567
|
+
const parsed = JSON.parse(lastLine);
|
|
568
|
+
return {
|
|
569
|
+
success: parsed.success,
|
|
570
|
+
output: parsed.output,
|
|
571
|
+
logs: parsed.logs ?? [],
|
|
572
|
+
error: parsed.error,
|
|
573
|
+
durationMs: Date.now() - start,
|
|
574
|
+
toolCalls: parsed.toolCalls ?? 0
|
|
575
|
+
};
|
|
576
|
+
} catch {
|
|
577
|
+
return {
|
|
578
|
+
success: true,
|
|
579
|
+
output: execResult.stdout.trim(),
|
|
580
|
+
logs: [],
|
|
581
|
+
durationMs: Date.now() - start,
|
|
582
|
+
toolCalls: 0
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
success: false,
|
|
588
|
+
output: void 0,
|
|
589
|
+
logs: [],
|
|
590
|
+
toolCalls: 0,
|
|
591
|
+
error: execResult.stderr || execResult.stdout || "Unknown error",
|
|
592
|
+
durationMs: Date.now() - start
|
|
593
|
+
};
|
|
594
|
+
} catch (err2) {
|
|
595
|
+
return {
|
|
596
|
+
success: false,
|
|
597
|
+
output: void 0,
|
|
598
|
+
logs: [],
|
|
599
|
+
toolCalls: 0,
|
|
600
|
+
error: err2 instanceof Error ? err2.message : String(err2),
|
|
601
|
+
durationMs: Date.now() - start
|
|
602
|
+
};
|
|
603
|
+
} finally {
|
|
604
|
+
await this.config.pool.release(container);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
// ../code-mode/dist/tool.js
|
|
610
|
+
function createCodeModeTool(registry, executor) {
|
|
611
|
+
const declarations = generateDeclarations(registry);
|
|
612
|
+
return {
|
|
613
|
+
name: "execute_code",
|
|
614
|
+
description: `Execute TypeScript code with access to the agent's APIs. Write the body of an async function.
|
|
615
|
+
|
|
616
|
+
Available APIs:
|
|
617
|
+
|
|
618
|
+
\`\`\`typescript
|
|
619
|
+
${declarations}
|
|
620
|
+
\`\`\`
|
|
621
|
+
|
|
622
|
+
Each API call returns { success: boolean, output: string }.
|
|
623
|
+
Use console.log() for intermediate output. Return your final result.`,
|
|
624
|
+
parameters: {
|
|
625
|
+
type: "object",
|
|
626
|
+
properties: {
|
|
627
|
+
code: {
|
|
628
|
+
type: "string",
|
|
629
|
+
description: "The body of an async TypeScript function. Use the 'api' object to call tools."
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
required: ["code"]
|
|
633
|
+
},
|
|
634
|
+
execute: async (params) => {
|
|
635
|
+
const { code } = params;
|
|
636
|
+
const result = await executor.execute(code);
|
|
637
|
+
if (result.success) {
|
|
638
|
+
const parts = [];
|
|
639
|
+
if (result.logs.length > 0) {
|
|
640
|
+
parts.push(`[logs]
|
|
641
|
+
${result.logs.join("\n")}`);
|
|
642
|
+
}
|
|
643
|
+
parts.push(typeof result.output === "string" ? result.output : JSON.stringify(result.output));
|
|
644
|
+
return { success: true, output: parts.join("\n\n") };
|
|
645
|
+
}
|
|
646
|
+
return {
|
|
647
|
+
success: false,
|
|
648
|
+
output: result.error ?? "Code execution failed"
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// ../code-mode/dist/auto-executor.js
|
|
655
|
+
var AutoExecutor = class {
|
|
656
|
+
primary;
|
|
657
|
+
fallback;
|
|
658
|
+
constructor(primary, fallback) {
|
|
659
|
+
this.primary = primary;
|
|
660
|
+
this.fallback = fallback;
|
|
661
|
+
}
|
|
662
|
+
async execute(code) {
|
|
663
|
+
try {
|
|
664
|
+
const result = await this.primary.execute(code);
|
|
665
|
+
return result;
|
|
666
|
+
} catch {
|
|
667
|
+
return this.fallback.execute(code);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
|
|
270
672
|
// ../core/dist/audit.js
|
|
271
673
|
import { appendFile, mkdir } from "fs/promises";
|
|
272
674
|
import { join } from "path";
|
|
@@ -349,6 +751,19 @@ var Agent = class {
|
|
|
349
751
|
const maxLoops = this.config.maxToolLoops ?? 10;
|
|
350
752
|
let loopCount = 0;
|
|
351
753
|
const toolSchemas = this.config.tools.toFunctionSchemas();
|
|
754
|
+
let effectiveSchemas = toolSchemas;
|
|
755
|
+
let codeModeTool;
|
|
756
|
+
if (this.config.codeModeExecutor) {
|
|
757
|
+
codeModeTool = createCodeModeTool(this.config.tools, this.config.codeModeExecutor);
|
|
758
|
+
effectiveSchemas = [{
|
|
759
|
+
type: "function",
|
|
760
|
+
function: {
|
|
761
|
+
name: codeModeTool.name,
|
|
762
|
+
description: codeModeTool.description,
|
|
763
|
+
parameters: codeModeTool.parameters
|
|
764
|
+
}
|
|
765
|
+
}];
|
|
766
|
+
}
|
|
352
767
|
while (loopCount < maxLoops) {
|
|
353
768
|
const messages = assembleContext({
|
|
354
769
|
systemPrompt: this.config.systemPrompt,
|
|
@@ -357,7 +772,7 @@ var Agent = class {
|
|
|
357
772
|
persona: this.config.persona
|
|
358
773
|
});
|
|
359
774
|
this.log.debug(`LLM call #${loopCount + 1} (${messages.length} messages)`);
|
|
360
|
-
const response = await this.config.llm.chat(messages,
|
|
775
|
+
const response = await this.config.llm.chat(messages, effectiveSchemas);
|
|
361
776
|
if (response.toolCalls.length === 0) {
|
|
362
777
|
history.push({
|
|
363
778
|
role: "assistant",
|
|
@@ -393,7 +808,12 @@ var Agent = class {
|
|
|
393
808
|
for (const toolCall of response.toolCalls) {
|
|
394
809
|
const toolStart = Date.now();
|
|
395
810
|
this.log.debug(`Tool: ${toolCall.name}`);
|
|
396
|
-
|
|
811
|
+
let result;
|
|
812
|
+
if (codeModeTool && toolCall.name === "execute_code") {
|
|
813
|
+
result = await codeModeTool.execute(toolCall.arguments, {});
|
|
814
|
+
} else {
|
|
815
|
+
result = await this.config.tools.execute(toolCall.name, toolCall.arguments);
|
|
816
|
+
}
|
|
397
817
|
this.log.debug(`Tool ${toolCall.name}: ${result.success ? "ok" : "fail"} (${Date.now() - toolStart}ms)`);
|
|
398
818
|
history.push({
|
|
399
819
|
role: "tool",
|
|
@@ -2303,6 +2723,7 @@ var CronScheduler = class {
|
|
|
2303
2723
|
timers = /* @__PURE__ */ new Map();
|
|
2304
2724
|
handlers = [];
|
|
2305
2725
|
persistChain = Promise.resolve();
|
|
2726
|
+
running = false;
|
|
2306
2727
|
constructor(store) {
|
|
2307
2728
|
this.store = store;
|
|
2308
2729
|
}
|
|
@@ -2320,12 +2741,21 @@ var CronScheduler = class {
|
|
|
2320
2741
|
throw new Error(`Invalid runAt date: ${job.runAt}`);
|
|
2321
2742
|
}
|
|
2322
2743
|
this.jobs.set(job.id, job);
|
|
2744
|
+
console.log(`[scheduler] Added job ${job.id} (${job.cron ? `cron: ${job.cron}` : `runAt: ${job.runAt}`})`);
|
|
2323
2745
|
if (job.enabled && job.cron) {
|
|
2324
2746
|
const task = createTask(job.cron, () => {
|
|
2747
|
+
console.log(`[scheduler] Cron fired for job ${job.id}`);
|
|
2325
2748
|
void this.executeHandlers(job);
|
|
2326
2749
|
});
|
|
2750
|
+
if (this.running) {
|
|
2751
|
+
task.start();
|
|
2752
|
+
console.log(`[scheduler] Started cron task for ${job.id} immediately (scheduler already running)`);
|
|
2753
|
+
}
|
|
2327
2754
|
this.tasks.set(job.id, task);
|
|
2328
2755
|
}
|
|
2756
|
+
if (this.running && job.enabled && job.runAt && !job.cron) {
|
|
2757
|
+
this.scheduleOneShot(job);
|
|
2758
|
+
}
|
|
2329
2759
|
this.persist();
|
|
2330
2760
|
}
|
|
2331
2761
|
removeJob(id) {
|
|
@@ -2340,6 +2770,7 @@ var CronScheduler = class {
|
|
|
2340
2770
|
this.timers.delete(id);
|
|
2341
2771
|
}
|
|
2342
2772
|
this.jobs.delete(id);
|
|
2773
|
+
console.log(`[scheduler] Removed job ${id}`);
|
|
2343
2774
|
this.persist();
|
|
2344
2775
|
}
|
|
2345
2776
|
listJobs() {
|
|
@@ -2356,16 +2787,21 @@ var CronScheduler = class {
|
|
|
2356
2787
|
if (!this.store)
|
|
2357
2788
|
return;
|
|
2358
2789
|
const jobs = await this.store.load();
|
|
2790
|
+
console.log(`[scheduler] Loading ${jobs.length} persisted jobs`);
|
|
2359
2791
|
for (const job of jobs) {
|
|
2360
2792
|
if (job.runAt && Date.parse(job.runAt) <= Date.now()) {
|
|
2793
|
+
console.log(`[scheduler] Skipping expired one-shot job ${job.id} (runAt: ${job.runAt})`);
|
|
2361
2794
|
continue;
|
|
2362
2795
|
}
|
|
2363
2796
|
this.addJob(job);
|
|
2364
2797
|
}
|
|
2365
2798
|
}
|
|
2366
2799
|
start() {
|
|
2367
|
-
|
|
2800
|
+
this.running = true;
|
|
2801
|
+
console.log(`[scheduler] Starting with ${this.tasks.size} cron tasks and ${this.handlers.length} handlers`);
|
|
2802
|
+
for (const [id, task] of this.tasks) {
|
|
2368
2803
|
task.start();
|
|
2804
|
+
console.log(`[scheduler] Started cron task: ${id}`);
|
|
2369
2805
|
}
|
|
2370
2806
|
for (const job of this.jobs.values()) {
|
|
2371
2807
|
if (job.enabled && job.runAt && !job.cron) {
|
|
@@ -2374,6 +2810,7 @@ var CronScheduler = class {
|
|
|
2374
2810
|
}
|
|
2375
2811
|
}
|
|
2376
2812
|
stop() {
|
|
2813
|
+
this.running = false;
|
|
2377
2814
|
for (const task of this.tasks.values()) {
|
|
2378
2815
|
task.stop();
|
|
2379
2816
|
}
|
|
@@ -2384,9 +2821,13 @@ var CronScheduler = class {
|
|
|
2384
2821
|
}
|
|
2385
2822
|
scheduleOneShot(job) {
|
|
2386
2823
|
const delayMs = Date.parse(job.runAt) - Date.now();
|
|
2387
|
-
if (delayMs <= 0)
|
|
2824
|
+
if (delayMs <= 0) {
|
|
2825
|
+
console.log(`[scheduler] One-shot job ${job.id} already expired (delay: ${delayMs}ms), skipping`);
|
|
2388
2826
|
return;
|
|
2827
|
+
}
|
|
2828
|
+
console.log(`[scheduler] Scheduled one-shot job ${job.id} in ${Math.round(delayMs / 1e3)}s (${job.runAt})`);
|
|
2389
2829
|
const timer = setTimeout(() => {
|
|
2830
|
+
console.log(`[scheduler] One-shot job ${job.id} firing now`);
|
|
2390
2831
|
this.timers.delete(job.id);
|
|
2391
2832
|
void this.executeHandlers(job).then(() => {
|
|
2392
2833
|
this.removeJob(job.id);
|
|
@@ -2401,6 +2842,7 @@ var CronScheduler = class {
|
|
|
2401
2842
|
this.persistChain = this.persistChain.then(() => this.store.save(jobs));
|
|
2402
2843
|
}
|
|
2403
2844
|
async executeHandlers(job) {
|
|
2845
|
+
console.log(`[scheduler] Executing ${this.handlers.length} handlers for job ${job.id}`);
|
|
2404
2846
|
for (const handler of this.handlers) {
|
|
2405
2847
|
await handler(job);
|
|
2406
2848
|
}
|
|
@@ -3977,6 +4419,40 @@ async function startAgent(configPath, opts) {
|
|
|
3977
4419
|
log.info(`Skills initialized: ${skillsPath}`);
|
|
3978
4420
|
}
|
|
3979
4421
|
tools.setContext({ config, memory, scheduler, pool });
|
|
4422
|
+
let codeModeExecutor;
|
|
4423
|
+
if (config.codeMode) {
|
|
4424
|
+
const cmConfig = config.codeMode;
|
|
4425
|
+
if (cmConfig.runtime === "vm") {
|
|
4426
|
+
codeModeExecutor = new VmExecutor(tools, {
|
|
4427
|
+
timeout: cmConfig.timeout * 1e3,
|
|
4428
|
+
// VmExecutor expects ms
|
|
4429
|
+
memoryLimit: cmConfig.memoryLimit
|
|
4430
|
+
});
|
|
4431
|
+
} else if (cmConfig.runtime === "docker") {
|
|
4432
|
+
codeModeExecutor = new DockerExecutor({
|
|
4433
|
+
registry: tools,
|
|
4434
|
+
pool,
|
|
4435
|
+
timeout: cmConfig.timeout,
|
|
4436
|
+
// DockerExecutor expects seconds
|
|
4437
|
+
memoryLimit: config.sandbox.defaults.memoryLimit,
|
|
4438
|
+
cpuLimit: config.sandbox.defaults.cpuLimit
|
|
4439
|
+
});
|
|
4440
|
+
} else {
|
|
4441
|
+
const vmExec = new VmExecutor(tools, {
|
|
4442
|
+
timeout: cmConfig.timeout * 1e3,
|
|
4443
|
+
memoryLimit: cmConfig.memoryLimit
|
|
4444
|
+
});
|
|
4445
|
+
const dockerExec = new DockerExecutor({
|
|
4446
|
+
registry: tools,
|
|
4447
|
+
pool,
|
|
4448
|
+
timeout: cmConfig.timeout,
|
|
4449
|
+
memoryLimit: config.sandbox.defaults.memoryLimit,
|
|
4450
|
+
cpuLimit: config.sandbox.defaults.cpuLimit
|
|
4451
|
+
});
|
|
4452
|
+
codeModeExecutor = new AutoExecutor(vmExec, dockerExec);
|
|
4453
|
+
}
|
|
4454
|
+
log.info(`Code Mode enabled: runtime=${cmConfig.runtime}, timeout=${cmConfig.timeout}s`);
|
|
4455
|
+
}
|
|
3980
4456
|
const auditConfig = config.audit ?? { path: "./logs", enabled: true };
|
|
3981
4457
|
const auditPath = resolve(configPath, "..", auditConfig.path);
|
|
3982
4458
|
const audit = auditConfig.enabled ? new FileAuditLogger(auditPath, log.child("audit")) : new NullAuditLogger();
|
|
@@ -4020,7 +4496,8 @@ async function startAgent(configPath, opts) {
|
|
|
4020
4496
|
audit,
|
|
4021
4497
|
guard,
|
|
4022
4498
|
modelName: config.llm.default.model,
|
|
4023
|
-
logger: log.child("agent")
|
|
4499
|
+
logger: log.child("agent"),
|
|
4500
|
+
codeModeExecutor
|
|
4024
4501
|
});
|
|
4025
4502
|
if (config.channels.telegram?.enabled) {
|
|
4026
4503
|
const telegramLog = log.child("telegram");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "augure",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Augure — your proactive AI agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,18 +12,10 @@
|
|
|
12
12
|
"engines": {
|
|
13
13
|
"node": ">=22.0.0"
|
|
14
14
|
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsup",
|
|
17
|
-
"dev": "tsup --watch",
|
|
18
|
-
"test": "vitest run",
|
|
19
|
-
"test:unit": "vitest run",
|
|
20
|
-
"typecheck": "tsc --noEmit",
|
|
21
|
-
"lint": "eslint src/",
|
|
22
|
-
"clean": "rm -rf dist .turbo"
|
|
23
|
-
},
|
|
24
15
|
"dependencies": {
|
|
25
16
|
"citty": "^0.2.1",
|
|
26
17
|
"dockerode": "^4.0.9",
|
|
18
|
+
"esbuild": "^0.25.0",
|
|
27
19
|
"grammy": "^1.40.0",
|
|
28
20
|
"imapflow": "^1.2.10",
|
|
29
21
|
"nodemailer": "^6.10.1",
|
|
@@ -33,17 +25,17 @@
|
|
|
33
25
|
"zod": "^4.3.6"
|
|
34
26
|
},
|
|
35
27
|
"devDependencies": {
|
|
36
|
-
"@augure/channels": "workspace:*",
|
|
37
|
-
"@augure/core": "workspace:*",
|
|
38
|
-
"@augure/memory": "workspace:*",
|
|
39
|
-
"@augure/sandbox": "workspace:*",
|
|
40
|
-
"@augure/scheduler": "workspace:*",
|
|
41
|
-
"@augure/skills": "workspace:*",
|
|
42
|
-
"@augure/tools": "workspace:*",
|
|
43
|
-
"@augure/types": "workspace:*",
|
|
44
28
|
"@types/dockerode": "^4.0.1",
|
|
45
29
|
"@types/node-cron": "^3.0.11",
|
|
46
|
-
"tsup": "^8.5.1"
|
|
30
|
+
"tsup": "^8.5.1",
|
|
31
|
+
"@augure/channels": "0.1.3",
|
|
32
|
+
"@augure/core": "0.4.0",
|
|
33
|
+
"@augure/sandbox": "0.1.2",
|
|
34
|
+
"@augure/scheduler": "0.1.2",
|
|
35
|
+
"@augure/memory": "0.0.5",
|
|
36
|
+
"@augure/types": "0.3.0",
|
|
37
|
+
"@augure/skills": "0.1.3",
|
|
38
|
+
"@augure/tools": "0.1.1"
|
|
47
39
|
},
|
|
48
40
|
"keywords": [
|
|
49
41
|
"ai",
|
|
@@ -61,5 +53,14 @@
|
|
|
61
53
|
},
|
|
62
54
|
"publishConfig": {
|
|
63
55
|
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"build": "tsup",
|
|
59
|
+
"dev": "tsup --watch",
|
|
60
|
+
"test": "vitest run",
|
|
61
|
+
"test:unit": "vitest run",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"lint": "eslint src/",
|
|
64
|
+
"clean": "rm -rf dist .turbo"
|
|
64
65
|
}
|
|
65
|
-
}
|
|
66
|
+
}
|