@swirls/looms 0.0.2 → 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 +9 -2
- package/dist/actor/cell.d.ts +9 -4
- package/dist/actor/cell.js +7 -11
- package/dist/actor/host.d.ts +7 -3
- package/dist/actor/host.js +55 -32
- package/dist/actor/index.d.ts +1 -1
- package/dist/actor/index.js +1 -1
- package/dist/actor/routing.d.ts +12 -1
- package/dist/actor/routing.js +57 -51
- package/dist/agent/agent-session.d.ts +5 -0
- package/dist/agent/agent-session.js +270 -0
- package/dist/agent/definitions-store.d.ts +2 -3
- package/dist/agent/definitions-store.js +2 -4
- package/dist/agent/definitions.d.ts +46 -20
- package/dist/agent/definitions.js +36 -8
- package/dist/agent/effects.d.ts +359 -2
- package/dist/agent/effects.js +60 -34
- package/dist/agent/events.d.ts +175 -19
- package/dist/agent/events.js +45 -10
- package/dist/agent/index.d.ts +1 -0
- package/dist/agent/index.js +1 -0
- package/dist/agent/llm.d.ts +11 -2
- package/dist/agent/llm.js +13 -3
- package/dist/agent/module.d.ts +812 -78
- package/dist/agent/module.js +16 -4
- package/dist/agent/scope.d.ts +174 -18
- package/dist/agent/signals.d.ts +24 -1
- package/dist/agent/signals.js +77 -0
- package/dist/agent/threads.d.ts +3 -33
- package/dist/agent/threads.js +20 -25
- package/dist/agent/tool-schema.js +0 -1
- package/dist/agent/types.d.ts +49 -4
- package/dist/agent/types.js +5 -5
- package/dist/ai-vercel/index.d.ts +1 -0
- package/dist/ai-vercel/index.js +1 -0
- package/dist/ai-vercel/messages.js +22 -7
- package/dist/ai-vercel/vercel-evaluator.d.ts +23 -0
- package/dist/ai-vercel/vercel-evaluator.js +68 -0
- package/dist/ai-vercel/vercel-llm.js +64 -44
- package/dist/approval/effects.d.ts +89 -0
- package/dist/approval/module.d.ts +179 -29
- package/dist/approval/projections.d.ts +0 -14
- package/dist/approval/projections.js +20 -3
- package/dist/approval/signals.d.ts +2 -0
- package/dist/approval/signals.js +18 -2
- package/dist/cli/cli.js +2 -0
- package/dist/cli/commands.js +12 -16
- package/dist/client/client.d.ts +1195 -18
- package/dist/client/client.js +118 -120
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/sse.d.ts +13 -0
- package/dist/client/sse.js +38 -44
- package/dist/cloudflare/alarm-scheduler.d.ts +12 -2
- package/dist/cloudflare/alarm-scheduler.js +34 -7
- package/dist/cloudflare/durable-object.d.ts +10 -2
- package/dist/cloudflare/durable-object.js +59 -28
- package/dist/cloudflare/event-store.d.ts +7 -2
- package/dist/cloudflare/event-store.js +8 -7
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/cloudflare/router.js +13 -14
- package/dist/core/catalog.d.ts +3 -3
- package/dist/core/catalog.js +2 -5
- package/dist/core/coalesce.js +5 -3
- package/dist/core/compose.d.ts +2 -1
- package/dist/core/compose.js +18 -2
- package/dist/core/definition-store.d.ts +11 -0
- package/dist/core/definition-store.js +6 -0
- package/dist/core/effects.d.ts +127 -15
- package/dist/core/effects.js +89 -17
- package/dist/core/envelope.d.ts +27 -7
- package/dist/core/envelope.js +20 -6
- package/dist/core/event-codec.d.ts +4 -2
- package/dist/core/event-codec.js +10 -5
- package/dist/core/event-index.js +1 -3
- package/dist/core/fold.d.ts +3 -0
- package/dist/core/fold.js +171 -24
- package/dist/core/ids.d.ts +5 -0
- package/dist/core/ids.js +35 -2
- package/dist/core/index.d.ts +5 -1
- package/dist/core/index.js +5 -1
- package/dist/core/kind.d.ts +22 -0
- package/dist/core/kind.js +17 -0
- package/dist/core/limits.d.ts +34 -0
- package/dist/core/limits.js +46 -0
- package/dist/core/match.d.ts +1 -0
- package/dist/core/match.js +10 -1
- package/dist/core/module-scope.d.ts +22 -20
- package/dist/core/module-scope.js +38 -28
- package/dist/core/module.d.ts +16 -5
- package/dist/core/module.js +4 -0
- package/dist/core/projection.d.ts +13 -13
- package/dist/core/projection.js +9 -5
- package/dist/core/protocol.d.ts +68 -11
- package/dist/core/protocol.js +82 -11
- package/dist/core/replay.d.ts +312 -3
- package/dist/core/replay.js +11 -1
- package/dist/core/schema.d.ts +8 -19
- package/dist/core/schema.js +25 -80
- package/dist/core/serialize.js +2 -4
- package/dist/core/snapshot-store.d.ts +2 -1
- package/dist/core/snapshot-store.js +8 -2
- package/dist/core/snapshots.d.ts +5 -1
- package/dist/core/snapshots.js +10 -15
- package/dist/core/sqlite-store.js +56 -11
- package/dist/core/state.d.ts +142 -4
- package/dist/core/state.js +78 -0
- package/dist/core/store.d.ts +38 -3
- package/dist/core/store.js +77 -22
- package/dist/core/thread.d.ts +10 -9
- package/dist/core/types.d.ts +5 -8
- package/dist/core/types.js +28 -24
- package/dist/core/validate-event.js +14 -4
- package/dist/core/worker-callback.d.ts +17 -0
- package/dist/core/worker-callback.js +1 -0
- package/dist/debugger/components/event-stream.js +9 -10
- package/dist/debugger/events/protocol-summarize.js +26 -0
- package/dist/debugger/lib/event-meta.js +1 -2
- package/dist/evaluator/definitions-store.d.ts +11 -0
- package/dist/evaluator/definitions-store.js +8 -0
- package/dist/evaluator/definitions.d.ts +18 -0
- package/dist/evaluator/definitions.js +4 -0
- package/dist/evaluator/effects.d.ts +226 -0
- package/dist/evaluator/effects.js +132 -0
- package/dist/evaluator/evaluator.d.ts +24 -0
- package/dist/evaluator/evaluator.js +67 -0
- package/dist/evaluator/events.d.ts +59 -0
- package/dist/evaluator/events.js +21 -0
- package/dist/evaluator/index.d.ts +11 -0
- package/dist/evaluator/index.js +11 -0
- package/dist/evaluator/module.d.ts +606 -0
- package/dist/evaluator/module.js +25 -0
- package/dist/evaluator/projections.d.ts +50 -0
- package/dist/evaluator/projections.js +20 -0
- package/dist/evaluator/scope.d.ts +59 -0
- package/dist/evaluator/scope.js +7 -0
- package/dist/evaluator/signals.d.ts +3 -0
- package/dist/evaluator/signals.js +17 -0
- package/dist/evaluator/threads.d.ts +62 -0
- package/dist/evaluator/threads.js +117 -0
- package/dist/evaluator/types.d.ts +125 -0
- package/dist/evaluator/types.js +51 -0
- package/dist/projectors/delivery.d.ts +83 -0
- package/dist/projectors/delivery.js +182 -0
- package/dist/projectors/index-model.d.ts +1 -1
- package/dist/projectors/index-model.js +4 -6
- package/dist/projectors/index.d.ts +2 -0
- package/dist/projectors/index.js +2 -0
- package/dist/projectors/memory.d.ts +1 -1
- package/dist/projectors/memory.js +10 -8
- package/dist/projectors/postgres.js +44 -58
- package/dist/projectors/projector.d.ts +17 -0
- package/dist/projectors/projector.js +26 -1
- package/dist/projectors/sqlite-delivery.d.ts +4 -0
- package/dist/projectors/sqlite-delivery.js +147 -0
- package/dist/projectors/sqlite.js +23 -23
- package/dist/projectors/with-projectors.d.ts +7 -2
- package/dist/projectors/with-projectors.js +27 -28
- package/dist/react/notify.js +11 -8
- package/dist/react/react.d.ts +2 -3
- package/dist/react/react.js +14 -30
- package/dist/react/sse.d.ts +1 -1
- package/dist/react/sse.js +1 -1
- package/dist/react/store.d.ts +2 -2
- package/dist/react/store.js +109 -119
- package/dist/runtime/cancellation.d.ts +16 -0
- package/dist/runtime/cancellation.js +129 -0
- package/dist/runtime/deadline-transition-planner.d.ts +31 -0
- package/dist/runtime/deadline-transition-planner.js +139 -0
- package/dist/runtime/dispatch-effect.d.ts +3 -2
- package/dist/runtime/dispatch-effect.js +7 -13
- package/dist/runtime/errors.d.ts +51 -0
- package/dist/runtime/errors.js +39 -0
- package/dist/runtime/{runtime-helpers.d.ts → helpers.d.ts} +24 -4
- package/dist/runtime/{runtime-helpers.js → helpers.js} +56 -19
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +3 -3
- package/dist/runtime/ingress.d.ts +15 -0
- package/dist/runtime/ingress.js +42 -0
- package/dist/runtime/local-effect-executor.d.ts +21 -0
- package/dist/runtime/local-effect-executor.js +137 -0
- package/dist/runtime/looms.d.ts +22 -4
- package/dist/runtime/looms.js +54 -36
- package/dist/runtime/observer.d.ts +45 -0
- package/dist/runtime/observer.js +11 -0
- package/dist/runtime/repository.d.ts +55 -0
- package/dist/runtime/repository.js +278 -0
- package/dist/runtime/retry-policy.d.ts +16 -0
- package/dist/runtime/retry-policy.js +29 -0
- package/dist/runtime/run-execution-context.d.ts +30 -0
- package/dist/runtime/run-execution-context.js +56 -0
- package/dist/runtime/run-start.d.ts +4 -0
- package/dist/runtime/run-start.js +44 -0
- package/dist/runtime/runtime.d.ts +6 -87
- package/dist/runtime/runtime.js +233 -470
- package/dist/runtime/server/auth.d.ts +40 -0
- package/dist/runtime/server/auth.js +40 -0
- package/dist/runtime/server/fetch-handler.d.ts +14 -0
- package/dist/runtime/server/fetch-handler.js +51 -0
- package/dist/runtime/server/http.d.ts +37 -0
- package/dist/runtime/server/http.js +62 -0
- package/dist/runtime/server/route-table.d.ts +55 -0
- package/dist/runtime/server/route-table.js +74 -0
- package/dist/runtime/server/routes/effects.d.ts +3 -0
- package/dist/runtime/server/routes/effects.js +59 -0
- package/dist/runtime/server/routes/operations.d.ts +3 -0
- package/dist/runtime/server/routes/operations.js +14 -0
- package/dist/runtime/server/routes/runs.d.ts +3 -0
- package/dist/runtime/server/routes/runs.js +192 -0
- package/dist/runtime/server.d.ts +2 -8
- package/dist/runtime/server.js +4 -211
- package/dist/runtime/sse.d.ts +2 -1
- package/dist/runtime/sse.js +24 -17
- package/dist/runtime/types.d.ts +115 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/wake-engine.d.ts +20 -0
- package/dist/runtime/wake-engine.js +311 -0
- package/dist/runtime/wake-scheduler.d.ts +3 -4
- package/dist/runtime/wake-scheduler.js +25 -31
- package/dist/runtime/worker-callbacks.d.ts +16 -0
- package/dist/runtime/worker-callbacks.js +167 -0
- package/dist/runtime/worker-effect-dispatch.d.ts +36 -0
- package/dist/runtime/worker-effect-dispatch.js +126 -0
- package/dist/s2/config.d.ts +1 -1
- package/dist/s2/config.js +1 -1
- package/dist/s2/lite.js +70 -82
- package/dist/s2/pagination.d.ts +15 -0
- package/dist/s2/pagination.js +36 -0
- package/dist/s2/projector.js +6 -5
- package/dist/s2/snapshot-store.js +148 -163
- package/dist/s2/store.d.ts +3 -21
- package/dist/s2/store.js +71 -165
- package/dist/testing/index.d.ts +15 -0
- package/dist/testing/index.js +53 -16
- package/dist/workflow/definitions-store.d.ts +2 -3
- package/dist/workflow/definitions-store.js +2 -2
- package/dist/workflow/definitions.d.ts +78 -22
- package/dist/workflow/definitions.js +80 -14
- package/dist/workflow/effects.d.ts +453 -107
- package/dist/workflow/effects.js +214 -115
- package/dist/workflow/events.d.ts +149 -5
- package/dist/workflow/events.js +27 -5
- package/dist/workflow/graph.d.ts +56 -0
- package/dist/workflow/graph.js +207 -0
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.js +1 -0
- package/dist/workflow/module.d.ts +1047 -266
- package/dist/workflow/projections.d.ts +14 -12
- package/dist/workflow/projections.js +30 -8
- package/dist/workflow/scope.d.ts +146 -4
- package/dist/workflow/threads.d.ts +383 -155
- package/dist/workflow/threads.js +308 -110
- package/package.json +7 -2
- package/dist/runtime/events-api.d.ts +0 -4
- package/dist/runtime/events-api.js +0 -84
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { Predicate } from 'effect';
|
|
2
|
+
import { cancel, createWaitId, deterministicThreadId, emit, spawn, wait, } from '@swirls/looms/core';
|
|
3
|
+
import { agentModule } from './scope.js';
|
|
4
|
+
function objectPayload(event) {
|
|
5
|
+
return Predicate.isObject(event.payload) ? event.payload : {};
|
|
6
|
+
}
|
|
7
|
+
function messageFrom(value) {
|
|
8
|
+
const payload = Predicate.isObject(value) ? value : {};
|
|
9
|
+
return Predicate.isString(payload.messageId) && Predicate.isString(payload.text)
|
|
10
|
+
? {
|
|
11
|
+
messageId: payload.messageId,
|
|
12
|
+
text: payload.text,
|
|
13
|
+
delivery: payload.delivery === 'steer' ||
|
|
14
|
+
payload.delivery === 'followUp' ||
|
|
15
|
+
payload.delivery === 'nextTurn'
|
|
16
|
+
? payload.delivery
|
|
17
|
+
: undefined,
|
|
18
|
+
}
|
|
19
|
+
: null;
|
|
20
|
+
}
|
|
21
|
+
function consumedIds(event) {
|
|
22
|
+
const payload = objectPayload(event);
|
|
23
|
+
const embedded = Predicate.isObject(payload.event) ? payload.event : {};
|
|
24
|
+
const embeddedPayload = Predicate.isObject(embedded.payload) ? embedded.payload : {};
|
|
25
|
+
const output = Predicate.isObject(embeddedPayload.output) ? embeddedPayload.output : {};
|
|
26
|
+
const ids = output.consumedSteerMessageIds;
|
|
27
|
+
return Array.isArray(ids) ? ids.filter(Predicate.isString) : [];
|
|
28
|
+
}
|
|
29
|
+
function closureStatus(event) {
|
|
30
|
+
const payload = objectPayload(event);
|
|
31
|
+
const embedded = Predicate.isObject(payload.event) ? payload.event : {};
|
|
32
|
+
const embeddedPayload = Predicate.isObject(embedded.payload) ? embedded.payload : {};
|
|
33
|
+
const status = embedded.type === 'runtime.thread.completed'
|
|
34
|
+
? 'completed'
|
|
35
|
+
: embedded.type === 'runtime.thread.cancelled'
|
|
36
|
+
? 'cancelled'
|
|
37
|
+
: 'failed';
|
|
38
|
+
const error = Predicate.isString(embeddedPayload.error) ? embeddedPayload.error : undefined;
|
|
39
|
+
return { status, error };
|
|
40
|
+
}
|
|
41
|
+
function close(messageId, status, error) {
|
|
42
|
+
return error === undefined ? { messageId, status } : { messageId, status, error };
|
|
43
|
+
}
|
|
44
|
+
export function createAgentSessionThread(definitions) {
|
|
45
|
+
return agentModule.thread({
|
|
46
|
+
kind: 'agent-session',
|
|
47
|
+
initialState: (ctx) => {
|
|
48
|
+
const definition = definitions.get(ctx.definitionName, ctx.definitionVersion);
|
|
49
|
+
return {
|
|
50
|
+
definitionName: ctx.definitionName,
|
|
51
|
+
definitionVersion: ctx.definitionVersion,
|
|
52
|
+
pendingMessages: [],
|
|
53
|
+
nextTurnMessages: [],
|
|
54
|
+
processedMessageIds: [],
|
|
55
|
+
activeTurn: null,
|
|
56
|
+
pendingSteerDeliveries: [],
|
|
57
|
+
pendingClosures: [],
|
|
58
|
+
lastSequence: 0,
|
|
59
|
+
idleTimeoutMs: definition?.idleTimeoutMs ?? 0,
|
|
60
|
+
idleDeadlineAt: null,
|
|
61
|
+
parked: false,
|
|
62
|
+
cancelling: false,
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
step(state, event) {
|
|
66
|
+
switch (event.type) {
|
|
67
|
+
case 'runtime.thread.started': {
|
|
68
|
+
const initial = messageFrom(objectPayload(event).input);
|
|
69
|
+
const idleDeadlineAt = state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null;
|
|
70
|
+
if (!initial || state.processedMessageIds.includes(initial.messageId)) {
|
|
71
|
+
return { ...state, idleDeadlineAt };
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
...state,
|
|
75
|
+
pendingMessages: [initial],
|
|
76
|
+
processedMessageIds: [initial.messageId],
|
|
77
|
+
idleDeadlineAt,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case 'agent.session.message.submitted': {
|
|
81
|
+
const payload = objectPayload(event);
|
|
82
|
+
const message = messageFrom(payload);
|
|
83
|
+
if (!message || state.processedMessageIds.includes(message.messageId)) {
|
|
84
|
+
return state;
|
|
85
|
+
}
|
|
86
|
+
const processedMessageIds = [...state.processedMessageIds, message.messageId];
|
|
87
|
+
const idleDeadlineAt = state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null;
|
|
88
|
+
if (message.delivery === 'nextTurn') {
|
|
89
|
+
return {
|
|
90
|
+
...state,
|
|
91
|
+
nextTurnMessages: [...state.nextTurnMessages, message],
|
|
92
|
+
processedMessageIds,
|
|
93
|
+
idleDeadlineAt,
|
|
94
|
+
parked: false,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const queued = message.delivery === 'steer' && state.activeTurn
|
|
98
|
+
? { ...message, steeredIntoMessageId: state.activeTurn.messageId }
|
|
99
|
+
: message;
|
|
100
|
+
return {
|
|
101
|
+
...state,
|
|
102
|
+
pendingMessages: [...state.pendingMessages, queued],
|
|
103
|
+
pendingSteerDeliveries: queued.steeredIntoMessageId &&
|
|
104
|
+
state.activeTurn &&
|
|
105
|
+
payload.activeChildThreadId !== state.activeTurn.childThreadId
|
|
106
|
+
? [...state.pendingSteerDeliveries, queued]
|
|
107
|
+
: state.pendingSteerDeliveries,
|
|
108
|
+
processedMessageIds,
|
|
109
|
+
idleDeadlineAt,
|
|
110
|
+
parked: false,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
case 'agent.session.turn.started': {
|
|
114
|
+
const messageId = event.payload.messageId;
|
|
115
|
+
const admitted = state.pendingMessages.find((message) => message.messageId === messageId);
|
|
116
|
+
const text = [...state.nextTurnMessages, ...(admitted ? [admitted] : [])]
|
|
117
|
+
.map((message) => message.text)
|
|
118
|
+
.join('\n');
|
|
119
|
+
return {
|
|
120
|
+
...state,
|
|
121
|
+
pendingMessages: state.pendingMessages.filter((message) => message.messageId !== messageId),
|
|
122
|
+
activeTurn: {
|
|
123
|
+
messageId,
|
|
124
|
+
childThreadId: event.payload.childThreadId,
|
|
125
|
+
text,
|
|
126
|
+
},
|
|
127
|
+
nextTurnMessages: [],
|
|
128
|
+
lastSequence: state.lastSequence + 1,
|
|
129
|
+
cancelling: false,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
case 'agent.session.steer.delivered':
|
|
133
|
+
return {
|
|
134
|
+
...state,
|
|
135
|
+
pendingSteerDeliveries: state.pendingSteerDeliveries.filter((message) => message.messageId !== event.payload.messageId),
|
|
136
|
+
};
|
|
137
|
+
case 'agent.session.turn.closed':
|
|
138
|
+
return {
|
|
139
|
+
...state,
|
|
140
|
+
pendingClosures: state.pendingClosures.filter((closure) => closure.messageId !== event.payload.messageId),
|
|
141
|
+
};
|
|
142
|
+
case 'agent.session.cancel.requested':
|
|
143
|
+
case 'runtime.thread.cancel.requested':
|
|
144
|
+
return state.activeTurn ? { ...state, cancelling: true } : state;
|
|
145
|
+
case 'runtime.wait.satisfied': {
|
|
146
|
+
const payload = objectPayload(event);
|
|
147
|
+
const tag = Predicate.isObject(payload.tag) ? payload.tag : {};
|
|
148
|
+
if (tag.kind === 'agent-session-idle') {
|
|
149
|
+
if (tag.deadlineAt === state.idleDeadlineAt && state.activeTurn === null) {
|
|
150
|
+
return { ...state, parked: true, idleDeadlineAt: null };
|
|
151
|
+
}
|
|
152
|
+
return state;
|
|
153
|
+
}
|
|
154
|
+
if (tag.kind !== 'agent-session-turn' || !state.activeTurn) {
|
|
155
|
+
return state;
|
|
156
|
+
}
|
|
157
|
+
const active = state.activeTurn;
|
|
158
|
+
const consumed = new Set(consumedIds(event));
|
|
159
|
+
const result = closureStatus(event);
|
|
160
|
+
const pendingClosures = [
|
|
161
|
+
...state.pendingClosures,
|
|
162
|
+
close(active.messageId, result.status, result.error),
|
|
163
|
+
...[...consumed].map((messageId) => close(messageId, result.status, result.error)),
|
|
164
|
+
];
|
|
165
|
+
return {
|
|
166
|
+
...state,
|
|
167
|
+
pendingMessages: state.pendingMessages.flatMap((message) => {
|
|
168
|
+
if (consumed.has(message.messageId)) {
|
|
169
|
+
return [];
|
|
170
|
+
}
|
|
171
|
+
return message.steeredIntoMessageId === active.messageId
|
|
172
|
+
? [{ ...message, steeredIntoMessageId: undefined }]
|
|
173
|
+
: [message];
|
|
174
|
+
}),
|
|
175
|
+
pendingSteerDeliveries: state.pendingSteerDeliveries.filter((message) => !consumed.has(message.messageId) &&
|
|
176
|
+
message.steeredIntoMessageId !== active.messageId),
|
|
177
|
+
pendingClosures,
|
|
178
|
+
activeTurn: null,
|
|
179
|
+
lastSequence: state.lastSequence + 1,
|
|
180
|
+
cancelling: false,
|
|
181
|
+
idleDeadlineAt: state.idleTimeoutMs > 0 ? event.ts + state.idleTimeoutMs : null,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
default:
|
|
185
|
+
return state;
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
effects(state, ctx) {
|
|
189
|
+
const effects = [];
|
|
190
|
+
for (const closure of state.pendingClosures) {
|
|
191
|
+
effects.push(emit(agentModule.input('session.turn.closed', { messageId: closure.messageId, status: closure.status, error: closure.error }, { threadId: ctx.threadId }), `session_close_${closure.messageId}`));
|
|
192
|
+
}
|
|
193
|
+
for (const message of state.pendingSteerDeliveries) {
|
|
194
|
+
if (!state.activeTurn || message.steeredIntoMessageId !== state.activeTurn.messageId) {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
effects.push(emit(agentModule.input('steered', {
|
|
198
|
+
turn: 0,
|
|
199
|
+
messageId: message.messageId,
|
|
200
|
+
message: { role: 'user', content: message.text },
|
|
201
|
+
interrupt: true,
|
|
202
|
+
}, { threadId: state.activeTurn.childThreadId }), `session_steer_${message.messageId}`), emit(agentModule.input('session.steer.delivered', { messageId: message.messageId, activeMessageId: state.activeTurn.messageId }, { threadId: ctx.threadId }), `session_steer_delivered_${message.messageId}`));
|
|
203
|
+
}
|
|
204
|
+
if (state.activeTurn) {
|
|
205
|
+
const { childThreadId: turnThreadId, messageId, text } = state.activeTurn;
|
|
206
|
+
const definition = definitions.get(state.definitionName, state.definitionVersion);
|
|
207
|
+
if (state.cancelling) {
|
|
208
|
+
effects.push(cancel(turnThreadId));
|
|
209
|
+
}
|
|
210
|
+
else if (definition) {
|
|
211
|
+
effects.push(spawn({
|
|
212
|
+
childThreadId: turnThreadId,
|
|
213
|
+
kind: 'agent',
|
|
214
|
+
definitionName: definition.agent.name,
|
|
215
|
+
definitionVersion: definition.agent.version,
|
|
216
|
+
input: { text },
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
// The turn wait must survive cancellation: the child's cancelled event is what closes it.
|
|
220
|
+
effects.push(wait({
|
|
221
|
+
waitId: createWaitId(ctx.threadId, `turn_${messageId}`),
|
|
222
|
+
on: {
|
|
223
|
+
type: [
|
|
224
|
+
'runtime.thread.completed',
|
|
225
|
+
'runtime.thread.failed',
|
|
226
|
+
'runtime.thread.cancelled',
|
|
227
|
+
],
|
|
228
|
+
match: { threadId: turnThreadId },
|
|
229
|
+
},
|
|
230
|
+
tag: { kind: 'agent-session-turn', messageId },
|
|
231
|
+
}));
|
|
232
|
+
return effects;
|
|
233
|
+
}
|
|
234
|
+
const next = state.pendingMessages.find((message) => message.steeredIntoMessageId === undefined);
|
|
235
|
+
if (next) {
|
|
236
|
+
effects.push(emit(agentModule.input('session.turn.started', {
|
|
237
|
+
messageId: next.messageId,
|
|
238
|
+
childThreadId: deterministicThreadId(ctx.threadId, 'turn', next.messageId),
|
|
239
|
+
}, { threadId: ctx.threadId }), `session_admit_${next.messageId}`));
|
|
240
|
+
return effects;
|
|
241
|
+
}
|
|
242
|
+
if (state.parked || state.idleTimeoutMs === 0 || state.idleDeadlineAt === null) {
|
|
243
|
+
effects.push(wait({
|
|
244
|
+
waitId: createWaitId(ctx.threadId, 'mailbox'),
|
|
245
|
+
on: { type: 'agent.session.message.submitted', match: { threadId: ctx.threadId } },
|
|
246
|
+
tag: { kind: 'agent-session-mailbox' },
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
effects.push(wait({
|
|
251
|
+
waitId: createWaitId(ctx.threadId, `idle_${state.idleDeadlineAt}`),
|
|
252
|
+
on: { timerAt: state.idleDeadlineAt },
|
|
253
|
+
tag: { kind: 'agent-session-idle', deadlineAt: state.idleDeadlineAt },
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
256
|
+
return effects;
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
export function agentSessionSnapshot(state) {
|
|
261
|
+
return {
|
|
262
|
+
activeTurnId: state.activeTurn?.messageId ?? null,
|
|
263
|
+
activeChildThreadId: state.activeTurn?.childThreadId ?? null,
|
|
264
|
+
pendingMessageCount: state.pendingMessages.length,
|
|
265
|
+
nextTurnHeldCount: state.nextTurnMessages.length,
|
|
266
|
+
processedMessageIds: state.processedMessageIds,
|
|
267
|
+
lastSequence: state.lastSequence,
|
|
268
|
+
parked: state.parked,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Context, Layer } from 'effect';
|
|
2
|
+
import { type DefinitionStore } from '@swirls/looms/core';
|
|
2
3
|
import type { AgentDefinition } from './definitions';
|
|
3
|
-
export
|
|
4
|
-
get(name: string): AgentDefinition | undefined;
|
|
5
|
-
}
|
|
4
|
+
export type AgentDefinitionStore = DefinitionStore<AgentDefinition>;
|
|
6
5
|
declare const AgentDefinitionsTag_base: Context.ServiceClass<AgentDefinitionsTag, "looms/AgentDefinitions", AgentDefinitionStore>;
|
|
7
6
|
export declare class AgentDefinitionsTag extends AgentDefinitionsTag_base {
|
|
8
7
|
}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { Context, Layer } from 'effect';
|
|
2
|
+
import { makeDefinitionStore } from '@swirls/looms/core';
|
|
2
3
|
export class AgentDefinitionsTag extends Context.Service()('looms/AgentDefinitions') {
|
|
3
4
|
}
|
|
4
5
|
export function makeAgentDefinitionStore(definitions) {
|
|
5
|
-
|
|
6
|
-
return {
|
|
7
|
-
get: (name) => map.get(name),
|
|
8
|
-
};
|
|
6
|
+
return makeDefinitionStore('agent', definitions);
|
|
9
7
|
}
|
|
10
8
|
export const AgentDefinitionsLive = (definitions) => Layer.succeed(AgentDefinitionsTag, makeAgentDefinitionStore(definitions));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
2
|
import type { Schema } from 'effect';
|
|
3
|
-
import
|
|
3
|
+
import { type JsonValue, type RuntimeEffect, type SchemaInput } from '@swirls/looms/core';
|
|
4
4
|
import type { StopWhen } from './stop-when';
|
|
5
5
|
import type { Message, ToolCall } from './types';
|
|
6
6
|
export interface ToolContext {
|
|
@@ -12,7 +12,7 @@ export interface FunctionTool<TName extends string = string, TInput = JsonValue,
|
|
|
12
12
|
readonly kind: 'function';
|
|
13
13
|
readonly name: TName;
|
|
14
14
|
readonly description: string;
|
|
15
|
-
readonly input?: StandardSchemaV1<any, TInput> | Schema.
|
|
15
|
+
readonly input?: StandardSchemaV1<any, TInput> | Schema.ConstraintDecoder<TInput>;
|
|
16
16
|
readonly inputSchema?: JsonValue;
|
|
17
17
|
handler(input: TInput, ctx: ToolContext): Promise<TOutput> | TOutput;
|
|
18
18
|
}
|
|
@@ -24,9 +24,11 @@ export interface ThreadTool {
|
|
|
24
24
|
readonly inputSchema?: JsonValue;
|
|
25
25
|
readonly childKind: string;
|
|
26
26
|
readonly childName: string;
|
|
27
|
+
readonly childVersion: string;
|
|
27
28
|
readonly child: {
|
|
28
29
|
kind: string;
|
|
29
30
|
name: string;
|
|
31
|
+
version?: string;
|
|
30
32
|
};
|
|
31
33
|
mapInput?(input: JsonValue): JsonValue;
|
|
32
34
|
}
|
|
@@ -46,6 +48,7 @@ export type ToolLike = FunctionTool | ThreadTool | EffectsTool;
|
|
|
46
48
|
export type AgentToolEntry = ToolLike | {
|
|
47
49
|
kind: string;
|
|
48
50
|
name: string;
|
|
51
|
+
version?: string;
|
|
49
52
|
instructions?: string;
|
|
50
53
|
description?: string;
|
|
51
54
|
input?: SchemaInput;
|
|
@@ -57,6 +60,7 @@ export interface AgentTurnContext<TInput = JsonValue> {
|
|
|
57
60
|
readonly input: TInput;
|
|
58
61
|
readonly tools: ToolLike[];
|
|
59
62
|
readonly instructions: string;
|
|
63
|
+
readonly signal?: AbortSignal;
|
|
60
64
|
}
|
|
61
65
|
export interface AgentTurnResult<TOutput extends JsonValue = JsonValue> {
|
|
62
66
|
message: Message;
|
|
@@ -71,9 +75,10 @@ export interface AgentTurnResult<TOutput extends JsonValue = JsonValue> {
|
|
|
71
75
|
export interface AgentDefinition<TName extends string = string, TInput = JsonValue, TOutput extends JsonValue = JsonValue> {
|
|
72
76
|
readonly kind: 'agent';
|
|
73
77
|
readonly name: TName;
|
|
78
|
+
readonly version: string;
|
|
74
79
|
readonly model?: string;
|
|
75
80
|
readonly instructions: string;
|
|
76
|
-
readonly input?: StandardSchemaV1<any, TInput> | Schema.
|
|
81
|
+
readonly input?: StandardSchemaV1<any, TInput> | Schema.ConstraintDecoder<TInput>;
|
|
77
82
|
readonly tools?: ToolLike[];
|
|
78
83
|
readonly maxTurns?: number;
|
|
79
84
|
readonly conversational?: boolean;
|
|
@@ -81,24 +86,26 @@ export interface AgentDefinition<TName extends string = string, TInput = JsonVal
|
|
|
81
86
|
runTurn?(ctx: AgentTurnContext<TInput>): Promise<AgentTurnResult<TOutput>> | AgentTurnResult<TOutput>;
|
|
82
87
|
}
|
|
83
88
|
export type AnyAgentDefinition = AgentDefinition;
|
|
89
|
+
export interface AgentSessionDefinition<TName extends string = string> {
|
|
90
|
+
readonly kind: 'agent-session';
|
|
91
|
+
readonly name: TName;
|
|
92
|
+
readonly version: string;
|
|
93
|
+
/** The agent definition is pinned when the session definition is created. */
|
|
94
|
+
readonly agent: Pick<AgentDefinition, 'kind' | 'name' | 'version'>;
|
|
95
|
+
/** Max idle milliseconds before parking. Zero waits indefinitely. */
|
|
96
|
+
readonly idleTimeoutMs: number;
|
|
97
|
+
}
|
|
98
|
+
export declare function defineAgentSession<TName extends string>(def: {
|
|
99
|
+
readonly name: TName;
|
|
100
|
+
readonly agent: Pick<AgentDefinition, 'kind' | 'name' | 'version'>;
|
|
101
|
+
readonly version?: string;
|
|
102
|
+
readonly idleTimeoutMs?: number;
|
|
103
|
+
}): AgentSessionDefinition<TName>;
|
|
84
104
|
export declare function normalizeTools(tools?: ReadonlyArray<AgentToolEntry>): ToolLike[];
|
|
85
|
-
export declare function defineTool<TName extends string,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
inputSchema?: JsonValue;
|
|
90
|
-
handler: (input: TInput, ctx: ToolContext) => Promise<TOutput> | TOutput;
|
|
91
|
-
}): FunctionTool<TName, TInput, TOutput>;
|
|
92
|
-
export declare function defineAgent<TName extends string, TSchema = undefined, TInput = InferDefinedSchema<TSchema>, TOutput extends JsonValue = JsonValue>(def: {
|
|
93
|
-
name: TName;
|
|
94
|
-
model?: string;
|
|
95
|
-
instructions: string;
|
|
96
|
-
input?: TSchema;
|
|
97
|
-
tools?: AgentToolEntry[];
|
|
98
|
-
maxTurns?: number;
|
|
99
|
-
conversational?: boolean;
|
|
100
|
-
stopWhen?: StopWhen;
|
|
101
|
-
runTurn?: (ctx: AgentTurnContext<TInput>) => Promise<AgentTurnResult<TOutput>> | AgentTurnResult<TOutput>;
|
|
105
|
+
export declare function defineTool<TName extends string, TInput = JsonValue, TOutput extends JsonValue = JsonValue>(def: Omit<FunctionTool<TName, TInput, TOutput>, 'kind'>): FunctionTool<TName, TInput, TOutput>;
|
|
106
|
+
export declare function defineAgent<TName extends string, TInput = JsonValue, TOutput extends JsonValue = JsonValue>(def: Omit<AgentDefinition<TName, TInput, TOutput>, 'kind' | 'version' | 'tools'> & {
|
|
107
|
+
readonly version?: string;
|
|
108
|
+
readonly tools?: AgentToolEntry[];
|
|
102
109
|
}): AgentDefinition<TName, TInput, TOutput>;
|
|
103
110
|
export declare function asThreadTool(def: {
|
|
104
111
|
name?: string;
|
|
@@ -108,6 +115,7 @@ export declare function asThreadTool(def: {
|
|
|
108
115
|
child: {
|
|
109
116
|
kind: string;
|
|
110
117
|
name: string;
|
|
118
|
+
version?: string;
|
|
111
119
|
};
|
|
112
120
|
mapInput?: (input: JsonValue) => JsonValue;
|
|
113
121
|
}): ThreadTool;
|
|
@@ -119,12 +127,28 @@ export declare function asAgentTool(def: {
|
|
|
119
127
|
agent: {
|
|
120
128
|
kind: 'agent';
|
|
121
129
|
name: string;
|
|
130
|
+
version?: string;
|
|
122
131
|
instructions?: string;
|
|
123
132
|
input?: SchemaInput;
|
|
124
133
|
inputSchema?: JsonValue;
|
|
125
134
|
};
|
|
126
135
|
mapInput?: (input: JsonValue) => JsonValue;
|
|
127
136
|
}): ThreadTool;
|
|
137
|
+
type EvaluatorToolTarget = {
|
|
138
|
+
kind: 'evaluator';
|
|
139
|
+
name: string;
|
|
140
|
+
description?: string;
|
|
141
|
+
input?: SchemaInput;
|
|
142
|
+
inputSchema?: JsonValue;
|
|
143
|
+
};
|
|
144
|
+
export declare function asEvaluatorTool(def: {
|
|
145
|
+
name?: string;
|
|
146
|
+
description?: string;
|
|
147
|
+
input?: SchemaInput;
|
|
148
|
+
inputSchema?: JsonValue;
|
|
149
|
+
evaluator: EvaluatorToolTarget;
|
|
150
|
+
mapInput?: (input: JsonValue) => JsonValue;
|
|
151
|
+
}): ThreadTool;
|
|
128
152
|
export declare function asWorkflowTool(def: {
|
|
129
153
|
name?: string;
|
|
130
154
|
description?: string;
|
|
@@ -133,6 +157,7 @@ export declare function asWorkflowTool(def: {
|
|
|
133
157
|
workflow: {
|
|
134
158
|
kind: 'workflow';
|
|
135
159
|
name: string;
|
|
160
|
+
version?: string;
|
|
136
161
|
description?: string;
|
|
137
162
|
input?: SchemaInput;
|
|
138
163
|
inputSchema?: JsonValue;
|
|
@@ -150,3 +175,4 @@ export declare function asEffectsTool(def: {
|
|
|
150
175
|
match?: JsonValue;
|
|
151
176
|
};
|
|
152
177
|
}): EffectsTool;
|
|
178
|
+
export {};
|
|
@@ -1,7 +1,26 @@
|
|
|
1
|
+
import { DEFAULT_DEFINITION_VERSION, } from '@swirls/looms/core';
|
|
2
|
+
export function defineAgentSession(def) {
|
|
3
|
+
return {
|
|
4
|
+
kind: 'agent-session',
|
|
5
|
+
name: def.name,
|
|
6
|
+
version: def.version ?? DEFAULT_DEFINITION_VERSION,
|
|
7
|
+
agent: {
|
|
8
|
+
kind: 'agent',
|
|
9
|
+
name: def.agent.name,
|
|
10
|
+
version: def.agent.version,
|
|
11
|
+
},
|
|
12
|
+
idleTimeoutMs: Math.max(0, def.idleTimeoutMs ?? 0),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
1
15
|
export function normalizeTools(tools = []) {
|
|
2
16
|
return tools.map((entry) => {
|
|
3
|
-
if (entry.kind === 'function'
|
|
4
|
-
|
|
17
|
+
if (entry.kind === 'function' && 'handler' in entry) {
|
|
18
|
+
return entry;
|
|
19
|
+
}
|
|
20
|
+
if (entry.kind === 'thread' && 'child' in entry) {
|
|
21
|
+
return entry;
|
|
22
|
+
}
|
|
23
|
+
if (entry.kind === 'effects' && 'effects' in entry) {
|
|
5
24
|
return entry;
|
|
6
25
|
}
|
|
7
26
|
return asThreadTool({
|
|
@@ -16,15 +35,13 @@ export function normalizeTools(tools = []) {
|
|
|
16
35
|
});
|
|
17
36
|
}
|
|
18
37
|
export function defineTool(def) {
|
|
19
|
-
|
|
20
|
-
return { kind: 'function', ...def, input: def.input };
|
|
38
|
+
return { kind: 'function', ...def };
|
|
21
39
|
}
|
|
22
40
|
export function defineAgent(def) {
|
|
23
|
-
// SAFETY: factory fields match AgentDefinition.
|
|
24
41
|
return {
|
|
25
42
|
kind: 'agent',
|
|
26
43
|
...def,
|
|
27
|
-
|
|
44
|
+
version: def.version ?? DEFAULT_DEFINITION_VERSION,
|
|
28
45
|
tools: def.tools ? normalizeTools(def.tools) : undefined,
|
|
29
46
|
};
|
|
30
47
|
}
|
|
@@ -37,6 +54,7 @@ export function asThreadTool(def) {
|
|
|
37
54
|
inputSchema: def.inputSchema,
|
|
38
55
|
childKind: def.child.kind,
|
|
39
56
|
childName: def.child.name,
|
|
57
|
+
childVersion: def.child.version ?? DEFAULT_DEFINITION_VERSION,
|
|
40
58
|
child: def.child,
|
|
41
59
|
mapInput: def.mapInput,
|
|
42
60
|
};
|
|
@@ -47,7 +65,17 @@ export function asAgentTool(def) {
|
|
|
47
65
|
description: def.description ?? def.agent.instructions,
|
|
48
66
|
input: def.input ?? def.agent.input,
|
|
49
67
|
inputSchema: def.inputSchema ?? def.agent.inputSchema,
|
|
50
|
-
child: { kind: 'agent', name: def.agent.name },
|
|
68
|
+
child: { kind: 'agent', name: def.agent.name, version: def.agent.version },
|
|
69
|
+
mapInput: def.mapInput,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export function asEvaluatorTool(def) {
|
|
73
|
+
return asThreadTool({
|
|
74
|
+
name: def.name,
|
|
75
|
+
description: def.description ?? def.evaluator.description,
|
|
76
|
+
input: def.input ?? def.evaluator.input,
|
|
77
|
+
inputSchema: def.inputSchema ?? def.evaluator.inputSchema,
|
|
78
|
+
child: { kind: 'evaluator', name: def.evaluator.name },
|
|
51
79
|
mapInput: def.mapInput,
|
|
52
80
|
});
|
|
53
81
|
}
|
|
@@ -57,7 +85,7 @@ export function asWorkflowTool(def) {
|
|
|
57
85
|
description: def.description ?? def.workflow.description,
|
|
58
86
|
input: def.input ?? def.workflow.input,
|
|
59
87
|
inputSchema: def.inputSchema ?? def.workflow.inputSchema,
|
|
60
|
-
child: { kind: 'workflow', name: def.workflow.name },
|
|
88
|
+
child: { kind: 'workflow', name: def.workflow.name, version: def.workflow.version },
|
|
61
89
|
mapInput: def.mapInput,
|
|
62
90
|
});
|
|
63
91
|
}
|