agentenkit 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/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/adapters/inline.d.ts +27 -0
- package/dist/adapters/inline.d.ts.map +1 -0
- package/dist/adapters/inline.js +41 -0
- package/dist/adapters/inline.js.map +1 -0
- package/dist/adapters/memory.d.ts +74 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +194 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/prisma.d.ts +176 -0
- package/dist/adapters/prisma.d.ts.map +1 -0
- package/dist/adapters/prisma.js +107 -0
- package/dist/adapters/prisma.js.map +1 -0
- package/dist/adapters/qstash.d.ts +36 -0
- package/dist/adapters/qstash.d.ts.map +1 -0
- package/dist/adapters/qstash.js +26 -0
- package/dist/adapters/qstash.js.map +1 -0
- package/dist/adapters/redis.d.ts +49 -0
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js +60 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +67 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +199 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/upstash.d.ts +48 -0
- package/dist/adapters/upstash.d.ts.map +1 -0
- package/dist/adapters/upstash.js +46 -0
- package/dist/adapters/upstash.js.map +1 -0
- package/dist/admin/default.d.ts +15 -0
- package/dist/admin/default.d.ts.map +1 -0
- package/dist/admin/default.js +22 -0
- package/dist/admin/default.js.map +1 -0
- package/dist/admin/memory.d.ts +29 -0
- package/dist/admin/memory.d.ts.map +1 -0
- package/dist/admin/memory.js +83 -0
- package/dist/admin/memory.js.map +1 -0
- package/dist/admin/postgres.d.ts +43 -0
- package/dist/admin/postgres.d.ts.map +1 -0
- package/dist/admin/postgres.js +201 -0
- package/dist/admin/postgres.js.map +1 -0
- package/dist/admin/sqlite.d.ts +35 -0
- package/dist/admin/sqlite.d.ts.map +1 -0
- package/dist/admin/sqlite.js +187 -0
- package/dist/admin/sqlite.js.map +1 -0
- package/dist/core/admin.d.ts +88 -0
- package/dist/core/admin.d.ts.map +1 -0
- package/dist/core/admin.js +147 -0
- package/dist/core/admin.js.map +1 -0
- package/dist/core/agent.d.ts +29 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +41 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/cache.d.ts +37 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +68 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/context.d.ts +13 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +87 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/deleteThread.d.ts +14 -0
- package/dist/core/deleteThread.d.ts.map +1 -0
- package/dist/core/deleteThread.js +34 -0
- package/dist/core/deleteThread.js.map +1 -0
- package/dist/core/engine.d.ts +79 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +489 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/follow.d.ts +50 -0
- package/dist/core/follow.d.ts.map +1 -0
- package/dist/core/follow.js +153 -0
- package/dist/core/follow.js.map +1 -0
- package/dist/core/hitl.d.ts +98 -0
- package/dist/core/hitl.d.ts.map +1 -0
- package/dist/core/hitl.js +199 -0
- package/dist/core/hitl.js.map +1 -0
- package/dist/core/keys.d.ts +26 -0
- package/dist/core/keys.d.ts.map +1 -0
- package/dist/core/keys.js +32 -0
- package/dist/core/keys.js.map +1 -0
- package/dist/core/loop.d.ts +105 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +234 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/publish.d.ts +18 -0
- package/dist/core/publish.d.ts.map +1 -0
- package/dist/core/publish.js +34 -0
- package/dist/core/publish.js.map +1 -0
- package/dist/core/reclaim.d.ts +20 -0
- package/dist/core/reclaim.d.ts.map +1 -0
- package/dist/core/reclaim.js +56 -0
- package/dist/core/reclaim.js.map +1 -0
- package/dist/core/run.d.ts +8 -0
- package/dist/core/run.d.ts.map +1 -0
- package/dist/core/run.js +102 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/state.d.ts +50 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +39 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/stop.d.ts +7 -0
- package/dist/core/stop.d.ts.map +1 -0
- package/dist/core/stop.js +15 -0
- package/dist/core/stop.js.map +1 -0
- package/dist/core/stream.d.ts +12 -0
- package/dist/core/stream.d.ts.map +1 -0
- package/dist/core/stream.js +21 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/subagent.d.ts +77 -0
- package/dist/core/subagent.d.ts.map +1 -0
- package/dist/core/subagent.js +261 -0
- package/dist/core/subagent.js.map +1 -0
- package/dist/core/tools.d.ts +36 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +22 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +286 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage.d.ts +40 -0
- package/dist/core/usage.d.ts.map +1 -0
- package/dist/core/usage.js +43 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/admin.d.ts +102 -0
- package/dist/ports/admin.d.ts.map +1 -0
- package/dist/ports/admin.js +2 -0
- package/dist/ports/admin.js.map +1 -0
- package/dist/ports/bus.d.ts +13 -0
- package/dist/ports/bus.d.ts.map +1 -0
- package/dist/ports/bus.js +2 -0
- package/dist/ports/bus.js.map +1 -0
- package/dist/ports/kv.d.ts +16 -0
- package/dist/ports/kv.d.ts.map +1 -0
- package/dist/ports/kv.js +2 -0
- package/dist/ports/kv.js.map +1 -0
- package/dist/ports/queue.d.ts +18 -0
- package/dist/ports/queue.d.ts.map +1 -0
- package/dist/ports/queue.js +2 -0
- package/dist/ports/queue.js.map +1 -0
- package/dist/ports/runtime.d.ts +260 -0
- package/dist/ports/runtime.d.ts.map +1 -0
- package/dist/ports/runtime.js +2 -0
- package/dist/ports/runtime.js.map +1 -0
- package/dist/ports/storage.d.ts +72 -0
- package/dist/ports/storage.d.ts.map +1 -0
- package/dist/ports/storage.js +2 -0
- package/dist/ports/storage.js.map +1 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +177 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +126 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus.js","sourceRoot":"","sources":["../../src/ports/bus.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Hot key-value port: thread state cache, HITL handoff keys, seq & attempt
|
|
2
|
+
* counters, per-thread run locks (§3.2). Backed by Redis in the reference
|
|
3
|
+
* adapters — any KV works. */
|
|
4
|
+
export interface Kv {
|
|
5
|
+
get(key: string): Promise<string | null>;
|
|
6
|
+
/** Returns true iff the value was written. With `onlyIfNotExists` (SET NX),
|
|
7
|
+
* returns false when the key already existed — this is the atomic
|
|
8
|
+
* primitive behind the per-thread run lock (§3.4). */
|
|
9
|
+
set(key: string, value: string, opts?: {
|
|
10
|
+
exSeconds?: number;
|
|
11
|
+
onlyIfNotExists?: boolean;
|
|
12
|
+
}): Promise<boolean>;
|
|
13
|
+
del(key: string): Promise<void>;
|
|
14
|
+
incr(key: string): Promise<number>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=kv.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/ports/kv.ts"],"names":[],"mappings":"AAAA;;+BAE+B;AAC/B,MAAM,WAAW,EAAE;IACjB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC;;2DAEuD;IACvD,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE,GACvD,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACpC"}
|
package/dist/ports/kv.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv.js","sourceRoot":"","sources":["../../src/ports/kv.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { RunJob } from '../core/types.js';
|
|
2
|
+
export interface EnqueueOptions {
|
|
3
|
+
/** Hold the job for this many seconds before delivering it: the HITL expiry
|
|
4
|
+
* (§2.5) and a job blocked by an older run's lock (§2.8).
|
|
5
|
+
*
|
|
6
|
+
* An adapter that cannot delay may deliver immediately — both callers treat
|
|
7
|
+
* an early arrival as a no-op — but it must NOT throw, or a park would fail
|
|
8
|
+
* the run that scheduled it. Note the shape of the reference adapter: QStash
|
|
9
|
+
* supports delays on publish only and rejects them on queue enqueue, so
|
|
10
|
+
* QStashQueue publishes delayed jobs and queues the rest. */
|
|
11
|
+
delaySeconds?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Durable dispatch port (§2.8). Delivery is at-least-once — the engine's
|
|
14
|
+
* state guard + Storage.threads.claimState make double dispatch a no-op. */
|
|
15
|
+
export interface Queue {
|
|
16
|
+
enqueue(job: RunJob, opts?: EnqueueOptions): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/ports/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B;;;;;;;kEAO8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;6EAC6E;AAC7E,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/ports/queue.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import type { ToolSet } from 'ai';
|
|
2
|
+
import type { AgentEvent, AgentConfig, AgentKind, ContextUsage, ExecutionState, MessageDTO, ProviderOptions, ResolvedModel, RunJob, RunRecord, SubagentsConfig, ThreadDTO, UsageTotals } from '../core/types.js';
|
|
3
|
+
import type { Storage } from './storage.js';
|
|
4
|
+
import type { AdminStore, RunFilter, StepRecord } from './admin.js';
|
|
5
|
+
import type { AgentRunState, BoundStorage } from '../core/state.js';
|
|
6
|
+
import type { FollowOptions, SseOptions, SseStream } from '../core/follow.js';
|
|
7
|
+
export type { AdminStore, NewStepRecord, RunFilter, StepRecord } from './admin.js';
|
|
8
|
+
export type { AgentRunState, BoundStorage, StorageContext } from '../core/state.js';
|
|
9
|
+
import type { EventBus } from './bus.js';
|
|
10
|
+
import type { Queue } from './queue.js';
|
|
11
|
+
import type { Kv } from './kv.js';
|
|
12
|
+
import type { ExecuteInput, ExecuteOutcome } from '../core/engine.js';
|
|
13
|
+
import type { AdminOverview, RunDetail, RunStats, ThreadDetail, ThreadSummary } from '../core/admin.js';
|
|
14
|
+
export type { AdminOverview, RunDetail, RunStats, } from '../core/admin.js';
|
|
15
|
+
export type { ExecuteInput, ExecuteOutcome } from '../core/engine.js';
|
|
16
|
+
export type { AgentKind, ProviderOptions, ResolvedModel, RunJob, SubagentsConfig } from '../core/types.js';
|
|
17
|
+
/** The ports bundle — everything in core/ receives this and nothing else.
|
|
18
|
+
*
|
|
19
|
+
* `storage` is the caller's implementation with THIS run's context already
|
|
20
|
+
* bound (§2.10), so core keeps calling `messages.append(threadId, msg)` while
|
|
21
|
+
* the implementation still receives the state. `admin` is the platform's own
|
|
22
|
+
* operational store (§2.9) — never the caller's. */
|
|
23
|
+
export interface RuntimePorts {
|
|
24
|
+
storage: BoundStorage;
|
|
25
|
+
admin: AdminStore;
|
|
26
|
+
bus: EventBus;
|
|
27
|
+
queue: Queue;
|
|
28
|
+
kv: Kv;
|
|
29
|
+
/** User-provided model resolution (§3.3): models can live in any shape on
|
|
30
|
+
* the consumer side — the platform only ever sees `ResolvedModel`. */
|
|
31
|
+
resolveModel(modelName: string): ResolvedModel;
|
|
32
|
+
config: AgentConfig;
|
|
33
|
+
}
|
|
34
|
+
export interface RuntimeOptions {
|
|
35
|
+
storage: Storage;
|
|
36
|
+
/** Where operational history goes (§2.9). Omitted, it is chosen from the
|
|
37
|
+
* environment: Postgres when AGENTIC_KIT_ADMIN_DATABASE_URL is set, SQLite
|
|
38
|
+
* on disk otherwise. Pass one to decide for yourself. */
|
|
39
|
+
admin?: AdminStore;
|
|
40
|
+
bus: EventBus;
|
|
41
|
+
queue: Queue;
|
|
42
|
+
kv: Kv;
|
|
43
|
+
/** Models can come in any shape — config files, a database, provider SDKs.
|
|
44
|
+
* The platform only ever sees the resolved `ResolvedModel`. */
|
|
45
|
+
resolveModel(modelName: string): ResolvedModel;
|
|
46
|
+
config?: Partial<AgentConfig>;
|
|
47
|
+
}
|
|
48
|
+
export interface RunInput {
|
|
49
|
+
/** Omit to create a fresh thread first (threads.create, §3.2) */
|
|
50
|
+
threadId?: string;
|
|
51
|
+
prompt: string;
|
|
52
|
+
/** Carried through this whole run (§2.10): every storage call, every tool,
|
|
53
|
+
* every nested run. Persisted on the dispatch, so a worker picking the job
|
|
54
|
+
* up later — or resuming it after an approval — sees the same thing. The
|
|
55
|
+
* platform never reads it. */
|
|
56
|
+
state?: AgentRunState;
|
|
57
|
+
/** Edit + resend (§5.1): replace this user message with `prompt` and drop
|
|
58
|
+
* every message after it, then answer again from that point. Must name a
|
|
59
|
+
* message in this thread whose role is 'user'. Omit for a normal turn. */
|
|
60
|
+
editMessageId?: string;
|
|
61
|
+
/** Registry key or provider instance reference — resolved via
|
|
62
|
+
* `AgentCore.resolveModel`. Overrides the spec default. */
|
|
63
|
+
model?: string;
|
|
64
|
+
/** Max cumulative tokens (input + output) for this run — overrides
|
|
65
|
+
* spec.tokenBudget / config (§2.1 safety cap). Flows to the worker
|
|
66
|
+
* via RunJob.tokenBudget. */
|
|
67
|
+
tokenBudget?: number;
|
|
68
|
+
/** Additional provider-specific options, passed through to the provider
|
|
69
|
+
* from the AI SDK (§3.1). Merged over the spec default: the execute
|
|
70
|
+
* input wins per provider namespace. */
|
|
71
|
+
providerOptions?: ProviderOptions;
|
|
72
|
+
}
|
|
73
|
+
export interface RunResult {
|
|
74
|
+
accepted: boolean;
|
|
75
|
+
threadId: string;
|
|
76
|
+
/** This run's id (§2.1) — the same one carried by the enqueued job. An
|
|
77
|
+
* in-process worker must pass it back, or its dispatch has no identity. */
|
|
78
|
+
runId?: string;
|
|
79
|
+
state?: ExecutionState;
|
|
80
|
+
error?: string;
|
|
81
|
+
}
|
|
82
|
+
export interface StopResult {
|
|
83
|
+
accepted: boolean;
|
|
84
|
+
error?: string;
|
|
85
|
+
}
|
|
86
|
+
export interface DeleteThreadResult {
|
|
87
|
+
accepted: boolean;
|
|
88
|
+
error?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface RespondInput {
|
|
91
|
+
threadId: string;
|
|
92
|
+
toolCallId: string;
|
|
93
|
+
approved: boolean;
|
|
94
|
+
payload?: unknown;
|
|
95
|
+
/** The run state (§2.10) for the storage calls answering makes. The RESUMED
|
|
96
|
+
* run rebuilds its own state from the park's ticket — this is only for the
|
|
97
|
+
* reads and writes `respond` itself performs. */
|
|
98
|
+
state?: AgentRunState;
|
|
99
|
+
}
|
|
100
|
+
export interface RespondResult {
|
|
101
|
+
delivered: boolean;
|
|
102
|
+
error?: string;
|
|
103
|
+
}
|
|
104
|
+
/** What a thread has spent, and how full its context is (§2.6, §4). */
|
|
105
|
+
export interface ThreadUsage {
|
|
106
|
+
/** Every run segment's tokens, summed. */
|
|
107
|
+
tokens: UsageTotals;
|
|
108
|
+
/** What the next run's prompt would carry before compaction. */
|
|
109
|
+
context: ContextUsage;
|
|
110
|
+
/** The model the budget was measured against. */
|
|
111
|
+
model: string;
|
|
112
|
+
}
|
|
113
|
+
/** Durable state used to hydrate a client before it starts live event replay. */
|
|
114
|
+
export interface ThreadSnapshot {
|
|
115
|
+
thread: ThreadDTO;
|
|
116
|
+
messages: MessageDTO[];
|
|
117
|
+
/** Nested runs on this thread (§2.7) — name, depth and final state, so a
|
|
118
|
+
* reconnecting client rebuilds its subagent panel without depending on
|
|
119
|
+
* events that only replay while a run is unfinished. */
|
|
120
|
+
runs: RunRecord[];
|
|
121
|
+
/** Cursor for starting live replay without duplicating snapshot state. */
|
|
122
|
+
lastEventSeq: number;
|
|
123
|
+
/** Only the unfinished run's events, used to restore transient activity. */
|
|
124
|
+
activeEvents: AgentEvent[];
|
|
125
|
+
}
|
|
126
|
+
/** Everything streamText accepts except the platform-owned keys (§3.1).
|
|
127
|
+
* `onChunk` / `onFinish` ARE allowed — the platform chains them (§4). */
|
|
128
|
+
export type StreamTextAgentSpec = {
|
|
129
|
+
/** Unique handle key — the queue dispatch key (§5). */
|
|
130
|
+
name: string;
|
|
131
|
+
/** Registry key for this agent's model — resolved via
|
|
132
|
+
* `AgentCore.resolveModel` (instance + contextWindow). */
|
|
133
|
+
model?: string;
|
|
134
|
+
/** Opt-in subagent delegation (§2.7). */
|
|
135
|
+
subagents?: boolean | SubagentsConfig;
|
|
136
|
+
/** Default per-run token budget (input + output). Per-run
|
|
137
|
+
* `input.tokenBudget` wins; `undefined` = unbounded apart from `maxSteps`. */
|
|
138
|
+
tokenBudget?: number;
|
|
139
|
+
/** Additional provider-specific options, passed through to the provider
|
|
140
|
+
* from the AI SDK. Per-provider namespace; the execute input wins. */
|
|
141
|
+
providerOptions?: ProviderOptions;
|
|
142
|
+
} & Omit<Parameters<typeof import('ai').streamText>[0], 'model' | 'messages' | 'prompt' | 'system' | 'abortSignal' | 'maxSteps' | 'onStepFinish' | 'onError'> & {
|
|
143
|
+
/** `system` is allowed here (static persona); per-run system is not. */
|
|
144
|
+
system?: string;
|
|
145
|
+
tools?: ToolSet;
|
|
146
|
+
onChunk?: (para: any) => void | Promise<void>;
|
|
147
|
+
onFinish?: (finishParams: any) => void | Promise<void>;
|
|
148
|
+
};
|
|
149
|
+
export type GenerateTextAgentSpec = {
|
|
150
|
+
/** Unique handle key — the queue dispatch key (§5). */
|
|
151
|
+
name: string;
|
|
152
|
+
model?: string;
|
|
153
|
+
subagents?: boolean | SubagentsConfig;
|
|
154
|
+
tokenBudget?: number;
|
|
155
|
+
providerOptions?: ProviderOptions;
|
|
156
|
+
} & Omit<Parameters<typeof import('ai').generateText>[0], 'model' | 'messages' | 'prompt' | 'abortSignal' | 'onFinish' | 'onStepFinish'> & {
|
|
157
|
+
tools?: ToolSet;
|
|
158
|
+
onFinish?: (finishParams: any) => void | Promise<void>;
|
|
159
|
+
};
|
|
160
|
+
/** An executor bound to a generation flavor and to the user's generation
|
|
161
|
+
* arguments (§3). Returned by the `create*Agent` factories. */
|
|
162
|
+
export interface AgentHandle {
|
|
163
|
+
readonly name: string;
|
|
164
|
+
readonly kind: AgentKind;
|
|
165
|
+
/** Worker-side only (§5.6). Throws on failure — see executeWithPolicy.
|
|
166
|
+
* Returns 'lock-conflict' when another worker owns the thread's run lock
|
|
167
|
+
* (nothing was executed) and 'stale' when a newer run has replaced this
|
|
168
|
+
* one (§2.1, §2.8). */
|
|
169
|
+
execute(input: ExecuteInput): Promise<ExecuteOutcome>;
|
|
170
|
+
/** execute + §2.8 failure policy: redrive < maxAttempts, else finalize FAILED */
|
|
171
|
+
executeWithPolicy(input: ExecuteInput, policy?: {
|
|
172
|
+
maxAttempts?: number;
|
|
173
|
+
}): Promise<void>;
|
|
174
|
+
/** Persist user message → state RUNNING → enqueue a job dispatched back to
|
|
175
|
+
* THIS handle (the job carries `agent: this.name` and `tokenBudget`). */
|
|
176
|
+
run(input: RunInput): Promise<RunResult>;
|
|
177
|
+
/** Platform stop (§2.1) — works regardless of which agent's run is active. */
|
|
178
|
+
stop(threadId: string, state?: AgentRunState): Promise<StopResult>;
|
|
179
|
+
}
|
|
180
|
+
export interface AgentCore {
|
|
181
|
+
/** Resolve a registry key to the stable identity and provider instance used
|
|
182
|
+
* by execution, compaction, usage attribution, and persisted run metadata. */
|
|
183
|
+
resolveModel(modelName: string): ResolvedModel;
|
|
184
|
+
/** Most recent first — thread pickers / sidebars. Takes the run state
|
|
185
|
+
* (§2.10) so a tenant-scoped Storage can filter; a read has no dispatch
|
|
186
|
+
* ticket to carry it on. */
|
|
187
|
+
listThreads(state?: AgentRunState): Promise<ThreadDTO[]>;
|
|
188
|
+
/** One call for UIs / history routes: thread + messages + recent events. */
|
|
189
|
+
getThreadSnapshot(threadId: string, state?: AgentRunState): Promise<ThreadSnapshot | null>;
|
|
190
|
+
/** Tokens spent so far and the §2.6 context load. Null when the thread is
|
|
191
|
+
* gone. Kept out of the snapshot so hydration stays one cheap read. */
|
|
192
|
+
getThreadUsage(threadId: string, state?: AgentRunState): Promise<ThreadUsage | null>;
|
|
193
|
+
/** Delete a thread and everything that follows it — messages, events,
|
|
194
|
+
* usage rows, subagent runs, and the thread's hot kv keys (§3.2).
|
|
195
|
+
* Refused while a run is active; stop() first. */
|
|
196
|
+
deleteThread(threadId: string, state?: AgentRunState): Promise<DeleteThreadResult>;
|
|
197
|
+
hitl: {
|
|
198
|
+
respond(input: RespondInput): Promise<RespondResult>;
|
|
199
|
+
reclaimIfOrphaned(threadId: string, state?: AgentRunState): Promise<boolean>;
|
|
200
|
+
};
|
|
201
|
+
events: {
|
|
202
|
+
since(threadId: string, sinceSeq: number, state?: AgentRunState): Promise<AgentEvent[]>;
|
|
203
|
+
subscribe(threadId: string, handler: (event: AgentEvent) => void): Promise<() => void>;
|
|
204
|
+
/** Replay then live, as one sequence, with the cursor discipline already
|
|
205
|
+
* applied (§2.2): subscribe before replaying, never emit at or below the
|
|
206
|
+
* cursor, forward a seq-0 notice without moving it.
|
|
207
|
+
*
|
|
208
|
+
* Framework-neutral — an async iterable is something Express, Nest, Hono,
|
|
209
|
+
* Next or a plain worker can each consume in their own way. Pass a signal,
|
|
210
|
+
* or the subscription outlives the client. */
|
|
211
|
+
follow(threadId: string, options?: FollowOptions & {
|
|
212
|
+
state?: AgentRunState;
|
|
213
|
+
}): AsyncGenerator<AgentEvent>;
|
|
214
|
+
/** `follow`, encoded as Server-Sent Events. Returns the stream and the
|
|
215
|
+
* headers rather than a Response, because half the ecosystem has none. */
|
|
216
|
+
sse(threadId: string, options?: SseOptions & {
|
|
217
|
+
state?: AgentRunState;
|
|
218
|
+
}): SseStream;
|
|
219
|
+
};
|
|
220
|
+
/** Agent factories — see §4. Each call registers a handle under `spec.name`. */
|
|
221
|
+
createStreamTextAgent(spec: StreamTextAgentSpec): AgentHandle;
|
|
222
|
+
createGenerateTextAgent(spec: GenerateTextAgentSpec): AgentHandle;
|
|
223
|
+
/** Worker-side resolution of a registered handle from the queue job. */
|
|
224
|
+
getAgent(name: string): AgentHandle | null;
|
|
225
|
+
/** Operational reads (§2.9). The platform records what runs did; building a
|
|
226
|
+
* view over it is the caller's business. Everything here comes from the
|
|
227
|
+
* platform's OWN store — it never reads the caller's database. */
|
|
228
|
+
admin: {
|
|
229
|
+
overview(range?: {
|
|
230
|
+
since?: Date;
|
|
231
|
+
}): Promise<AdminOverview>;
|
|
232
|
+
listRuns(filter?: RunFilter): Promise<RunRecord[]>;
|
|
233
|
+
stats(range?: {
|
|
234
|
+
since?: Date;
|
|
235
|
+
until?: Date;
|
|
236
|
+
}): Promise<RunStats>;
|
|
237
|
+
getRun(runId: string): Promise<RunDetail | null>;
|
|
238
|
+
listRunsByThread(threadId: string): Promise<RunRecord[]>;
|
|
239
|
+
listSteps(runId: string): Promise<StepRecord[]>;
|
|
240
|
+
/** Threads with their runs rolled up — the top level of an operational
|
|
241
|
+
* view, since a thread is what a person recognises (§2.9). */
|
|
242
|
+
listThreads(filter?: {
|
|
243
|
+
state?: ExecutionState[];
|
|
244
|
+
since?: Date;
|
|
245
|
+
limit?: number;
|
|
246
|
+
}): Promise<ThreadSummary[]>;
|
|
247
|
+
getThread(threadId: string): Promise<ThreadDetail | null>;
|
|
248
|
+
};
|
|
249
|
+
/** The queue dispatch side of the platform (§2.8): resolves the handle,
|
|
250
|
+
* applies the failure policy, and is idempotent under at-least-once
|
|
251
|
+
* delivery (the per-thread run lock, §3.4). The HTTP layer only verifies
|
|
252
|
+
* signatures, parses JSON, and calls this. */
|
|
253
|
+
worker: {
|
|
254
|
+
handleJob(job: RunJob): Promise<{
|
|
255
|
+
accepted: boolean;
|
|
256
|
+
reason?: string;
|
|
257
|
+
}>;
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/ports/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,eAAe,EACf,aAAa,EACb,MAAM,EACN,SAAS,EACT,eAAe,EACf,SAAS,EACT,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9E,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnF,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,aAAa,EACd,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,aAAa,EACb,SAAS,EACT,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAE1B,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAGtE,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE3G;;;;;qDAKqD;AACrD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,EAAE,CAAC;IACP;2EACuE;IACvE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/C,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB;;8DAE0D;IAC1D,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;IACb,EAAE,EAAE,EAAE,CAAC;IACP;oEACgE;IAChE,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC;IAC/C,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,QAAQ;IACvB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf;;;mCAG+B;IAC/B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;+EAE2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;gEAC4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;kCAE8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;6CAEyC;IACzC,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB;gFAC4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;sDAEkD;IAClD,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,WAAW,WAAW;IAC1B,0CAA0C;IAC1C,MAAM,EAAE,WAAW,CAAC;IACpB,gEAAgE;IAChE,OAAO,EAAE,YAAY,CAAC;IACtB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,iFAAiF;AACjF,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB;;6DAEyD;IACzD,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,0EAA0E;IAC1E,YAAY,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,YAAY,EAAE,UAAU,EAAE,CAAC;CAC5B;AAED;0EAC0E;AAC1E,MAAM,MAAM,mBAAmB,GAAG;IAChC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb;+DAC2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACtC;mFAC+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;2EACuE;IACvE,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,EAClD,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,GACxD,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC,GAAG;IAC/C,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC,GAAG,IAAI,CAAC,UAAU,CAAC,cAAc,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,EACpD,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,cAAc,CAAC,GAAG;IACnF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD,CAAC;AAEF;gEACgE;AAChE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAEzB;;;4BAGwB;IACxB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAEtD,iFAAiF;IACjF,iBAAiB,CACf,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAChC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;8EAC0E;IAC1E,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAEzC,8EAA8E;IAC9E,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,SAAS;IACxB;mFAC+E;IAC/E,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAAC;IAE/C;;iCAE6B;IAC7B,WAAW,CAAC,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;IAEzD,4EAA4E;IAC5E,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAE3F;4EACwE;IACxE,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAErF;;uDAEmD;IACnD,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAEnF,IAAI,EAAE;QACJ,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QACrD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAC9E,CAAC;IAEF,MAAM,EAAE;QACN,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACvF;;;;;;uDAM+C;QAC/C,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,aAAa,GAAG;YAAE,KAAK,CAAC,EAAE,aAAa,CAAA;SAAE,GAClD,cAAc,CAAC,UAAU,CAAC,CAAC;QAC9B;mFAC2E;QAC3E,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG;YAAE,KAAK,CAAC,EAAE,aAAa,CAAA;SAAE,GAAG,SAAS,CAAC;KACpF,CAAC;IAEF,gFAAgF;IAChF,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,WAAW,CAAC;IAC9D,uBAAuB,CAAC,IAAI,EAAE,qBAAqB,GAAG,WAAW,CAAC;IAElE,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IAE3C;;uEAEmE;IACnE,KAAK,EAAE;QACL,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,IAAI,CAAA;SAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACnD,KAAK,CAAC,KAAK,CAAC,EAAE;YAAE,KAAK,CAAC,EAAE,IAAI,CAAC;YAAC,KAAK,CAAC,EAAE,IAAI,CAAA;SAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACjD,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACzD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAChD;uEAC+D;QAC/D,WAAW,CAAC,MAAM,CAAC,EAAE;YACnB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;YACzB,KAAK,CAAC,EAAE,IAAI,CAAC;YACb,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QAC7B,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;KAC3D,CAAC;IAEF;;;mDAG+C;IAC/C,MAAM,EAAE;QACN,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;YAAE,QAAQ,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACzE,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/ports/runtime.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { StorageContext } from '../core/state.js';
|
|
2
|
+
import type { AgentEvent, ExecutionState, MessageDTO, NewMessage, NewUsage, UsageTotals, ThreadDTO } from '../core/types.js';
|
|
3
|
+
/** Persistence port for a caller's OWN data (§3.2): threads, messages, events,
|
|
4
|
+
* usage. DTOs cross the boundary; ORM/entity types never leak into core.
|
|
5
|
+
* Implement it once for MongoDB, MySQL, DynamoDB — or use the shipped
|
|
6
|
+
* PrismaStorage reference adapter.
|
|
7
|
+
*
|
|
8
|
+
* Operational history — run records, timings, step markers — is NOT here.
|
|
9
|
+
* agentic-kit owns and stores that itself (§2.9); callers only read it back
|
|
10
|
+
* through `runtime.admin`.
|
|
11
|
+
*
|
|
12
|
+
* Every method receives the run's StorageContext as its last argument, so an
|
|
13
|
+
* implementation can scope a query to a tenant, stamp a row with who caused
|
|
14
|
+
* it, or route to a different database entirely (§2.10). */
|
|
15
|
+
export interface Storage {
|
|
16
|
+
threads: {
|
|
17
|
+
get(threadId: string, ctx: StorageContext): Promise<ThreadDTO | null>;
|
|
18
|
+
create(init: {
|
|
19
|
+
model?: string;
|
|
20
|
+
} | undefined, ctx: StorageContext): Promise<ThreadDTO>;
|
|
21
|
+
/** Most recent first — thread pickers / sidebars. */
|
|
22
|
+
list(ctx: StorageContext): Promise<ThreadDTO[]>;
|
|
23
|
+
setState(threadId: string, state: ExecutionState, ctx: StorageContext): Promise<void>;
|
|
24
|
+
/** Delete the thread AND everything that follows it: messages, events,
|
|
25
|
+
* usage rows, and subagent runs. Throws if the thread does not exist.
|
|
26
|
+
* The reference Prisma schema cascades via `onDelete: Cascade`. */
|
|
27
|
+
delete(threadId: string, ctx: StorageContext): Promise<void>;
|
|
28
|
+
/** Compare-and-set: returns true iff THIS caller performed the transition.
|
|
29
|
+
* Backs HITL reclamation + double-dispatch protection (§2.5, §2.8).
|
|
30
|
+
* Must be atomic — a single conditional UPDATE or equivalent. */
|
|
31
|
+
claimState(threadId: string, from: ExecutionState, to: ExecutionState, ctx: StorageContext): Promise<boolean>;
|
|
32
|
+
};
|
|
33
|
+
messages: {
|
|
34
|
+
append(threadId: string, message: NewMessage, ctx: StorageContext): Promise<MessageDTO>;
|
|
35
|
+
/** Oldest first. The scope decides WHOSE turns come back (§2.7):
|
|
36
|
+
* - `{ agentId: null }` — the main agent's stream. Compaction (§2.6) and
|
|
37
|
+
* the edit lookup (§5.1) must use this; unscoped, a subagent's turns
|
|
38
|
+
* leak into the parent's prompt and context isolation is gone.
|
|
39
|
+
* - `{ agentId: 'sub_1' }` — that nested run's own stream.
|
|
40
|
+
* - omitted — every row on the thread, for UI hydration (§2.2). */
|
|
41
|
+
list(threadId: string, opts: {
|
|
42
|
+
agentId?: string | null;
|
|
43
|
+
} | undefined, ctx: StorageContext): Promise<MessageDTO[]>;
|
|
44
|
+
/** Delete `messageId` and every message after it, in the same order
|
|
45
|
+
* `list` returns (§5.1 edit + resend). Returns how many rows went; 0 when
|
|
46
|
+
* the id is not in this thread.
|
|
47
|
+
*
|
|
48
|
+
* Dropping a suffix only leaves the history well-formed if it starts at a
|
|
49
|
+
* user turn — cutting from a tool result would strip it off the assistant
|
|
50
|
+
* tool-call that produced it, and a dangling call is a conversation no
|
|
51
|
+
* provider accepts. `run()` enforces that; adapters just delete. */
|
|
52
|
+
deleteFrom(threadId: string, messageId: string, ctx: StorageContext): Promise<number>;
|
|
53
|
+
};
|
|
54
|
+
events: {
|
|
55
|
+
append(threadId: string, event: AgentEvent, ctx: StorageContext): Promise<void>;
|
|
56
|
+
/** All events after the cursor, ascending by seq — SSE replay (§2.2) */
|
|
57
|
+
listSince(threadId: string, sinceSeq: number, ctx: StorageContext): Promise<AgentEvent[]>;
|
|
58
|
+
/** Most recent event of a type — the HITL pending check (§2.5) */
|
|
59
|
+
latest(threadId: string, type: string, ctx: StorageContext): Promise<AgentEvent | null>;
|
|
60
|
+
/** Every event of a type, ascending by seq. The open-approval set (§2.7)
|
|
61
|
+
* is derived from these; scanning `listSince` instead would drag every
|
|
62
|
+
* CHUNK on the thread through memory. */
|
|
63
|
+
listByType(threadId: string, type: string, ctx: StorageContext): Promise<AgentEvent[]>;
|
|
64
|
+
};
|
|
65
|
+
usage: {
|
|
66
|
+
record(threadId: string, usage: NewUsage, ctx: StorageContext): Promise<void>;
|
|
67
|
+
/** Every recorded segment for the thread, summed (§4). A thread with no
|
|
68
|
+
* usage rows yet returns zeroes, never null. */
|
|
69
|
+
total(threadId: string, ctx: StorageContext): Promise<UsageTotals>;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/ports/storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,SAAS,EACV,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;;6DAW6D;AAC7D,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE;QACP,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,EAAE;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACtF,qDAAqD;QACrD,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QACtF;;4EAEoE;QACpE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D;;0EAEkE;QAClE,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;KACrB,CAAC;IACF,QAAQ,EAAE;QACR,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;QACxF;;;;;4EAKoE;QACpE,IAAI,CACF,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE,GAAG,SAAS,EAC7C,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QACzB;;;;;;;6EAOqE;QACrE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACvF,CAAC;IACF,MAAM,EAAE;QACN,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAChF,wEAAwE;QACxE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QAC1F,kEAAkE;QAClE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;QACxF;;kDAE0C;QAC1C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;KACxF,CAAC;IACF,KAAK,EAAE;QACL,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9E;yDACiD;QACjD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;KACpE,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/ports/storage.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AgentCore, RuntimeOptions } from './ports/runtime.js';
|
|
2
|
+
/** Bind the ports to the core behaviors (§3.3). This is the package's public
|
|
3
|
+
* entry point — the only place where anything is wired together. */
|
|
4
|
+
export declare function setupAgentCore(opts: RuntimeOptions): Promise<AgentCore>;
|
|
5
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EAMT,cAAc,EAGf,MAAM,oBAAoB,CAAC;AAY5B;qEACqE;AACrE,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CA6M7E"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { resolveConfig } from './core/types.js';
|
|
2
|
+
import { contextUsage } from './core/context.js';
|
|
3
|
+
import { createGenerateTextAgent, createStreamTextAgent } from './core/agent.js';
|
|
4
|
+
import * as adminReads from './core/admin.js';
|
|
5
|
+
import { bindStorage } from './core/state.js';
|
|
6
|
+
import { followEvents, toSseStream } from './core/follow.js';
|
|
7
|
+
import { openDefaultAdminStore } from './admin/default.js';
|
|
8
|
+
import { reclaimIfOrphaned } from './core/reclaim.js';
|
|
9
|
+
import { respond } from './core/hitl.js';
|
|
10
|
+
import { deleteThread } from './core/deleteThread.js';
|
|
11
|
+
/** Bind the ports to the core behaviors (§3.3). This is the package's public
|
|
12
|
+
* entry point — the only place where anything is wired together. */
|
|
13
|
+
export async function setupAgentCore(opts) {
|
|
14
|
+
// Operational history is the platform's own (§2.9). Nothing configured means
|
|
15
|
+
// SQLite on disk: history that survives a restart should be the default, not
|
|
16
|
+
// something you have to remember to switch on.
|
|
17
|
+
//
|
|
18
|
+
// Opened here, eagerly, which is why this function is async: a store that
|
|
19
|
+
// cannot be opened is a startup error you see immediately, rather than a
|
|
20
|
+
// surprise on the first run — and losing run history silently looks exactly
|
|
21
|
+
// like having no traffic.
|
|
22
|
+
const admin = opts.admin ?? (await openDefaultAdminStore());
|
|
23
|
+
const shared = {
|
|
24
|
+
admin,
|
|
25
|
+
bus: opts.bus,
|
|
26
|
+
queue: opts.queue,
|
|
27
|
+
kv: opts.kv,
|
|
28
|
+
resolveModel: (modelName) => opts.resolveModel(modelName),
|
|
29
|
+
config: resolveConfig(opts.config),
|
|
30
|
+
};
|
|
31
|
+
/** Ports for ONE run: the caller's storage with that run's state bound, so
|
|
32
|
+
* every query, insert and update their implementation makes can see it
|
|
33
|
+
* (§2.10). Called per entry point rather than once, because state belongs
|
|
34
|
+
* to a run and a runtime outlives many. */
|
|
35
|
+
const scope = (state = {}, runId) => ({
|
|
36
|
+
...shared,
|
|
37
|
+
storage: bindStorage(opts.storage, { state, runId }),
|
|
38
|
+
});
|
|
39
|
+
// For reads that are not on behalf of any particular run.
|
|
40
|
+
const deps = scope();
|
|
41
|
+
// Handle registry — keyed by spec.name, resolved by the queue dispatch.
|
|
42
|
+
const registry = new Map();
|
|
43
|
+
// The first registered stream-text handle is the default for jobs that
|
|
44
|
+
// omit `agent` (§5).
|
|
45
|
+
let defaultAgent = null;
|
|
46
|
+
const register = (name, kind, spec) => {
|
|
47
|
+
const handle = kind === 'stream-text'
|
|
48
|
+
? createStreamTextAgent(scope, spec)
|
|
49
|
+
: createGenerateTextAgent(scope, spec);
|
|
50
|
+
registry.set(name, handle);
|
|
51
|
+
return handle;
|
|
52
|
+
};
|
|
53
|
+
const core = {
|
|
54
|
+
resolveModel: (modelName) => deps.resolveModel(modelName),
|
|
55
|
+
// Reads take the run state too (§2.10). A run carries it on its ticket,
|
|
56
|
+
// but a read has no ticket to carry — so a tenant-scoped Storage would see
|
|
57
|
+
// an empty context here and either return nothing or, worse, everything.
|
|
58
|
+
listThreads: (state) => scope(state).storage.threads.list(),
|
|
59
|
+
deleteThread: (threadId, state) => deleteThread(scope(state), threadId),
|
|
60
|
+
getThreadSnapshot: async (threadId, state) => {
|
|
61
|
+
const deps = scope(state);
|
|
62
|
+
const thread = await deps.storage.threads.get(threadId);
|
|
63
|
+
if (!thread)
|
|
64
|
+
return null;
|
|
65
|
+
const messages = await deps.storage.messages.list(threadId, undefined);
|
|
66
|
+
const runs = await deps.admin.runs.listByThread(threadId);
|
|
67
|
+
const events = await deps.storage.events.listSince(threadId, -1);
|
|
68
|
+
const lastEventSeq = events.at(-1)?.seq ?? -1;
|
|
69
|
+
let activeEvents = [];
|
|
70
|
+
if (thread.state === 'RUNNING' || thread.state === 'WAITING_FOR_INPUT') {
|
|
71
|
+
let boundary = -1;
|
|
72
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
73
|
+
const event = events[index];
|
|
74
|
+
if (event.type === 'STATE_CHANGE' &&
|
|
75
|
+
event.payload?.state === 'RUNNING') {
|
|
76
|
+
boundary = index;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const active = events.slice(Math.max(0, boundary));
|
|
81
|
+
// Everything up to the last committed step is ALREADY in `messages`
|
|
82
|
+
// (§2.2). Replaying those chunks too would render each finished step's
|
|
83
|
+
// text twice — once from the durable message, once from the stream
|
|
84
|
+
// that produced it. Only the in-flight step's chunks are missing from
|
|
85
|
+
// durable history, so only those are transient.
|
|
86
|
+
//
|
|
87
|
+
// Chunks alone: a park (INPUT_REQUIRED) is published DURING the step,
|
|
88
|
+
// before its messages commit, so slicing the whole window by this
|
|
89
|
+
// boundary would drop the very approval a reconnecting client needs.
|
|
90
|
+
const lastCommitted = active.reduce((seq, e) => (e.type === 'STEP_COMMITTED' ? e.seq : seq), -1);
|
|
91
|
+
const isStream = (type) => type === 'CHUNK' || type === 'SUBAGENT_CHUNK';
|
|
92
|
+
activeEvents = active.filter((e) => !(isStream(e.type) && e.seq !== 0 && e.seq <= lastCommitted));
|
|
93
|
+
}
|
|
94
|
+
return { thread, messages, runs, lastEventSeq, activeEvents };
|
|
95
|
+
},
|
|
96
|
+
admin: {
|
|
97
|
+
overview: (range) => adminReads.overview(deps, range),
|
|
98
|
+
listRuns: (filter) => adminReads.listRuns(deps, filter),
|
|
99
|
+
stats: (range) => adminReads.runStats(deps, range),
|
|
100
|
+
getRun: (runId) => adminReads.getRun(deps, runId),
|
|
101
|
+
listRunsByThread: (threadId) => deps.admin.runs.listByThread(threadId),
|
|
102
|
+
listSteps: (runId) => adminReads.listSteps(deps, runId),
|
|
103
|
+
listThreads: (filter) => adminReads.listThreads(deps, filter),
|
|
104
|
+
getThread: (threadId) => adminReads.getThread(deps, threadId),
|
|
105
|
+
},
|
|
106
|
+
getThreadUsage: async (threadId, state) => {
|
|
107
|
+
const deps = scope(state);
|
|
108
|
+
const thread = await deps.storage.threads.get(threadId);
|
|
109
|
+
if (!thread)
|
|
110
|
+
return null;
|
|
111
|
+
const [tokens, context] = await Promise.all([
|
|
112
|
+
deps.storage.usage.total(threadId),
|
|
113
|
+
contextUsage(deps, threadId, thread.model),
|
|
114
|
+
]);
|
|
115
|
+
return { tokens, context, model: thread.model };
|
|
116
|
+
},
|
|
117
|
+
hitl: {
|
|
118
|
+
respond: (input) => {
|
|
119
|
+
// Scoped like the run it resumes: answering an approval reads and
|
|
120
|
+
// writes the caller's rows (§2.10).
|
|
121
|
+
const scoped = scope(input.state);
|
|
122
|
+
// Heal an orphaned wait first — if reclamation claims the thread, the
|
|
123
|
+
// response is rejected as late (§2.5)
|
|
124
|
+
return (async () => {
|
|
125
|
+
await reclaimIfOrphaned(scoped, input.threadId);
|
|
126
|
+
return respond(scoped, input);
|
|
127
|
+
})();
|
|
128
|
+
},
|
|
129
|
+
reclaimIfOrphaned: (threadId, state) => reclaimIfOrphaned(scope(state), threadId),
|
|
130
|
+
},
|
|
131
|
+
events: {
|
|
132
|
+
since: (threadId, sinceSeq, state) => scope(state).storage.events.listSince(threadId, sinceSeq),
|
|
133
|
+
subscribe: async (threadId, handler) => deps.bus.subscribe(threadId, handler),
|
|
134
|
+
// The replay-then-tail dance lives here rather than in every route
|
|
135
|
+
// handler: subscribe first, never emit at or below the cursor, and let a
|
|
136
|
+
// seq-0 notice through without moving it (§2.2).
|
|
137
|
+
follow: (threadId, options = {}) => followEvents(scope(options.state), threadId, options),
|
|
138
|
+
sse: (threadId, options = {}) => toSseStream(followEvents(scope(options.state), threadId, options), options),
|
|
139
|
+
},
|
|
140
|
+
createStreamTextAgent: (spec) => {
|
|
141
|
+
const handle = register(spec.name, 'stream-text', spec);
|
|
142
|
+
if (defaultAgent === null)
|
|
143
|
+
defaultAgent = spec.name;
|
|
144
|
+
return handle;
|
|
145
|
+
},
|
|
146
|
+
createGenerateTextAgent: (spec) => register(spec.name, 'generate-text', spec),
|
|
147
|
+
getAgent: (name) => registry.get(name) ?? null,
|
|
148
|
+
worker: {
|
|
149
|
+
handleJob: async (job) => {
|
|
150
|
+
// Missing `agent` → the default handle (first registered stream-text)
|
|
151
|
+
const agent = (job.agent ? registry.get(job.agent) : null) ??
|
|
152
|
+
(defaultAgent ? registry.get(defaultAgent) : null);
|
|
153
|
+
if (!agent)
|
|
154
|
+
return { accepted: false, reason: 'unknown-agent' };
|
|
155
|
+
// executeWithPolicy: run lock (idempotent under at-least-once
|
|
156
|
+
// delivery, §3.4) + §2.8 failure policy — redrive < maxAttempts,
|
|
157
|
+
// else finalize FAILED; a user stop is never retried.
|
|
158
|
+
await agent.executeWithPolicy({
|
|
159
|
+
threadId: job.threadId,
|
|
160
|
+
// The dispatch's identity (§2.1) — without it the worker cannot tell
|
|
161
|
+
// it has been replaced by a newer run, and a blocked job is dropped.
|
|
162
|
+
runId: job.runId,
|
|
163
|
+
// Carries the queue wait through to the run record (§2.9).
|
|
164
|
+
enqueuedAt: job.enqueuedAt,
|
|
165
|
+
// Rehydrated from the ticket: this worker never saw the caller (§2.10).
|
|
166
|
+
state: job.state,
|
|
167
|
+
model: job.model,
|
|
168
|
+
tokenBudget: job.tokenBudget,
|
|
169
|
+
providerOptions: job.providerOptions,
|
|
170
|
+
});
|
|
171
|
+
return { accepted: true };
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
return core;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=runtime.js.map
|