@agentswf/engine 0.1.0-beta.2 → 0.1.0-beta.3
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/package.json +5 -5
- package/src/allowance-command.ts +29 -7
- package/src/attempt-ending.ts +23 -5
- package/src/attempt-output.ts +48 -18
- package/src/attempt-view.ts +25 -15
- package/src/commands.ts +176 -0
- package/src/control-plane.ts +72 -21
- package/src/coordinator-port.ts +29 -0
- package/src/coordinator-prompt.ts +237 -0
- package/src/coordinator-socket.ts +236 -0
- package/src/deadlines.ts +47 -10
- package/src/decisions/directory.ts +8 -6
- package/src/duration.ts +29 -0
- package/src/emit-command.ts +130 -0
- package/src/emit.ts +246 -0
- package/src/files.ts +11 -1
- package/src/here.ts +8 -2
- package/src/hold-run-lock.fixture.ts +8 -0
- package/src/holder-command.ts +297 -0
- package/src/inbox-command.ts +727 -0
- package/src/init-command.ts +27 -0
- package/src/init-template/AGENTS.md.template +1 -1
- package/src/init-template/hello/workflow.test.ts.template +2 -2
- package/src/init-template/hello/workflow.ts.template +16 -20
- package/src/keep-alive.ts +40 -0
- package/src/logs-command.ts +104 -20
- package/src/machine.ts +12 -1
- package/src/mailbox.ts +977 -0
- package/src/message-operation.ts +26 -3
- package/src/messaging/messaging.ts +458 -65
- package/src/messaging/routes.ts +10 -3
- package/src/messaging/text.ts +8 -5
- package/src/operation-liveness.ts +54 -8
- package/src/operator-cli.ts +290 -119
- package/src/operator-runtime.ts +5 -2
- package/src/progress-view.ts +49 -7
- package/src/projects.ts +57 -0
- package/src/result-slots.ts +43 -19
- package/src/result-validation.ts +18 -27
- package/src/run-command.ts +36 -32
- package/src/run-commands.ts +13 -2
- package/src/run-lock.ts +123 -0
- package/src/run-prepare.ts +94 -22
- package/src/run-state.ts +125 -6
- package/src/run-usage.ts +1 -1
- package/src/run-view.ts +0 -9
- package/src/runs-command.ts +46 -17
- package/src/runs.ts +142 -23
- package/src/sandboxes.ts +8 -2
- package/src/simple-input.ts +258 -0
- package/src/socket-exchange.ts +26 -0
- package/src/sources.ts +70 -0
- package/src/stage-ledger.ts +88 -13
- package/src/stage-plan.ts +23 -0
- package/src/stop-crashed.ts +39 -0
- package/src/test-command.ts +32 -0
- package/src/testing.ts +71 -3
- package/src/tick-command.ts +87 -0
- package/src/tools.ts +636 -0
- package/src/wake.ts +264 -0
- package/src/workflow-loader.ts +32 -22
- package/src/workflow-runner.ts +1210 -77
- package/src/workflow-testing/coordinator.typecheck.ts +55 -0
- package/src/workflow-testing/coordinators.ts +137 -0
- package/src/workflow-testing/host.ts +61 -1
- package/src/workflow-testing/index.ts +488 -33
- package/src/workflow-testing/script.ts +72 -2
- package/src/workflow-testing/workflow-testing.typecheck.ts +19 -2
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ParticipantCode,
|
|
3
|
+
ReplyCode,
|
|
4
|
+
SendCode,
|
|
5
|
+
ToolCode,
|
|
6
|
+
ToolFailure,
|
|
7
|
+
} from "@agentswf/contract/wire";
|
|
8
|
+
import type {
|
|
9
|
+
Effort,
|
|
10
|
+
JsonObject,
|
|
11
|
+
JsonValue,
|
|
12
|
+
OperationCause,
|
|
13
|
+
OutputSchema,
|
|
14
|
+
} from "@agentswf/contract/workflow";
|
|
3
15
|
import type Type from "typebox";
|
|
4
16
|
import { canonical } from "../canonical-json";
|
|
5
17
|
import { messageOf } from "../errors";
|
|
@@ -38,10 +50,24 @@ export type Turn = {
|
|
|
38
50
|
send(peer: string, text: string, options?: SendOptions): Promise<MessageOutcome>;
|
|
39
51
|
/** `wf reply`: answers the question `peer` asked. A result is refused while one is owed. */
|
|
40
52
|
reply(peer: string, text: string, options?: SendOptions): Promise<MessageOutcome>;
|
|
53
|
+
/**
|
|
54
|
+
* `wf tool`: calls the agent's tool `name` with `input` as its JSON, or none, through the run's
|
|
55
|
+
* real checks and handler; resolves with what the agent would read.
|
|
56
|
+
*/
|
|
57
|
+
tool(name: string, input?: JsonObject): Promise<ToolOutcome>;
|
|
41
58
|
/** Fires when the engine cancels the turn. */
|
|
42
59
|
signal: AbortSignal;
|
|
43
60
|
};
|
|
44
61
|
|
|
62
|
+
/**
|
|
63
|
+
* How a tool call ended, as `wf tool` reports it; a failure or a refusal is a value to test. A
|
|
64
|
+
* refusal carries what the agent is told, which for `invalid-input` is what it corrects from.
|
|
65
|
+
*/
|
|
66
|
+
export type ToolOutcome =
|
|
67
|
+
| { kind: "result"; output?: string }
|
|
68
|
+
| { kind: "failed"; outcome: ToolFailure; error: string }
|
|
69
|
+
| { kind: "refused"; code: ToolCode; error: string };
|
|
70
|
+
|
|
45
71
|
/** A message as the agent was shown it. */
|
|
46
72
|
export type Message = {
|
|
47
73
|
from: string;
|
|
@@ -70,6 +96,7 @@ export type ReceivedMessage = Message & {
|
|
|
70
96
|
turn: Turn;
|
|
71
97
|
reply(text: string, options?: SendOptions): Promise<MessageOutcome>;
|
|
72
98
|
send(peer: string, text: string, options?: SendOptions): Promise<MessageOutcome>;
|
|
99
|
+
tool(name: string, input?: JsonObject): Promise<ToolOutcome>;
|
|
73
100
|
/** Ends the turn without a reply; one owed is reminded once, then fails. */
|
|
74
101
|
silent(): Reply;
|
|
75
102
|
/** The harness failed: the message operation fails, and the agent stops. */
|
|
@@ -85,6 +112,49 @@ export type MessageScript = (
|
|
|
85
112
|
message: ReceivedMessage,
|
|
86
113
|
) => Reply | MessageOutcome | undefined | Promise<Reply | MessageOutcome | undefined>;
|
|
87
114
|
|
|
115
|
+
/**
|
|
116
|
+
* How a participant's script's `reply` or `send` ended, as `awf reply --json` reports it: a reply's
|
|
117
|
+
* `id` is the question's, a send's the new message's.
|
|
118
|
+
*/
|
|
119
|
+
export type ParticipantOutcome = { code: "delivered"; id: string } | { code: ParticipantCode };
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A message an agent sent a participant, and what the participant's script may do about it, as
|
|
123
|
+
* whoever answers for it would with `awf reply` and `awf send`. An answer is recorded as coming through `test`.
|
|
124
|
+
*/
|
|
125
|
+
export type ParticipantMessage = {
|
|
126
|
+
kind: "message";
|
|
127
|
+
/** `{attempt}.{n}`, as `awf inbox` prints it. */
|
|
128
|
+
id: string;
|
|
129
|
+
/** The agent's peer address. */
|
|
130
|
+
from: string;
|
|
131
|
+
text: string;
|
|
132
|
+
/** A question: it stays open until the script answers it, or it expires. */
|
|
133
|
+
asks?: true;
|
|
134
|
+
/** Answers this question, as `awf reply --to` does. */
|
|
135
|
+
reply(text: string): Promise<ParticipantOutcome>;
|
|
136
|
+
/** Messages an agent over a route the workflow allowed, as `awf send` does. */
|
|
137
|
+
send(agent: string, text: string): Promise<ParticipantOutcome>;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** A route to or from a participant, as it opens: where a script that speaks first starts. */
|
|
141
|
+
export type ParticipantRoute = {
|
|
142
|
+
kind: "route";
|
|
143
|
+
/** The agent's peer address. */
|
|
144
|
+
agent: string;
|
|
145
|
+
direction: "both" | "to-participant" | "from-participant";
|
|
146
|
+
purpose: string;
|
|
147
|
+
/** Messages the agent, as `awf send` does. */
|
|
148
|
+
send(text: string): Promise<ParticipantOutcome>;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* A participant's script: called with each route to it as it opens, and each message an agent sends
|
|
153
|
+
* it, once recorded; the `awf inbox` items whoever answers for it would act on. What it returns is awaited and
|
|
154
|
+
* otherwise ignored: a question it does not answer stays open, and a throw fails the test.
|
|
155
|
+
*/
|
|
156
|
+
export type ParticipantScript = (event: ParticipantRoute | ParticipantMessage) => unknown;
|
|
157
|
+
|
|
88
158
|
const ENTRY: unique symbol = Symbol("agentswf.script-entry");
|
|
89
159
|
|
|
90
160
|
type Respond = (turn: Turn) => JsonValue | Reply | Promise<JsonValue | Reply>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Checked by `tsc --noEmit`, never run: each wrong answer is refused where it is written.
|
|
2
|
-
import type
|
|
2
|
+
import { defineWorkflow, type OutputSchema } from "@agentswf/contract/workflow";
|
|
3
3
|
import Type from "typebox";
|
|
4
|
-
import { answer, reply, type Script } from ".";
|
|
4
|
+
import { answer, reply, type Script, testWorkflow } from ".";
|
|
5
5
|
|
|
6
6
|
const VERDICT = Type.Union([
|
|
7
7
|
Type.Object({ kind: Type.Literal("ready"), summary: Type.String() }),
|
|
@@ -45,3 +45,20 @@ export const invalid: Script[] = [
|
|
|
45
45
|
|
|
46
46
|
// @ts-expect-error raw JSON where a script expects answer(…)
|
|
47
47
|
export const raw: Script = { kind: "ready", summary: "ok" };
|
|
48
|
+
|
|
49
|
+
const withEvents = defineWorkflow({
|
|
50
|
+
meta: { name: "w", description: "w" },
|
|
51
|
+
file: import.meta.path,
|
|
52
|
+
events: { ping: { type: "object" } as OutputSchema<{ n: number }> },
|
|
53
|
+
run: async (workflow) => (await workflow.receive()).length,
|
|
54
|
+
});
|
|
55
|
+
export const tested = () => testWorkflow(withEvents, { id: "k" });
|
|
56
|
+
// @ts-expect-error a workflow with events is tested from { id, event? }, never its args
|
|
57
|
+
export const byArgs = () => testWorkflow(withEvents, null);
|
|
58
|
+
const plain = defineWorkflow({
|
|
59
|
+
meta: { name: "p", description: "p" },
|
|
60
|
+
prepare: ({ argv }) => ({ n: argv.length }),
|
|
61
|
+
run: async (_workflow, args) => args.n,
|
|
62
|
+
});
|
|
63
|
+
// @ts-expect-error a workflow without events is tested from its args, not { id }
|
|
64
|
+
export const byOptions = () => testWorkflow(plain, { id: "k" });
|