@rong/agentscript 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/CHANGELOG.md +22 -0
- package/INSTALL.md +92 -0
- package/LICENSE +21 -0
- package/README.md +246 -0
- package/dist/ast/constants.js +1 -0
- package/dist/ast/format.js +41 -0
- package/dist/ast/types.js +1 -0
- package/dist/bin/agentscript.js +234 -0
- package/dist/bin/input.js +19 -0
- package/dist/bin/repl.js +290 -0
- package/dist/index.js +26 -0
- package/dist/parser/errors.js +8 -0
- package/dist/parser/parser.js +661 -0
- package/dist/parser/tokenizer.js +246 -0
- package/dist/providers/llm/anthropic.js +36 -0
- package/dist/providers/llm/index.js +3 -0
- package/dist/providers/llm/ollama.js +19 -0
- package/dist/providers/llm/openai.js +31 -0
- package/dist/providers/llm/protocol.js +45 -0
- package/dist/providers/llm/shared.js +147 -0
- package/dist/providers/llm/types.js +1 -0
- package/dist/providers/llm/uri.js +24 -0
- package/dist/providers/memory/file.js +44 -0
- package/dist/providers/memory/host.js +66 -0
- package/dist/providers/memory/index.js +1 -0
- package/dist/providers/memory/shared.js +56 -0
- package/dist/providers/memory/sqlite.js +98 -0
- package/dist/providers/mock/index.js +32 -0
- package/dist/providers/tools/env.js +11 -0
- package/dist/providers/tools/file.js +99 -0
- package/dist/providers/tools/host.js +34 -0
- package/dist/providers/tools/http.js +40 -0
- package/dist/providers/tools/index.js +2 -0
- package/dist/providers/tools/scheme.js +16 -0
- package/dist/providers/tools/shared.js +92 -0
- package/dist/providers/tools/shell.js +80 -0
- package/dist/runtime/context.js +160 -0
- package/dist/runtime/errors.js +14 -0
- package/dist/runtime/evaluator.js +276 -0
- package/dist/runtime/generate.js +175 -0
- package/dist/runtime/guards.js +39 -0
- package/dist/runtime/input.js +38 -0
- package/dist/runtime/interpreter.js +314 -0
- package/dist/runtime/json.js +59 -0
- package/dist/runtime/loader.js +146 -0
- package/dist/runtime/scope.js +47 -0
- package/dist/runtime/shape.js +132 -0
- package/dist/runtime/trace.js +54 -0
- package/dist/runtime/truth.js +13 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/uri.js +10 -0
- package/dist/semantic/analyzer.js +519 -0
- package/dist/semantic/diagnostics.js +16 -0
- package/dist/utils/assert.js +3 -0
- package/docs/cn/context-engineering.md +389 -0
- package/docs/cn/language.md +478 -0
- package/docs/design-history/v0-design.md +365 -0
- package/docs/design-history/v0-implement.md +274 -0
- package/docs/design-history/v1-design.md +323 -0
- package/docs/design-history/v1-implement.md +267 -0
- package/docs/design-history/v2-design.md +387 -0
- package/docs/design-history/v2-implement.md +399 -0
- package/docs/en/context-engineering.md +332 -0
- package/docs/en/language.md +478 -0
- package/examples/changelog.as +29 -0
- package/examples/extract.as +29 -0
- package/examples/review.as +38 -0
- package/examples/summarize.as +28 -0
- package/examples/translate.as +33 -0
- package/package.json +59 -0
- package/tutorials/cli.as +22 -0
- package/tutorials/helloworld.as +14 -0
- package/tutorials/memory.as +19 -0
- package/tutorials/plan-execute.as +155 -0
- package/tutorials/react.as +98 -0
- package/tutorials/repl.as +31 -0
- package/tutorials/self-improve.as +60 -0
package/dist/bin/repl.js
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { createInterface } from "node:readline/promises";
|
|
3
|
+
import { stdin as inputStream, stdout as outputStream } from "node:process";
|
|
4
|
+
import { parse } from "../parser/parser.js";
|
|
5
|
+
import { executeAgent } from "../runtime/interpreter.js";
|
|
6
|
+
import { sanitizeForJson } from "../runtime/json.js";
|
|
7
|
+
import { loadProgramSource } from "../runtime/loader.js";
|
|
8
|
+
import { ProtocolLlmProvider } from "../providers/llm/index.js";
|
|
9
|
+
import { formatTrace } from "../runtime/trace.js";
|
|
10
|
+
import { analyze } from "../semantic/analyzer.js";
|
|
11
|
+
import { formatSemanticDiagnostics } from "../semantic/diagnostics.js";
|
|
12
|
+
import { parseInteractiveInputValue, parseJsonObjectInput } from "./input.js";
|
|
13
|
+
const MAIN_AGENT_PATTERN = /^\s*main\s+agent\b/;
|
|
14
|
+
const AGENT_PATTERN = /^\s*(?:main\s+)?agent\b/;
|
|
15
|
+
export async function runRepl(options = {}) {
|
|
16
|
+
const reader = createInterface({
|
|
17
|
+
input: options.input ?? inputStream,
|
|
18
|
+
output: options.output ?? outputStream,
|
|
19
|
+
terminal: isTty(options.input ?? inputStream)
|
|
20
|
+
});
|
|
21
|
+
const session = {
|
|
22
|
+
agentSources: new Map(),
|
|
23
|
+
importSources: [],
|
|
24
|
+
lastTrace: [],
|
|
25
|
+
realLlm: false,
|
|
26
|
+
sourcePath: undefined
|
|
27
|
+
};
|
|
28
|
+
try {
|
|
29
|
+
console.log("AgentScript REPL");
|
|
30
|
+
console.log("Paste one complete agent or use :help.");
|
|
31
|
+
let buffer = [];
|
|
32
|
+
while (true) {
|
|
33
|
+
const line = await reader.question(buffer.length === 0 ? "> " : ". ");
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (buffer.length === 0 && trimmed.startsWith(":")) {
|
|
36
|
+
const shouldContinue = await handleCommand(trimmed, session, reader);
|
|
37
|
+
if (!shouldContinue) {
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (buffer.length === 0 && trimmed.length === 0) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
buffer.push(line);
|
|
46
|
+
if (!isBalancedAgentBuffer(buffer)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const source = buffer.join("\n").trim();
|
|
50
|
+
buffer = [];
|
|
51
|
+
if (source.length === 0) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
addAgentSource(session, source);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error instanceof Error && error.message === "readline was closed") {
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
reader.close();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function handleCommand(commandLine, session, reader) {
|
|
69
|
+
const [command, ...rest] = commandLine.slice(1).trim().split(/\s+/);
|
|
70
|
+
const args = rest.join(" ");
|
|
71
|
+
switch (command) {
|
|
72
|
+
case "help":
|
|
73
|
+
printHelp();
|
|
74
|
+
return true;
|
|
75
|
+
case "exit":
|
|
76
|
+
case "quit":
|
|
77
|
+
return false;
|
|
78
|
+
case "import":
|
|
79
|
+
addImport(session, args);
|
|
80
|
+
return true;
|
|
81
|
+
case "load":
|
|
82
|
+
loadFile(session, args);
|
|
83
|
+
return true;
|
|
84
|
+
case "agents":
|
|
85
|
+
printAgents(session);
|
|
86
|
+
return true;
|
|
87
|
+
case "main":
|
|
88
|
+
setMainAgent(session, args);
|
|
89
|
+
return true;
|
|
90
|
+
case "show":
|
|
91
|
+
console.log(buildProgramSource(session));
|
|
92
|
+
return true;
|
|
93
|
+
case "parse":
|
|
94
|
+
console.log(JSON.stringify(loadSessionProgram(session), null, 2));
|
|
95
|
+
return true;
|
|
96
|
+
case "check":
|
|
97
|
+
checkSession(session);
|
|
98
|
+
return true;
|
|
99
|
+
case "run":
|
|
100
|
+
await runSession(session, args, reader);
|
|
101
|
+
return true;
|
|
102
|
+
case "trace":
|
|
103
|
+
if (args === "pretty") {
|
|
104
|
+
console.log(formatTrace(session.lastTrace));
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
console.log(JSON.stringify(session.lastTrace, null, 2));
|
|
108
|
+
}
|
|
109
|
+
return true;
|
|
110
|
+
case "real-llm":
|
|
111
|
+
setRealLlm(session, args);
|
|
112
|
+
return true;
|
|
113
|
+
case "reset":
|
|
114
|
+
session.agentSources.clear();
|
|
115
|
+
session.importSources = [];
|
|
116
|
+
session.lastTrace = [];
|
|
117
|
+
session.sourcePath = undefined;
|
|
118
|
+
console.log("reset");
|
|
119
|
+
return true;
|
|
120
|
+
default:
|
|
121
|
+
console.error(`Unknown command ':${command}'. Use :help.`);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function addImport(session, source) {
|
|
126
|
+
const line = source.trim().startsWith("import ") ? source.trim() : `import ${source.trim()}`;
|
|
127
|
+
parse(`${line}\nmain agent { main func(input {}) { return input } }`);
|
|
128
|
+
session.importSources = [...session.importSources.filter((item) => item !== line), line];
|
|
129
|
+
console.log("imported");
|
|
130
|
+
}
|
|
131
|
+
function loadFile(session, file) {
|
|
132
|
+
if (!file) {
|
|
133
|
+
console.error("Usage: :load <file.as>");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const source = readFileSync(file, "utf8");
|
|
137
|
+
session.sourcePath = file;
|
|
138
|
+
const program = parse(source);
|
|
139
|
+
for (const line of source.split(/\r?\n/)) {
|
|
140
|
+
const trimmed = line.trim();
|
|
141
|
+
if (trimmed.startsWith("import ")) {
|
|
142
|
+
session.importSources = [...session.importSources.filter((item) => item !== trimmed), trimmed];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const agentSources = extractAgentSources(source);
|
|
146
|
+
if (agentSources.length !== program.agents.length) {
|
|
147
|
+
throw new Error("Could not split loaded file into agent declarations");
|
|
148
|
+
}
|
|
149
|
+
for (const [index, agent] of program.agents.entries()) {
|
|
150
|
+
if (agent.isMain) {
|
|
151
|
+
for (const [name, existingSource] of session.agentSources) {
|
|
152
|
+
session.agentSources.set(name, existingSource.replace(MAIN_AGENT_PATTERN, "agent"));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
session.agentSources.set(agent.name, agentSources[index]);
|
|
156
|
+
}
|
|
157
|
+
console.log(`loaded ${program.agents.length} agent(s)`);
|
|
158
|
+
}
|
|
159
|
+
function addAgentSource(session, source) {
|
|
160
|
+
if (!AGENT_PATTERN.test(source)) {
|
|
161
|
+
console.error("REPL accepts one complete agent declaration at a time.");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const previousImports = session.importSources.join("\n");
|
|
165
|
+
const programSource = [previousImports, source].filter(Boolean).join("\n\n");
|
|
166
|
+
const program = parse(programSource);
|
|
167
|
+
const agent = program.agents[program.agents.length - 1];
|
|
168
|
+
if (!agent) {
|
|
169
|
+
console.error("No agent found.");
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (agent.isMain) {
|
|
173
|
+
for (const [name, existingSource] of session.agentSources) {
|
|
174
|
+
session.agentSources.set(name, existingSource.replace(MAIN_AGENT_PATTERN, "agent"));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const replaced = session.agentSources.has(agent.name);
|
|
178
|
+
session.agentSources.set(agent.name, source);
|
|
179
|
+
console.log(`${replaced ? "replaced" : "added"} agent ${agent.name}`);
|
|
180
|
+
}
|
|
181
|
+
function setMainAgent(session, name) {
|
|
182
|
+
if (!name) {
|
|
183
|
+
console.error("Usage: :main <AgentName>");
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const source = session.agentSources.get(name);
|
|
187
|
+
if (!source) {
|
|
188
|
+
console.error(`Unknown agent '${name}'`);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
for (const [agentName, agentSource] of session.agentSources) {
|
|
192
|
+
session.agentSources.set(agentName, agentSource.replace(MAIN_AGENT_PATTERN, "agent"));
|
|
193
|
+
}
|
|
194
|
+
session.agentSources.set(name, source.replace(/^\s*agent\b/, "main agent"));
|
|
195
|
+
console.log(`main agent ${name}`);
|
|
196
|
+
}
|
|
197
|
+
function checkSession(session) {
|
|
198
|
+
const program = loadSessionProgram(session);
|
|
199
|
+
const result = analyze(program);
|
|
200
|
+
if (result.diagnostics.length > 0) {
|
|
201
|
+
console.error(formatSemanticDiagnostics(result.diagnostics));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log("ok");
|
|
205
|
+
}
|
|
206
|
+
return !result.diagnostics.some((diagnostic) => diagnostic.severity === "error");
|
|
207
|
+
}
|
|
208
|
+
async function runSession(session, inputJson, reader) {
|
|
209
|
+
const program = loadSessionProgram(session);
|
|
210
|
+
const input = inputJson.trim().length > 0 ? parseJsonObjectInput(inputJson, ":run input") : {};
|
|
211
|
+
const result = await executeAgent(program, input, {
|
|
212
|
+
inputProvider: {
|
|
213
|
+
async read(request) {
|
|
214
|
+
const answer = await reader.question(`${request.path.join(".")}: `);
|
|
215
|
+
return parseInteractiveInputValue(answer);
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
llmProvider: session.realLlm ? new ProtocolLlmProvider() : undefined,
|
|
219
|
+
sourcePath: session.sourcePath
|
|
220
|
+
});
|
|
221
|
+
session.lastTrace = result.trace;
|
|
222
|
+
console.log(JSON.stringify({ value: sanitizeForJson(result.value), trace: result.trace }, null, 2));
|
|
223
|
+
}
|
|
224
|
+
function setRealLlm(session, value) {
|
|
225
|
+
if (value !== "on" && value !== "off") {
|
|
226
|
+
console.error("Usage: :real-llm on|off");
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
session.realLlm = value === "on";
|
|
230
|
+
console.log(`real-llm ${value}`);
|
|
231
|
+
}
|
|
232
|
+
function printAgents(session) {
|
|
233
|
+
if (session.agentSources.size === 0) {
|
|
234
|
+
console.log("(no agents)");
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
for (const [name, source] of session.agentSources) {
|
|
238
|
+
const marker = MAIN_AGENT_PATTERN.test(source) ? "*" : " ";
|
|
239
|
+
console.log(`${marker} ${name}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function printHelp() {
|
|
243
|
+
const lines = [
|
|
244
|
+
":import <import statement>",
|
|
245
|
+
":load <file.as>",
|
|
246
|
+
":agents",
|
|
247
|
+
":main <AgentName>",
|
|
248
|
+
":show",
|
|
249
|
+
":check",
|
|
250
|
+
":parse",
|
|
251
|
+
":run [json]",
|
|
252
|
+
":trace [pretty]",
|
|
253
|
+
":real-llm on|off",
|
|
254
|
+
":reset",
|
|
255
|
+
":exit"
|
|
256
|
+
];
|
|
257
|
+
console.log(`Commands:\n${lines.join("\n")}`);
|
|
258
|
+
}
|
|
259
|
+
function buildProgramSource(session) {
|
|
260
|
+
return [...session.importSources, ...session.agentSources.values()].join("\n\n");
|
|
261
|
+
}
|
|
262
|
+
function loadSessionProgram(session) {
|
|
263
|
+
return loadProgramSource(buildProgramSource(session), { sourcePath: session.sourcePath });
|
|
264
|
+
}
|
|
265
|
+
function extractAgentSources(source) {
|
|
266
|
+
const starts = [...source.matchAll(/^\s*(?:main\s+)?agent\b/gm)].map((match) => match.index ?? 0);
|
|
267
|
+
return starts.map((start, index) => {
|
|
268
|
+
const end = starts[index + 1] ?? source.length;
|
|
269
|
+
return source.slice(start, end).trim();
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function isBalancedAgentBuffer(lines) {
|
|
273
|
+
let depth = 0;
|
|
274
|
+
let sawAgent = false;
|
|
275
|
+
for (const line of lines) {
|
|
276
|
+
if (AGENT_PATTERN.test(line)) {
|
|
277
|
+
sawAgent = true;
|
|
278
|
+
}
|
|
279
|
+
for (const char of line) {
|
|
280
|
+
if (char === "{")
|
|
281
|
+
depth += 1;
|
|
282
|
+
if (char === "}")
|
|
283
|
+
depth -= 1;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return sawAgent && depth === 0;
|
|
287
|
+
}
|
|
288
|
+
function isTty(stream) {
|
|
289
|
+
return "isTTY" in stream && stream.isTTY === true;
|
|
290
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from "./ast/types.js";
|
|
2
|
+
export * from "./ast/constants.js";
|
|
3
|
+
export * from "./ast/format.js";
|
|
4
|
+
export * from "./parser/tokenizer.js";
|
|
5
|
+
export * from "./parser/parser.js";
|
|
6
|
+
export * from "./semantic/analyzer.js";
|
|
7
|
+
export * from "./semantic/diagnostics.js";
|
|
8
|
+
export * from "./runtime/errors.js";
|
|
9
|
+
export * from "./runtime/context.js";
|
|
10
|
+
export * from "./runtime/evaluator.js";
|
|
11
|
+
export * from "./runtime/generate.js";
|
|
12
|
+
export * from "./runtime/guards.js";
|
|
13
|
+
export * from "./runtime/interpreter.js";
|
|
14
|
+
export * from "./runtime/input.js";
|
|
15
|
+
export * from "./runtime/json.js";
|
|
16
|
+
export * from "./runtime/loader.js";
|
|
17
|
+
export * from "./providers/llm/index.js";
|
|
18
|
+
export * from "./providers/memory/index.js";
|
|
19
|
+
export * from "./providers/mock/index.js";
|
|
20
|
+
export * from "./runtime/scope.js";
|
|
21
|
+
export * from "./runtime/shape.js";
|
|
22
|
+
export * from "./providers/tools/index.js";
|
|
23
|
+
export * from "./runtime/trace.js";
|
|
24
|
+
export * from "./runtime/truth.js";
|
|
25
|
+
export * from "./runtime/types.js";
|
|
26
|
+
export * from "./runtime/uri.js";
|