agency-lang 0.1.0 → 0.1.1
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/lib/backends/agencyGenerator.d.ts +1 -2
- package/dist/lib/backends/agencyGenerator.js +4 -13
- package/dist/lib/backends/typescriptBuilder.js +8 -1
- package/dist/lib/cli/commands.js +1 -1
- package/dist/lib/cli/debug.js +1 -1
- package/dist/lib/cli/schedule/backends/launchd.js +2 -0
- package/dist/lib/cli/schedule/test.d.ts +14 -0
- package/dist/lib/cli/schedule/test.js +29 -0
- package/dist/lib/cli/serve.d.ts +8 -0
- package/dist/lib/cli/serve.js +85 -0
- package/dist/lib/config.d.ts +11 -3
- package/dist/lib/config.js +1 -0
- package/dist/lib/debugger/overlays.d.ts +1 -1
- package/dist/lib/debugger/overlays.js +1 -1
- package/dist/lib/debugger/testSession.d.ts +1 -1
- package/dist/lib/debugger/testSession.js +1 -1
- package/dist/lib/debugger/ui.d.ts +1 -1
- package/dist/lib/debugger/ui.js +1 -1
- package/dist/lib/logger.d.ts +8 -0
- package/dist/lib/logger.js +21 -0
- package/dist/lib/logger.test.d.ts +1 -0
- package/dist/lib/logger.test.js +44 -0
- package/dist/lib/lsp/semantics.js +2 -0
- package/dist/lib/parser.js +2 -2
- package/dist/lib/parsers/assignment.test.js +9 -9
- package/dist/lib/parsers/exportConst.test.d.ts +1 -0
- package/dist/lib/parsers/exportConst.test.js +41 -0
- package/dist/lib/parsers/exportNode.test.d.ts +1 -0
- package/dist/lib/parsers/exportNode.test.js +37 -0
- package/dist/lib/parsers/parsers.d.ts +1 -1
- package/dist/lib/parsers/parsers.js +81 -21
- package/dist/lib/runtime/agencyFunction.d.ts +4 -0
- package/dist/lib/runtime/agencyFunction.js +8 -0
- package/dist/lib/serve/constants.d.ts +1 -0
- package/dist/lib/serve/constants.js +1 -0
- package/dist/lib/serve/discovery.d.ts +9 -0
- package/dist/lib/serve/discovery.js +35 -0
- package/dist/lib/serve/discovery.test.d.ts +1 -0
- package/dist/lib/serve/discovery.test.js +105 -0
- package/dist/lib/serve/http/adapter.d.ts +18 -0
- package/dist/lib/serve/http/adapter.js +150 -0
- package/dist/lib/serve/http/adapter.test.d.ts +1 -0
- package/dist/lib/serve/http/adapter.test.js +121 -0
- package/dist/lib/serve/http/auth.d.ts +1 -0
- package/dist/lib/serve/http/auth.js +10 -0
- package/dist/lib/serve/http/auth.test.d.ts +1 -0
- package/dist/lib/serve/http/auth.test.js +22 -0
- package/dist/lib/serve/mcp/adapter.d.ts +18 -0
- package/dist/lib/serve/mcp/adapter.js +111 -0
- package/dist/lib/serve/mcp/adapter.test.d.ts +1 -0
- package/dist/lib/serve/mcp/adapter.test.js +107 -0
- package/dist/lib/serve/types.d.ts +16 -0
- package/dist/lib/serve/types.js +1 -0
- package/dist/lib/serve/util.d.ts +6 -0
- package/dist/lib/serve/util.js +36 -0
- package/dist/lib/symbolTable.d.ts +8 -1
- package/dist/lib/symbolTable.js +11 -0
- package/dist/lib/templates/backends/typescriptGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.js +1 -1
- package/dist/lib/templates/cli/schedule/plist.d.ts +3 -1
- package/dist/lib/templates/cli/schedule/plist.js +7 -0
- package/dist/lib/tui/builders.d.ts +7 -0
- package/dist/lib/tui/builders.js +58 -0
- package/dist/lib/tui/colors.d.ts +3 -0
- package/dist/lib/tui/colors.js +24 -0
- package/dist/lib/tui/elements.d.ts +61 -0
- package/dist/lib/tui/elements.js +1 -0
- package/dist/lib/tui/frame.d.ts +27 -0
- package/dist/lib/tui/frame.js +42 -0
- package/dist/lib/tui/index.d.ts +18 -0
- package/dist/lib/tui/index.js +18 -0
- package/dist/lib/tui/input/scripted.d.ts +12 -0
- package/dist/lib/tui/input/scripted.js +46 -0
- package/dist/lib/tui/input/terminal.d.ts +14 -0
- package/dist/lib/tui/input/terminal.js +131 -0
- package/dist/lib/tui/input/types.d.ts +10 -0
- package/dist/lib/tui/input/types.js +1 -0
- package/dist/lib/tui/layout.d.ts +6 -0
- package/dist/lib/tui/layout.js +191 -0
- package/dist/lib/tui/output/recorder.d.ts +14 -0
- package/dist/lib/tui/output/recorder.js +64 -0
- package/dist/lib/tui/output/terminal.d.ts +16 -0
- package/dist/lib/tui/output/terminal.js +63 -0
- package/dist/lib/tui/output/types.d.ts +5 -0
- package/dist/lib/tui/output/types.js +1 -0
- package/dist/lib/tui/render/ansi.d.ts +2 -0
- package/dist/lib/tui/render/ansi.js +43 -0
- package/dist/lib/tui/render/flatten.d.ts +9 -0
- package/dist/lib/tui/render/flatten.js +32 -0
- package/dist/lib/tui/render/html.d.ts +2 -0
- package/dist/lib/tui/render/html.js +45 -0
- package/dist/lib/tui/render/plaintext.d.ts +2 -0
- package/dist/lib/tui/render/plaintext.js +7 -0
- package/dist/lib/tui/render/renderer.d.ts +3 -0
- package/dist/lib/tui/render/renderer.js +189 -0
- package/dist/lib/tui/screen.d.ts +24 -0
- package/dist/lib/tui/screen.js +34 -0
- package/dist/lib/tui/styleParser.d.ts +8 -0
- package/dist/lib/tui/styleParser.js +86 -0
- package/dist/lib/tui/utils.d.ts +15 -0
- package/dist/lib/tui/utils.js +18 -0
- package/dist/lib/typeChecker/scopes.js +6 -0
- package/dist/lib/typeChecker.test.js +53 -0
- package/dist/lib/types/graphNode.d.ts +1 -2
- package/dist/lib/types.d.ts +1 -0
- package/dist/scripts/agency.js +55 -0
- package/package.json +28 -29
- package/stdlib/agent.js +10 -3
- package/stdlib/array.js +40 -13
- package/stdlib/browser.js +4 -1
- package/stdlib/calendar.js +19 -6
- package/stdlib/clipboard.js +7 -2
- package/stdlib/date.js +46 -15
- package/stdlib/email.js +10 -3
- package/stdlib/fs.js +22 -7
- package/stdlib/http.js +4 -1
- package/stdlib/imessage.js +4 -1
- package/stdlib/index.js +52 -17
- package/stdlib/keyring.js +13 -4
- package/stdlib/lib/speech.js +60 -1
- package/stdlib/math.js +13 -4
- package/stdlib/oauth.js +13 -4
- package/stdlib/object.js +16 -5
- package/stdlib/path.js +22 -7
- package/stdlib/policy.js +7 -2
- package/stdlib/shell.agency +64 -19
- package/stdlib/shell.js +28 -15
- package/stdlib/sms.js +4 -1
- package/stdlib/speech.agency +19 -1
- package/stdlib/speech.js +163 -3
- package/stdlib/strategy.js +16 -5
- package/stdlib/system.js +19 -6
- package/stdlib/ui.js +40 -13
- package/stdlib/weather.js +10 -3
- package/stdlib/wikipedia.js +10 -3
- package/dist/lib/agents/agency-agent/run.js +0 -113
- package/dist/lib/agents/agency-agent/subagents/code.js +0 -628
- package/dist/lib/agents/agency-agent/subagents/plan.js +0 -445
- package/dist/lib/agents/agency-agent/subagents/task.js +0 -557
- package/scripts/hooks/postinstall.js +0 -13
- package/stdlib/_builtins.js +0 -134
- package/stdlib/_math.js +0 -9
- package/stdlib/lib/process.js +0 -29
|
@@ -3,7 +3,7 @@ import { AccessChainElement, ValueAccess } from "../types/access.js";
|
|
|
3
3
|
import { BlockArgument } from "../types/blockArgument.js";
|
|
4
4
|
import { AgencyArray, AgencyObject } from "../types/dataStructures.js";
|
|
5
5
|
import { FunctionCall, FunctionDefinition } from "../types/function.js";
|
|
6
|
-
import { GraphNodeDefinition
|
|
6
|
+
import { GraphNodeDefinition } from "../types/graphNode.js";
|
|
7
7
|
import { IfElse } from "../types/ifElse.js";
|
|
8
8
|
import { ImportNameType, ImportNodeStatement, ImportStatement } from "../types/importStatement.js";
|
|
9
9
|
import { MatchBlock } from "../types/matchBlock.js";
|
|
@@ -95,7 +95,6 @@ export declare class AgencyGenerator {
|
|
|
95
95
|
protected processImportNameType(node: ImportNameType): string;
|
|
96
96
|
protected processImportNodeStatement(node: ImportNodeStatement): string;
|
|
97
97
|
private sortAndRenderImports;
|
|
98
|
-
protected visibilityToString(vis: Visibility): string;
|
|
99
98
|
protected processGraphNode(node: GraphNodeDefinition): string;
|
|
100
99
|
protected processClassDefinition(node: ClassDefinition): string;
|
|
101
100
|
protected processNewExpression(node: NewExpression): string;
|
|
@@ -326,13 +326,14 @@ export class AgencyGenerator {
|
|
|
326
326
|
const varName = node.typeHint
|
|
327
327
|
? `${node.variableName}${chainStr}: ${variableTypeToString(node.typeHint, this.typeAliases)}${bangSuffix}`
|
|
328
328
|
: `${node.variableName}${chainStr}`;
|
|
329
|
+
const exportPrefix = node.exported ? "export " : "";
|
|
329
330
|
const staticPrefix = node.static ? "static " : "";
|
|
330
331
|
const declPrefix = node.declKind ? `${node.declKind} ` : "";
|
|
331
332
|
let valueCode = node.value.type === "binOpExpression"
|
|
332
333
|
? this.processBinOpExpression(node.value, true).trim()
|
|
333
334
|
: this.processNode(node.value).trim();
|
|
334
335
|
return (tags +
|
|
335
|
-
this.indentStr(`${staticPrefix}${declPrefix}${varName} = ${valueCode}`));
|
|
336
|
+
this.indentStr(`${exportPrefix}${staticPrefix}${declPrefix}${varName} = ${valueCode}`));
|
|
336
337
|
}
|
|
337
338
|
generateLiteral(literal) {
|
|
338
339
|
switch (literal.type) {
|
|
@@ -690,16 +691,6 @@ export class AgencyGenerator {
|
|
|
690
691
|
.map((g) => g.map((e) => e.render()).join("\n"));
|
|
691
692
|
return groups.join("\n\n");
|
|
692
693
|
}
|
|
693
|
-
visibilityToString(vis) {
|
|
694
|
-
switch (vis) {
|
|
695
|
-
case "public":
|
|
696
|
-
return "public ";
|
|
697
|
-
case "private":
|
|
698
|
-
return "private ";
|
|
699
|
-
case undefined:
|
|
700
|
-
return "";
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
694
|
processGraphNode(node) {
|
|
704
695
|
const tags = this.formatAttachedTags(node);
|
|
705
696
|
const { nodeName, body, parameters } = node;
|
|
@@ -707,8 +698,8 @@ export class AgencyGenerator {
|
|
|
707
698
|
const returnTypeStr = node.returnType
|
|
708
699
|
? ": " + variableTypeToString(node.returnType, this.typeAliases) + returnTypeBang
|
|
709
700
|
: "";
|
|
710
|
-
const
|
|
711
|
-
const prefix = `${
|
|
701
|
+
const exportPrefix = node.exported ? "export " : "";
|
|
702
|
+
const prefix = `${exportPrefix}node ${nodeName}`;
|
|
712
703
|
const renderedParams = this.renderParams(parameters);
|
|
713
704
|
const signature = this.wrapList(renderedParams, prefix, "(", ")", `${returnTypeStr} {`);
|
|
714
705
|
let result = this.indentStr(`${signature}\n`);
|
|
@@ -351,10 +351,13 @@ export class TypeScriptBuilder {
|
|
|
351
351
|
// a separate `__initializeStatic(__ctx)` function (called once from __initializeGlobals).
|
|
352
352
|
// This gives them access to __ctx for handlers and function dispatch.
|
|
353
353
|
const staticVarNames = new Set();
|
|
354
|
+
const exportedStaticVarNames = new Set();
|
|
354
355
|
const staticInitStatements = [];
|
|
355
356
|
for (const node of program.nodes) {
|
|
356
357
|
if (node.type === "assignment" && node.scope === "static") {
|
|
357
358
|
staticVarNames.add(node.variableName);
|
|
359
|
+
if (node.exported)
|
|
360
|
+
exportedStaticVarNames.add(node.variableName);
|
|
358
361
|
const valueNode = this.processNodeInGlobalInit(node.value);
|
|
359
362
|
staticInitStatements.push(ts.assign(ts.id(node.variableName), ts.call(ts.id("__deepFreeze"), [valueNode])));
|
|
360
363
|
}
|
|
@@ -363,6 +366,8 @@ export class TypeScriptBuilder {
|
|
|
363
366
|
node.statement.scope === "static") {
|
|
364
367
|
const stmt = node.statement;
|
|
365
368
|
staticVarNames.add(stmt.variableName);
|
|
369
|
+
if (stmt.exported)
|
|
370
|
+
exportedStaticVarNames.add(stmt.variableName);
|
|
366
371
|
const valueNode = this.processNodeInGlobalInit(stmt.value);
|
|
367
372
|
const handler = this.buildHandlerArrow(node.handlerName);
|
|
368
373
|
staticInitStatements.push(ts.withHandler(handler, ts.assign(ts.id(stmt.variableName), ts.call(ts.id("__deepFreeze"), [valueNode]))));
|
|
@@ -427,7 +432,7 @@ export class TypeScriptBuilder {
|
|
|
427
432
|
}
|
|
428
433
|
// Emit static variable `let` declarations at module level + __initializeStatic function
|
|
429
434
|
if (staticVarNames.size > 0) {
|
|
430
|
-
const staticLetDecls = [...staticVarNames].map(name => ts.letDecl(name));
|
|
435
|
+
const staticLetDecls = [...staticVarNames].map(name => exportedStaticVarNames.has(name) ? ts.export(ts.letDecl(name)) : ts.letDecl(name));
|
|
431
436
|
sections.push(ts.statements([
|
|
432
437
|
ts.raw("let __staticInitPromise = null"),
|
|
433
438
|
...staticLetDecls,
|
|
@@ -1453,6 +1458,8 @@ export class TypeScriptBuilder {
|
|
|
1453
1458
|
fn: ts.id(implName),
|
|
1454
1459
|
params: ts.arr(paramNodes),
|
|
1455
1460
|
toolDefinition: toolDef,
|
|
1461
|
+
safe: ts.bool(!!node.safe),
|
|
1462
|
+
exported: ts.bool(!!node.exported),
|
|
1456
1463
|
}),
|
|
1457
1464
|
ts.id("__toolRegistry"),
|
|
1458
1465
|
])
|
package/dist/lib/cli/commands.js
CHANGED
|
@@ -49,7 +49,7 @@ export function parse(contents, config, applyTemplate = true) {
|
|
|
49
49
|
const parseResult = parseAgency(contents, config, applyTemplate);
|
|
50
50
|
// Check if parsing was successful
|
|
51
51
|
if (!parseResult.success) {
|
|
52
|
-
console.error("Failed to parse Agency program.");
|
|
52
|
+
console.error("Failed to parse Agency program.", contents.slice(0, 400));
|
|
53
53
|
process.exit(1);
|
|
54
54
|
}
|
|
55
55
|
return parseResult.result;
|
package/dist/lib/cli/debug.js
CHANGED
|
@@ -5,7 +5,7 @@ import { parseAgency } from "../parser.js";
|
|
|
5
5
|
import { getNodesOfType } from "../utils/node.js";
|
|
6
6
|
import { DebuggerDriver } from "../debugger/driver.js";
|
|
7
7
|
import { DebuggerUI } from "../debugger/ui.js";
|
|
8
|
-
import { Screen, TerminalInput, TerminalOutput } from "
|
|
8
|
+
import { Screen, TerminalInput, TerminalOutput } from "../tui/index.js";
|
|
9
9
|
import { TraceReader } from "../runtime/trace/traceReader.js";
|
|
10
10
|
import { Checkpoint } from "../runtime/state/checkpointStore.js";
|
|
11
11
|
import { createDebugInterrupt } from "../runtime/interrupts.js";
|
|
@@ -61,6 +61,8 @@ export class LaunchdBackend {
|
|
|
61
61
|
name: entry.name,
|
|
62
62
|
runScriptPath,
|
|
63
63
|
agentDir: path.dirname(entry.agentFile),
|
|
64
|
+
path: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
|
|
65
|
+
home: os.homedir(),
|
|
64
66
|
intervals: buildIntervals(entry.cron),
|
|
65
67
|
logDir: entry.logDir,
|
|
66
68
|
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type TestOptions = {
|
|
2
|
+
baseDir?: string;
|
|
3
|
+
cwd?: string;
|
|
4
|
+
};
|
|
5
|
+
export type TestResult = {
|
|
6
|
+
name: string;
|
|
7
|
+
agentFile: string;
|
|
8
|
+
outputFile: string;
|
|
9
|
+
logDir: string;
|
|
10
|
+
};
|
|
11
|
+
export declare const TEST_SCHEDULE_NAME = "agency-cron-test";
|
|
12
|
+
export declare const TEST_OUTPUT_FILE = "agency-cron-test.txt";
|
|
13
|
+
export declare const TEST_AGENT_FILE = "agency-cron-test.agency";
|
|
14
|
+
export declare function scheduleTest(opts?: TestOptions): TestResult;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import * as os from "os";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import { scheduleAdd } from "./index.js";
|
|
5
|
+
export const TEST_SCHEDULE_NAME = "agency-cron-test";
|
|
6
|
+
export const TEST_OUTPUT_FILE = "agency-cron-test.txt";
|
|
7
|
+
export const TEST_AGENT_FILE = "agency-cron-test.agency";
|
|
8
|
+
const TEST_AGENT_CONTENT = `import { now } from "std::date"
|
|
9
|
+
|
|
10
|
+
node main() {
|
|
11
|
+
write("${TEST_OUTPUT_FILE}", now()) with approve
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
export function scheduleTest(opts = {}) {
|
|
15
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
16
|
+
const agentFile = path.join(cwd, TEST_AGENT_FILE);
|
|
17
|
+
const outputFile = path.join(cwd, TEST_OUTPUT_FILE);
|
|
18
|
+
fs.writeFileSync(agentFile, TEST_AGENT_CONTENT);
|
|
19
|
+
scheduleAdd({
|
|
20
|
+
file: agentFile,
|
|
21
|
+
every: "minute",
|
|
22
|
+
name: TEST_SCHEDULE_NAME,
|
|
23
|
+
baseDir: opts.baseDir,
|
|
24
|
+
force: true,
|
|
25
|
+
});
|
|
26
|
+
const baseDir = opts.baseDir ?? path.join(os.homedir(), ".agency", "schedules");
|
|
27
|
+
const logDir = path.join(baseDir, TEST_SCHEDULE_NAME, "logs");
|
|
28
|
+
return { name: TEST_SCHEDULE_NAME, agentFile, outputFile, logDir };
|
|
29
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import process from "process";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
import { compile, loadConfig } from "./commands.js";
|
|
5
|
+
import { SymbolTable } from "../symbolTable.js";
|
|
6
|
+
import { discoverExports } from "../serve/discovery.js";
|
|
7
|
+
import { createMcpHandler, startStdioServer } from "../serve/mcp/adapter.js";
|
|
8
|
+
import { startHttpServer } from "../serve/http/adapter.js";
|
|
9
|
+
import { createLogger } from "../logger.js";
|
|
10
|
+
import { VERSION } from "../version.js";
|
|
11
|
+
import * as esbuild from "esbuild";
|
|
12
|
+
function compileForServe(file) {
|
|
13
|
+
const config = loadConfig();
|
|
14
|
+
const absoluteFile = path.resolve(file);
|
|
15
|
+
const symbolTable = SymbolTable.build(absoluteFile, config);
|
|
16
|
+
const outputPath = compile(config, file, undefined, { symbolTable });
|
|
17
|
+
if (!outputPath) {
|
|
18
|
+
throw new Error(`Compilation failed for ${file}`);
|
|
19
|
+
}
|
|
20
|
+
const fileSymbols = symbolTable.getFile(absoluteFile);
|
|
21
|
+
const exportedNodeNames = Object.values(fileSymbols ?? {})
|
|
22
|
+
.filter((sym) => sym.kind === "node" && sym.exported)
|
|
23
|
+
.map((sym) => sym.name);
|
|
24
|
+
const moduleId = path.relative(process.cwd(), absoluteFile);
|
|
25
|
+
return { outputPath, moduleId, exportedNodeNames };
|
|
26
|
+
}
|
|
27
|
+
async function loadAndDiscover(compileResult) {
|
|
28
|
+
const moduleUrl = pathToFileURL(path.resolve(compileResult.outputPath)).href;
|
|
29
|
+
const mod = await import(moduleUrl);
|
|
30
|
+
const moduleExports = mod;
|
|
31
|
+
const toolRegistry = moduleExports.__toolRegistry ?? {};
|
|
32
|
+
const exports = discoverExports({
|
|
33
|
+
toolRegistry,
|
|
34
|
+
moduleExports,
|
|
35
|
+
moduleId: compileResult.moduleId,
|
|
36
|
+
exportedNodeNames: compileResult.exportedNodeNames,
|
|
37
|
+
});
|
|
38
|
+
return { exports, moduleExports };
|
|
39
|
+
}
|
|
40
|
+
export async function serveMcp(file, options) {
|
|
41
|
+
const compileResult = compileForServe(file);
|
|
42
|
+
const { exports } = await loadAndDiscover(compileResult);
|
|
43
|
+
const serverName = options.name ?? path.basename(file, ".agency");
|
|
44
|
+
const handler = createMcpHandler({
|
|
45
|
+
serverName,
|
|
46
|
+
serverVersion: VERSION,
|
|
47
|
+
exports,
|
|
48
|
+
});
|
|
49
|
+
startStdioServer(handler);
|
|
50
|
+
}
|
|
51
|
+
export async function serveHttp(file, options) {
|
|
52
|
+
const compileResult = compileForServe(file);
|
|
53
|
+
if (options.standalone) {
|
|
54
|
+
await generateStandalone(compileResult.outputPath, file);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const { exports, moduleExports } = await loadAndDiscover(compileResult);
|
|
58
|
+
const port = parseInt(options.port ?? "3545", 10);
|
|
59
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
60
|
+
throw new Error(`Invalid port: ${options.port}`);
|
|
61
|
+
}
|
|
62
|
+
const logger = createLogger("info");
|
|
63
|
+
startHttpServer({
|
|
64
|
+
exports,
|
|
65
|
+
port,
|
|
66
|
+
apiKey: options.apiKey,
|
|
67
|
+
logger,
|
|
68
|
+
hasInterrupts: moduleExports.hasInterrupts,
|
|
69
|
+
respondToInterrupts: moduleExports.respondToInterrupts,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async function generateStandalone(compiledPath, originalFile) {
|
|
73
|
+
const outfile = path.basename(originalFile, ".agency") + ".server.js";
|
|
74
|
+
await esbuild.build({
|
|
75
|
+
entryPoints: [compiledPath],
|
|
76
|
+
bundle: true,
|
|
77
|
+
platform: "node",
|
|
78
|
+
format: "esm",
|
|
79
|
+
outfile,
|
|
80
|
+
banner: {
|
|
81
|
+
js: "// Generated by Agency — standalone HTTP server\n",
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
console.log(`Standalone server written to ${outfile}`);
|
|
85
|
+
}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AgencyNode } from "./types.js";
|
|
2
|
+
import type { LogLevel } from "./logger.js";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
export declare const TYPES_THAT_DONT_TRIGGER_NEW_PART: AgencyNode["type"][];
|
|
4
5
|
/**
|
|
@@ -13,6 +14,7 @@ export declare const BUILTIN_VARIABLES: string[];
|
|
|
13
14
|
*/
|
|
14
15
|
export interface AgencyConfig {
|
|
15
16
|
verbose?: boolean;
|
|
17
|
+
logLevel?: LogLevel;
|
|
16
18
|
outDir?: string;
|
|
17
19
|
/**
|
|
18
20
|
* Array of AST node types to exclude from code generation
|
|
@@ -121,6 +123,12 @@ export interface AgencyConfig {
|
|
|
121
123
|
}
|
|
122
124
|
export declare const AgencyConfigSchema: z.ZodObject<{
|
|
123
125
|
verbose: z.ZodOptional<z.ZodBoolean>;
|
|
126
|
+
logLevel: z.ZodOptional<z.ZodEnum<{
|
|
127
|
+
debug: "debug";
|
|
128
|
+
info: "info";
|
|
129
|
+
warn: "warn";
|
|
130
|
+
error: "error";
|
|
131
|
+
}>>;
|
|
124
132
|
outDir: z.ZodOptional<z.ZodString>;
|
|
125
133
|
excludeNodeTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
126
134
|
excludeBuiltinFunctions: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -136,10 +144,10 @@ export declare const AgencyConfigSchema: z.ZodObject<{
|
|
|
136
144
|
}, z.core.$strip>>;
|
|
137
145
|
client: z.ZodOptional<z.ZodObject<{
|
|
138
146
|
logLevel: z.ZodOptional<z.ZodEnum<{
|
|
139
|
-
error: "error";
|
|
140
|
-
warn: "warn";
|
|
141
|
-
info: "info";
|
|
142
147
|
debug: "debug";
|
|
148
|
+
info: "info";
|
|
149
|
+
warn: "warn";
|
|
150
|
+
error: "error";
|
|
143
151
|
}>>;
|
|
144
152
|
defaultModel: z.ZodOptional<z.ZodString>;
|
|
145
153
|
openAiApiKey: z.ZodOptional<z.ZodString>;
|
package/dist/lib/config.js
CHANGED
|
@@ -19,6 +19,7 @@ export const BUILTIN_VARIABLES = ["color"];
|
|
|
19
19
|
export const AgencyConfigSchema = z
|
|
20
20
|
.object({
|
|
21
21
|
verbose: z.boolean(),
|
|
22
|
+
logLevel: z.enum(["debug", "info", "warn", "error"]),
|
|
22
23
|
outDir: z.string(),
|
|
23
24
|
excludeNodeTypes: z.array(z.string()),
|
|
24
25
|
excludeBuiltinFunctions: z.array(z.string()),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { box, row, column, text, escapeStyleTags, } from "
|
|
1
|
+
import { box, row, column, text, escapeStyleTags, } from "../tui/index.js";
|
|
2
2
|
import { formatValue } from "./util.js";
|
|
3
3
|
// ---------------------------------------------------------------------------
|
|
4
4
|
// Rewind selector
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FrameRecorder, type Frame } from "
|
|
1
|
+
import { FrameRecorder, type Frame } from "../tui/index.js";
|
|
2
2
|
import { DebuggerDriver } from "./driver.js";
|
|
3
3
|
import { DebuggerUI } from "./ui.js";
|
|
4
4
|
import type { Checkpoint } from "../runtime/state/checkpointStore.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Screen, FrameRecorder, } from "
|
|
1
|
+
import { Screen, FrameRecorder, } from "../tui/index.js";
|
|
2
2
|
import { DebuggerDriver } from "./driver.js";
|
|
3
3
|
import { DebuggerUI } from "./ui.js";
|
|
4
4
|
import { hasInterrupts, createDebugInterrupt } from "../runtime/interrupts.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Screen, type Element, type Frame } from "
|
|
1
|
+
import { Screen, type Element, type Frame } from "../tui/index.js";
|
|
2
2
|
import type { Checkpoint } from "../runtime/state/checkpointStore.js";
|
|
3
3
|
import type { FunctionParameter } from "../types.js";
|
|
4
4
|
import type { DebuggerCommand, DebuggerIO } from "./types.js";
|
package/dist/lib/debugger/ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { box, row, column, text, escapeStyleTags, } from "
|
|
1
|
+
import { box, row, column, text, escapeStyleTags, } from "../tui/index.js";
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
3
|
import { formatTypeHint } from "../cli/util.js";
|
|
4
4
|
import { UIState } from "./uiState.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
2
|
+
export type Logger = {
|
|
3
|
+
debug: (message: string) => void;
|
|
4
|
+
info: (message: string) => void;
|
|
5
|
+
warn: (message: string) => void;
|
|
6
|
+
error: (message: string) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function createLogger(level?: LogLevel): Logger;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const LEVEL_ORDER = {
|
|
2
|
+
debug: 0,
|
|
3
|
+
info: 1,
|
|
4
|
+
warn: 2,
|
|
5
|
+
error: 3,
|
|
6
|
+
};
|
|
7
|
+
export function createLogger(level = "info") {
|
|
8
|
+
const threshold = LEVEL_ORDER[level];
|
|
9
|
+
function log(msgLevel, message) {
|
|
10
|
+
if (LEVEL_ORDER[msgLevel] < threshold)
|
|
11
|
+
return;
|
|
12
|
+
const timestamp = new Date().toISOString().replace("T", " ").replace("Z", "");
|
|
13
|
+
process.stderr.write(`[${timestamp}] ${msgLevel.toUpperCase()} ${message}\n`);
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
debug: (msg) => log("debug", msg),
|
|
17
|
+
info: (msg) => log("info", msg),
|
|
18
|
+
warn: (msg) => log("warn", msg),
|
|
19
|
+
error: (msg) => log("error", msg),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { createLogger } from "./logger.js";
|
|
3
|
+
describe("createLogger", () => {
|
|
4
|
+
let spy;
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
spy = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
|
|
7
|
+
});
|
|
8
|
+
afterEach(() => spy.mockRestore());
|
|
9
|
+
it("logs at info level by default", () => {
|
|
10
|
+
const log = createLogger("info");
|
|
11
|
+
log.info("hello");
|
|
12
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
13
|
+
expect(spy.mock.calls[0][0]).toContain("hello");
|
|
14
|
+
});
|
|
15
|
+
it("suppresses debug when level is info", () => {
|
|
16
|
+
const log = createLogger("info");
|
|
17
|
+
log.debug("hidden");
|
|
18
|
+
expect(spy).not.toHaveBeenCalled();
|
|
19
|
+
});
|
|
20
|
+
it("shows debug when level is debug", () => {
|
|
21
|
+
const log = createLogger("debug");
|
|
22
|
+
log.debug("visible");
|
|
23
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
24
|
+
});
|
|
25
|
+
it("suppresses info when level is warn", () => {
|
|
26
|
+
const log = createLogger("warn");
|
|
27
|
+
log.warn("caution");
|
|
28
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
29
|
+
log.info("suppressed");
|
|
30
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
31
|
+
});
|
|
32
|
+
it("suppresses warn when level is error", () => {
|
|
33
|
+
const log = createLogger("error");
|
|
34
|
+
log.error("bad");
|
|
35
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
36
|
+
log.warn("suppressed");
|
|
37
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
38
|
+
});
|
|
39
|
+
it("includes level label in output", () => {
|
|
40
|
+
const log = createLogger("debug");
|
|
41
|
+
log.warn("test");
|
|
42
|
+
expect(spy.mock.calls[0][0]).toContain("WARN");
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -165,6 +165,8 @@ function formatSignature(symbol) {
|
|
|
165
165
|
: `type ${symbol.name}`;
|
|
166
166
|
case "class":
|
|
167
167
|
return `class ${symbol.name}`;
|
|
168
|
+
case "constant":
|
|
169
|
+
return `static const ${symbol.name}${symbol.returnType ? `: ${formatTypeHint(symbol.returnType)}` : ""}`;
|
|
168
170
|
}
|
|
169
171
|
}
|
|
170
172
|
export function formatSemanticHover(symbol) {
|
package/dist/lib/parser.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { capture, eof, failure, getErrorMessage, many, map, or, seqC, set, setInputStr, setTraceHost, setTraceId, success, TarsecError, trace, } from "tarsec";
|
|
2
2
|
import { nanoid } from "nanoid";
|
|
3
3
|
import render from "./templates/backends/agency/template.js";
|
|
4
|
-
import { assignmentParser, binOpParser, booleanParser, commentParser, debuggerParser, forLoopParser, functionParser, gotoStatementParser, graphNodeParser, handleBlockParser, ifParser, importNodeStatmentParser, importStatmentParser, interruptStatementParser, keywordParser, matchBlockParser, messageThreadParser, multiLineCommentParser, newLineParser, blankLineParser, BLANK_LINE_SENTINEL, optionalSpacesOrNewline, returnStatementParser,
|
|
5
|
-
const nodeParser = or(keywordParser, importNodeStatmentParser, importStatmentParser, graphNodeParser, classParser, typeAliasParser, ifParser, forLoopParser, whileLoopParser, matchBlockParser, messageThreadParser, handleBlockParser, debuggerParser, skillParser, functionParser, returnStatementParser, gotoStatementParser, interruptStatementParser, tagParser, withModifierParser,
|
|
4
|
+
import { assignmentParser, binOpParser, booleanParser, commentParser, debuggerParser, forLoopParser, functionParser, gotoStatementParser, graphNodeParser, handleBlockParser, ifParser, importNodeStatmentParser, importStatmentParser, interruptStatementParser, keywordParser, matchBlockParser, messageThreadParser, multiLineCommentParser, newLineParser, blankLineParser, BLANK_LINE_SENTINEL, optionalSpacesOrNewline, returnStatementParser, modifiedAssignmentParser, skillParser, tagParser, typeAliasParser, valueAccessParser, whileLoopParser, withModifierParser, classParser, AGENCY_TEMPLATE_OFFSET, setTemplateOffset, } from "./parsers/parsers.js";
|
|
5
|
+
const nodeParser = or(keywordParser, importNodeStatmentParser, importStatmentParser, graphNodeParser, classParser, typeAliasParser, ifParser, forLoopParser, whileLoopParser, matchBlockParser, messageThreadParser, handleBlockParser, debuggerParser, skillParser, functionParser, returnStatementParser, gotoStatementParser, interruptStatementParser, tagParser, withModifierParser, modifiedAssignmentParser, assignmentParser, binOpParser, booleanParser, valueAccessParser, multiLineCommentParser, commentParser, blankLineParser, newLineParser);
|
|
6
6
|
export const agencyNode = (input) => {
|
|
7
7
|
const parser = many(trace("agencyParser", map(seqC(capture(nodeParser, "node"), optionalSpacesOrNewline), (result) => result.node)));
|
|
8
8
|
return parser(input);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { assignmentParser,
|
|
2
|
+
import { assignmentParser, modifiedAssignmentParser } from "./parsers.js";
|
|
3
3
|
describe("assignmentParser", () => {
|
|
4
4
|
const testCases = [
|
|
5
5
|
// Happy path - simple literal assignments
|
|
@@ -564,9 +564,9 @@ describe("assignmentParser", () => {
|
|
|
564
564
|
}
|
|
565
565
|
});
|
|
566
566
|
});
|
|
567
|
-
describe("
|
|
567
|
+
describe("modifiedAssignmentParser", () => {
|
|
568
568
|
it("should parse static const with a number", () => {
|
|
569
|
-
const result =
|
|
569
|
+
const result = modifiedAssignmentParser("static const x = 42");
|
|
570
570
|
expect(result.success).toBe(true);
|
|
571
571
|
if (result.success) {
|
|
572
572
|
expect(result.result.type).toBe("assignment");
|
|
@@ -577,7 +577,7 @@ describe("staticAssignmentParser", () => {
|
|
|
577
577
|
}
|
|
578
578
|
});
|
|
579
579
|
it("should parse static const with a string", () => {
|
|
580
|
-
const result =
|
|
580
|
+
const result = modifiedAssignmentParser('static const name = "Alice"');
|
|
581
581
|
expect(result.success).toBe(true);
|
|
582
582
|
if (result.success) {
|
|
583
583
|
expect(result.result.static).toBe(true);
|
|
@@ -586,7 +586,7 @@ describe("staticAssignmentParser", () => {
|
|
|
586
586
|
}
|
|
587
587
|
});
|
|
588
588
|
it("should parse static const with a function call", () => {
|
|
589
|
-
const result =
|
|
589
|
+
const result = modifiedAssignmentParser('static const myPrompt = read("prompt.md")');
|
|
590
590
|
expect(result.success).toBe(true);
|
|
591
591
|
if (result.success) {
|
|
592
592
|
expect(result.result.static).toBe(true);
|
|
@@ -596,19 +596,19 @@ describe("staticAssignmentParser", () => {
|
|
|
596
596
|
}
|
|
597
597
|
});
|
|
598
598
|
it("should reject static let", () => {
|
|
599
|
-
const result =
|
|
599
|
+
const result = modifiedAssignmentParser("static let x = 42");
|
|
600
600
|
expect(result.success).toBe(false);
|
|
601
601
|
});
|
|
602
602
|
it("should reject static without const", () => {
|
|
603
|
-
const result =
|
|
603
|
+
const result = modifiedAssignmentParser("static x = 42");
|
|
604
604
|
expect(result.success).toBe(false);
|
|
605
605
|
});
|
|
606
606
|
it("should not parse a regular assignment", () => {
|
|
607
|
-
const result =
|
|
607
|
+
const result = modifiedAssignmentParser("x = 42");
|
|
608
608
|
expect(result.success).toBe(false);
|
|
609
609
|
});
|
|
610
610
|
it("should not parse const without static", () => {
|
|
611
|
-
const result =
|
|
611
|
+
const result = modifiedAssignmentParser("const x = 42");
|
|
612
612
|
expect(result.success).toBe(false);
|
|
613
613
|
});
|
|
614
614
|
it("regular assignmentParser should not set static", () => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { modifiedAssignmentParser } from "./parsers.js";
|
|
3
|
+
describe("export const", () => {
|
|
4
|
+
it("parses export const", () => {
|
|
5
|
+
const result = modifiedAssignmentParser(`export const x = 5\n`);
|
|
6
|
+
expect(result.success).toBe(true);
|
|
7
|
+
if (result.success) {
|
|
8
|
+
expect(result.result.exported).toBe(true);
|
|
9
|
+
expect(result.result.declKind).toBe("const");
|
|
10
|
+
expect(result.result.variableName).toBe("x");
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
it("parses export static const", () => {
|
|
14
|
+
const result = modifiedAssignmentParser(`export static const x = 5\n`);
|
|
15
|
+
expect(result.success).toBe(true);
|
|
16
|
+
if (result.success) {
|
|
17
|
+
expect(result.result.exported).toBe(true);
|
|
18
|
+
expect(result.result.static).toBe(true);
|
|
19
|
+
expect(result.result.declKind).toBe("const");
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
it("parses static export const (any order)", () => {
|
|
23
|
+
const result = modifiedAssignmentParser(`static export const x = 5\n`);
|
|
24
|
+
expect(result.success).toBe(true);
|
|
25
|
+
if (result.success) {
|
|
26
|
+
expect(result.result.exported).toBe(true);
|
|
27
|
+
expect(result.result.static).toBe(true);
|
|
28
|
+
expect(result.result.declKind).toBe("const");
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
// The parser accepts export let syntactically; the typechecker is responsible
|
|
32
|
+
// for rejecting it (export only makes sense for const declarations).
|
|
33
|
+
it("parses export let (typechecker rejects this, not parser)", () => {
|
|
34
|
+
const result = modifiedAssignmentParser(`export let x = 5\n`);
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
if (result.success) {
|
|
37
|
+
expect(result.result.exported).toBe(true);
|
|
38
|
+
expect(result.result.declKind).toBe("let");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { graphNodeParser, functionParser } from "./parsers.js";
|
|
3
|
+
describe("export node", () => {
|
|
4
|
+
it("parses export node", () => {
|
|
5
|
+
const result = graphNodeParser(`export node main() {\n print("hello")\n}`);
|
|
6
|
+
expect(result.success).toBe(true);
|
|
7
|
+
if (result.success) {
|
|
8
|
+
expect(result.result.exported).toBe(true);
|
|
9
|
+
expect(result.result.nodeName).toBe("main");
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
it("parses node without export", () => {
|
|
13
|
+
const result = graphNodeParser(`node main() {\n print("hello")\n}`);
|
|
14
|
+
expect(result.success).toBe(true);
|
|
15
|
+
if (result.success) {
|
|
16
|
+
expect(result.result.exported).toBeUndefined();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe("function modifier order", () => {
|
|
21
|
+
it("parses export safe def", () => {
|
|
22
|
+
const result = functionParser(`export safe def foo() {\n return 1\n}`);
|
|
23
|
+
expect(result.success).toBe(true);
|
|
24
|
+
if (result.success) {
|
|
25
|
+
expect(result.result.exported).toBe(true);
|
|
26
|
+
expect(result.result.safe).toBe(true);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
it("parses safe export def (any order)", () => {
|
|
30
|
+
const result = functionParser(`safe export def foo() {\n return 1\n}`);
|
|
31
|
+
expect(result.success).toBe(true);
|
|
32
|
+
if (result.success) {
|
|
33
|
+
expect(result.result.exported).toBe(true);
|
|
34
|
+
expect(result.result.safe).toBe(true);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -129,7 +129,7 @@ export declare const matchBlockParser: Parser<{
|
|
|
129
129
|
export declare const importNodeStatmentParser: Parser<ImportNodeStatement>;
|
|
130
130
|
export declare const importStatmentParser: Parser<ImportStatement>;
|
|
131
131
|
export declare const assignmentParser: Parser<Assignment>;
|
|
132
|
-
export declare const
|
|
132
|
+
export declare const modifiedAssignmentParser: Parser<Assignment>;
|
|
133
133
|
export declare const docStringParser: Parser<DocString>;
|
|
134
134
|
export declare const bodyParser: (input: string) => ParserResult<AgencyNode[]>;
|
|
135
135
|
export declare const _messageThreadParser: Parser<MessageThread>;
|