@slopus/happy-agent-base 0.0.1 → 0.0.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/README.md +20 -235
- package/dist/Agent.d.ts +71 -9
- package/dist/Agent.d.ts.map +1 -1
- package/dist/Agent.js +258 -40
- package/dist/Agent.js.map +1 -1
- package/dist/AgentBase.d.ts +268 -23
- package/dist/AgentBase.d.ts.map +1 -1
- package/dist/AgentBase.js +1620 -333
- package/dist/AgentBase.js.map +1 -1
- package/dist/AgentBaseHooks.d.ts +108 -24
- package/dist/AgentBaseHooks.d.ts.map +1 -1
- package/dist/AgentBasePending.d.ts +44 -0
- package/dist/AgentBasePending.d.ts.map +1 -0
- package/dist/AgentBasePending.js +64 -0
- package/dist/AgentBasePending.js.map +1 -0
- package/dist/AgentBaseState.d.ts +2 -0
- package/dist/AgentBaseState.d.ts.map +1 -1
- package/dist/AgentConfig.d.ts +67 -0
- package/dist/AgentConfig.d.ts.map +1 -0
- package/dist/AgentConfig.js +81 -0
- package/dist/AgentConfig.js.map +1 -0
- package/dist/AgentContexts.d.ts +40 -0
- package/dist/AgentContexts.d.ts.map +1 -0
- package/dist/AgentContexts.js +70 -0
- package/dist/AgentContexts.js.map +1 -0
- package/dist/AgentFeature.d.ts +118 -15
- package/dist/AgentFeature.d.ts.map +1 -1
- package/dist/AgentKV.d.ts +58 -0
- package/dist/AgentKV.d.ts.map +1 -0
- package/dist/AgentKV.js +114 -0
- package/dist/AgentKV.js.map +1 -0
- package/dist/AgentModel.d.ts +17 -0
- package/dist/AgentModel.d.ts.map +1 -0
- package/dist/AgentModel.js +2 -0
- package/dist/AgentModel.js.map +1 -0
- package/dist/{AgentBasePersistence.d.ts → AgentPersistence.d.ts} +13 -8
- package/dist/AgentPersistence.d.ts.map +1 -0
- package/dist/AgentPersistence.js +2 -0
- package/dist/AgentPersistence.js.map +1 -0
- package/dist/AgentProviders.d.ts +22 -7
- package/dist/AgentProviders.d.ts.map +1 -1
- package/dist/AgentProviders.js +18 -9
- package/dist/AgentProviders.js.map +1 -1
- package/dist/AgentRef.d.ts +41 -0
- package/dist/AgentRef.d.ts.map +1 -0
- package/dist/AgentRef.js +60 -0
- package/dist/AgentRef.js.map +1 -0
- package/dist/AgentStorage.d.ts +39 -0
- package/dist/AgentStorage.d.ts.map +1 -0
- package/dist/AgentStorage.js +49 -0
- package/dist/AgentStorage.js.map +1 -0
- package/dist/AgentSystem.d.ts +52 -0
- package/dist/AgentSystem.d.ts.map +1 -0
- package/dist/AgentSystem.js +2 -0
- package/dist/AgentSystem.js.map +1 -0
- package/dist/AgentSystemContext.d.ts +15 -0
- package/dist/AgentSystemContext.d.ts.map +1 -0
- package/dist/AgentSystemContext.js +20 -0
- package/dist/AgentSystemContext.js.map +1 -0
- package/dist/AgentSystemLocal.d.ts +104 -0
- package/dist/AgentSystemLocal.d.ts.map +1 -0
- package/dist/AgentSystemLocal.js +401 -0
- package/dist/AgentSystemLocal.js.map +1 -0
- package/dist/AgentSystemRef.d.ts +56 -0
- package/dist/AgentSystemRef.d.ts.map +1 -0
- package/dist/AgentSystemRef.js +75 -0
- package/dist/AgentSystemRef.js.map +1 -0
- package/dist/AgentTaskContext.d.ts +17 -0
- package/dist/AgentTaskContext.d.ts.map +1 -0
- package/dist/AgentTaskContext.js +26 -0
- package/dist/AgentTaskContext.js.map +1 -0
- package/dist/AgentTool.d.ts +40 -0
- package/dist/AgentTool.d.ts.map +1 -1
- package/dist/AgentTool.js.map +1 -1
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +62 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +185 -0
- package/dist/models.js.map +1 -0
- package/package.json +6 -4
- package/dist/AgentBaseContext.d.ts +0 -22
- package/dist/AgentBaseContext.d.ts.map +0 -1
- package/dist/AgentBaseContext.js +0 -33
- package/dist/AgentBaseContext.js.map +0 -1
- package/dist/AgentBasePersistence.d.ts.map +0 -1
- package/dist/AgentBasePersistence.js +0 -2
- package/dist/AgentBasePersistence.js.map +0 -1
|
@@ -9,7 +9,7 @@ import type { Context } from "@steve.kite/stdlib";
|
|
|
9
9
|
* written in the same transaction that physically deletes the superseded records, so it opens
|
|
10
10
|
* the store; the records after it append as usual.
|
|
11
11
|
*/
|
|
12
|
-
export type
|
|
12
|
+
export type AgentRecord = {
|
|
13
13
|
readonly type: "user";
|
|
14
14
|
readonly message: SessionUserMessage;
|
|
15
15
|
} | {
|
|
@@ -29,11 +29,12 @@ export type AgentBaseRecord = {
|
|
|
29
29
|
* Storage for one agent: an append-only main context store plus a sorted key-value store held
|
|
30
30
|
* alongside it. A sent message is first written under a `pending.` key ordered by append time;
|
|
31
31
|
* it reaches the main store only when a turn consumes it into the context, and its pending key
|
|
32
|
-
* is deleted at that moment.
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* is deleted at that moment. Exactly one owner connects to a store, and the agent serializes its
|
|
33
|
+
* own record and bookkeeping writes through one lock, so history order always matches storage
|
|
34
|
+
* order. Key-value operations — a feature's or a tool's — run as they come, so each one has to be
|
|
35
|
+
* atomic on its own, but no implementation ever has to defend against a second owner.
|
|
35
36
|
*/
|
|
36
|
-
export interface
|
|
37
|
+
export interface AgentPersistence {
|
|
37
38
|
/**
|
|
38
39
|
* Run work atomically. The implementation opens a transaction and passes work a derived
|
|
39
40
|
* context that its own operations recognize; how the transaction rides on that context is
|
|
@@ -41,8 +42,10 @@ export interface AgentBasePersistence {
|
|
|
41
42
|
* error rolls them all back.
|
|
42
43
|
*/
|
|
43
44
|
transaction<Result>(ctx: Context, work: (ctx: Context) => Promise<Result>): Promise<Result>;
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
/** Every record in the main context store, in append order. */
|
|
46
|
+
load(ctx: Context): Promise<readonly AgentRecord[]>;
|
|
47
|
+
/** Add one more record to the end of the main context store. */
|
|
48
|
+
append(ctx: Context, record: AgentRecord): Promise<void>;
|
|
46
49
|
/**
|
|
47
50
|
* Physically delete every record in the main context store. Called only inside the
|
|
48
51
|
* compaction transaction, immediately before the replacement compaction record is appended,
|
|
@@ -54,7 +57,9 @@ export interface AgentBasePersistence {
|
|
|
54
57
|
readonly key: string;
|
|
55
58
|
readonly value: unknown;
|
|
56
59
|
}[]>;
|
|
60
|
+
/** Store the value under `key`, replacing whatever was there before. */
|
|
57
61
|
writeValue(ctx: Context, key: string, value: unknown): Promise<void>;
|
|
62
|
+
/** Remove the entry stored under `key`, if any. */
|
|
58
63
|
deleteValue(ctx: Context, key: string): Promise<void>;
|
|
59
64
|
}
|
|
60
|
-
//# sourceMappingURL=
|
|
65
|
+
//# sourceMappingURL=AgentPersistence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentPersistence.d.ts","sourceRoot":"","sources":["../sources/AgentPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,wBAAwB,EACxB,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,MAAM,WAAW,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;CAAE,GAC/D;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,wBAAwB,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GACnE;IACI,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAChD,CAAC;AAER;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5F,+DAA+D;IAC/D,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,SAAS,WAAW,EAAE,CAAC,CAAC;IACpD,gEAAgE;IAChE,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,UAAU,CACN,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,MAAM,GACf,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC,CAAC;IACzE,wEAAwE;IACxE,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,mDAAmD;IACnD,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentPersistence.js","sourceRoot":"","sources":["../sources/AgentPersistence.ts"],"names":[],"mappings":""}
|
package/dist/AgentProviders.d.ts
CHANGED
|
@@ -1,17 +1,32 @@
|
|
|
1
1
|
import type { BaseProvider, ProviderModelCompatibilityType } from "@slopus/happy-providers";
|
|
2
|
+
/** The serializable provider/model selection a provider source resolves. */
|
|
3
|
+
export interface AgentProviderSelection {
|
|
4
|
+
/** The caller-defined registration ID of the provider. */
|
|
5
|
+
readonly id: string;
|
|
6
|
+
/** The model whose provider instance is needed, if the agent selected one. */
|
|
7
|
+
readonly model: string | undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Either one provider suitable for every selected model or a lazy model-aware provider factory.
|
|
11
|
+
* Providers own no session lifetime; each AgentBase owns and destroys the sessions it opens.
|
|
12
|
+
*/
|
|
13
|
+
export type AgentProviderSource = BaseProvider | ((selection: AgentProviderSelection) => BaseProvider | Promise<BaseProvider>);
|
|
2
14
|
/**
|
|
3
|
-
* Mutable registry of
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* conversation must reset. Providers can be added and removed while the process runs; lookups
|
|
7
|
-
* return the live reference or null when absent.
|
|
15
|
+
* Mutable registry of model-aware provider sources keyed by caller-supplied IDs. Each entry carries
|
|
16
|
+
* its compatibility type, which decides how far a model change can go before the conversation
|
|
17
|
+
* must reset.
|
|
8
18
|
*/
|
|
9
19
|
export declare class AgentProviders {
|
|
10
20
|
#private;
|
|
11
|
-
|
|
21
|
+
/** Register a provider source under `id`. Throws if that ID is already registered. */
|
|
22
|
+
add(id: string, source: AgentProviderSource, type: ProviderModelCompatibilityType): void;
|
|
23
|
+
/** Unregister the provider at `id`. Returns whether one was actually removed. */
|
|
12
24
|
remove(id: string): boolean;
|
|
13
|
-
|
|
25
|
+
/** Resolve the provider suitable for `model`, or null when `id` is not registered. */
|
|
26
|
+
resolve(id: string, model: string | undefined): Promise<BaseProvider | null>;
|
|
27
|
+
/** The compatibility type the provider at `id` was registered with, or null when absent. */
|
|
14
28
|
typeOf(id: string): ProviderModelCompatibilityType | null;
|
|
29
|
+
/** Every currently registered provider ID. */
|
|
15
30
|
get ids(): readonly string[];
|
|
16
31
|
}
|
|
17
32
|
//# sourceMappingURL=AgentProviders.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentProviders.d.ts","sourceRoot":"","sources":["../sources/AgentProviders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAE5F
|
|
1
|
+
{"version":3,"file":"AgentProviders.d.ts","sourceRoot":"","sources":["../sources/AgentProviders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,yBAAyB,CAAC;AAE5F,4EAA4E;AAC5E,MAAM,WAAW,sBAAsB;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GACzB,YAAY,GACZ,CAAC,CAAC,SAAS,EAAE,sBAAsB,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;AAEpF;;;;GAIG;AACH,qBAAa,cAAc;;IAOvB,sFAAsF;IACtF,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,IAAI,EAAE,8BAA8B,GAAG,IAAI,CAKvF;IAED,iFAAiF;IACjF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE1B;IAED,sFAAsF;IAChF,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAMjF;IAED,4FAA4F;IAC5F,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,8BAA8B,GAAG,IAAI,CAExD;IAED,8CAA8C;IAC9C,IAAI,GAAG,IAAI,SAAS,MAAM,EAAE,CAE3B;CACJ"}
|
package/dist/AgentProviders.js
CHANGED
|
@@ -1,27 +1,36 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mutable registry of
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* conversation must reset. Providers can be added and removed while the process runs; lookups
|
|
6
|
-
* return the live reference or null when absent.
|
|
2
|
+
* Mutable registry of model-aware provider sources keyed by caller-supplied IDs. Each entry carries
|
|
3
|
+
* its compatibility type, which decides how far a model change can go before the conversation
|
|
4
|
+
* must reset.
|
|
7
5
|
*/
|
|
8
6
|
export class AgentProviders {
|
|
7
|
+
/** Registered provider sources keyed by their caller-supplied ID and compatibility type. */
|
|
9
8
|
#providers = new Map();
|
|
10
|
-
|
|
9
|
+
/** Register a provider source under `id`. Throws if that ID is already registered. */
|
|
10
|
+
add(id, source, type) {
|
|
11
11
|
if (this.#providers.has(id)) {
|
|
12
12
|
throw new Error(`Provider "${id}" is already registered.`);
|
|
13
13
|
}
|
|
14
|
-
this.#providers.set(id, {
|
|
14
|
+
this.#providers.set(id, { source, type });
|
|
15
15
|
}
|
|
16
|
+
/** Unregister the provider at `id`. Returns whether one was actually removed. */
|
|
16
17
|
remove(id) {
|
|
17
18
|
return this.#providers.delete(id);
|
|
18
19
|
}
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
/** Resolve the provider suitable for `model`, or null when `id` is not registered. */
|
|
21
|
+
async resolve(id, model) {
|
|
22
|
+
const entry = this.#providers.get(id);
|
|
23
|
+
if (entry === undefined)
|
|
24
|
+
return null;
|
|
25
|
+
return typeof entry.source === "function"
|
|
26
|
+
? await entry.source({ id, model })
|
|
27
|
+
: entry.source;
|
|
21
28
|
}
|
|
29
|
+
/** The compatibility type the provider at `id` was registered with, or null when absent. */
|
|
22
30
|
typeOf(id) {
|
|
23
31
|
return this.#providers.get(id)?.type ?? null;
|
|
24
32
|
}
|
|
33
|
+
/** Every currently registered provider ID. */
|
|
25
34
|
get ids() {
|
|
26
35
|
return [...this.#providers.keys()];
|
|
27
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentProviders.js","sourceRoot":"","sources":["../sources/AgentProviders.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AgentProviders.js","sourceRoot":"","sources":["../sources/AgentProviders.ts"],"names":[],"mappings":"AAkBA;;;;GAIG;AACH,MAAM,OAAO,cAAc;IACvB,4FAA4F;IACnF,UAAU,GAAG,IAAI,GAAG,EAG1B,CAAC;IAEJ,sFAAsF;IACtF,GAAG,CAAC,EAAU,EAAE,MAA2B,EAAE,IAAoC;QAC7E,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,aAAa,EAAE,0BAA0B,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,iFAAiF;IACjF,MAAM,CAAC,EAAU;QACb,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,sFAAsF;IACtF,KAAK,CAAC,OAAO,CAAC,EAAU,EAAE,KAAyB;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU;YACrC,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;YACnC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACvB,CAAC;IAED,4FAA4F;IAC5F,MAAM,CAAC,EAAU;QACb,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC;IACjD,CAAC;IAED,8CAA8C;IAC9C,IAAI,GAAG;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;CACJ"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { SessionUserMessage } from "@slopus/happy-providers";
|
|
2
|
+
import type { Context } from "@steve.kite/stdlib";
|
|
3
|
+
import type { Agent } from "./Agent.js";
|
|
4
|
+
import type { AgentBaseMessageOptions } from "./AgentBase.js";
|
|
5
|
+
/**
|
|
6
|
+
* Whether this caller may be told that `agentId` durably accepted a message. Acceptance is a
|
|
7
|
+
* queue write under that agent's own persistence lock, so waiting for it is safe from anywhere
|
|
8
|
+
* except inside that agent's loop, which is holding the lock the write needs. The proof is the
|
|
9
|
+
* caller's context naming a different agent; a context naming none proves nothing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function acceptanceIsWaitable(ctx: Context, target: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* A reference to an agent for code that runs inside one — a feature hook, or a tool the run loop
|
|
14
|
+
* is waiting on. No operation here waits for a run loop: `compact` and `abort` are requests that
|
|
15
|
+
* resolve once they have been made, and there is no `close`, `waitForIdle` or `start`, each of
|
|
16
|
+
* which is whole-agent lifetime owned by whoever created the agent and nothing *but* the wait
|
|
17
|
+
* this caller must not make.
|
|
18
|
+
*
|
|
19
|
+
* Messages are different, because accepting one is a durable queue write rather than a turn.
|
|
20
|
+
* Addressed to another agent, `steer` and `send` resolve once the message really is part of that
|
|
21
|
+
* agent's conversation and reject when the write fails, so a caller routing work elsewhere knows
|
|
22
|
+
* whether it arrived. Addressed to the agent the caller is running inside — whose loop would have
|
|
23
|
+
* to perform that write — the message is queued and not waited for. The context decides, since it
|
|
24
|
+
* names the agent the caller is in; a context that names none proves nothing and waits for
|
|
25
|
+
* nothing.
|
|
26
|
+
*/
|
|
27
|
+
export declare class AgentRef {
|
|
28
|
+
#private;
|
|
29
|
+
constructor(agent: Agent);
|
|
30
|
+
/** The wrapped agent's ID. */
|
|
31
|
+
get id(): string;
|
|
32
|
+
/** Queue a message that injects as soon as the current response and its tool batch finish. */
|
|
33
|
+
steer(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
|
|
34
|
+
/** Queue a message that injects when the agent would otherwise stop. */
|
|
35
|
+
send(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
|
|
36
|
+
/** Ask the agent to compact, which it does between turns. */
|
|
37
|
+
compact(ctx: Context): Promise<void>;
|
|
38
|
+
/** Cancel the agent's active turn. */
|
|
39
|
+
abort(ctx: Context): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=AgentRef.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentRef.d.ts","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9D;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAG1E;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,QAAQ;;IAIjB,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,8BAA8B;IAC9B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,8FAA8F;IACxF,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,wEAAwE;IAClE,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,6DAA6D;IACvD,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEzC;IAED,sCAAsC;IAChC,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;CACJ"}
|
package/dist/AgentRef.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { agentId } from "./AgentContexts.js";
|
|
2
|
+
/**
|
|
3
|
+
* Whether this caller may be told that `agentId` durably accepted a message. Acceptance is a
|
|
4
|
+
* queue write under that agent's own persistence lock, so waiting for it is safe from anywhere
|
|
5
|
+
* except inside that agent's loop, which is holding the lock the write needs. The proof is the
|
|
6
|
+
* caller's context naming a different agent; a context naming none proves nothing.
|
|
7
|
+
*/
|
|
8
|
+
export function acceptanceIsWaitable(ctx, target) {
|
|
9
|
+
const caller = agentId(ctx);
|
|
10
|
+
return caller !== undefined && caller !== target;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A reference to an agent for code that runs inside one — a feature hook, or a tool the run loop
|
|
14
|
+
* is waiting on. No operation here waits for a run loop: `compact` and `abort` are requests that
|
|
15
|
+
* resolve once they have been made, and there is no `close`, `waitForIdle` or `start`, each of
|
|
16
|
+
* which is whole-agent lifetime owned by whoever created the agent and nothing *but* the wait
|
|
17
|
+
* this caller must not make.
|
|
18
|
+
*
|
|
19
|
+
* Messages are different, because accepting one is a durable queue write rather than a turn.
|
|
20
|
+
* Addressed to another agent, `steer` and `send` resolve once the message really is part of that
|
|
21
|
+
* agent's conversation and reject when the write fails, so a caller routing work elsewhere knows
|
|
22
|
+
* whether it arrived. Addressed to the agent the caller is running inside — whose loop would have
|
|
23
|
+
* to perform that write — the message is queued and not waited for. The context decides, since it
|
|
24
|
+
* names the agent the caller is in; a context that names none proves nothing and waits for
|
|
25
|
+
* nothing.
|
|
26
|
+
*/
|
|
27
|
+
export class AgentRef {
|
|
28
|
+
/** The agent this reference wraps. */
|
|
29
|
+
#agent;
|
|
30
|
+
constructor(agent) {
|
|
31
|
+
this.#agent = agent;
|
|
32
|
+
}
|
|
33
|
+
/** The wrapped agent's ID. */
|
|
34
|
+
get id() {
|
|
35
|
+
return this.#agent.id;
|
|
36
|
+
}
|
|
37
|
+
/** Queue a message that injects as soon as the current response and its tool batch finish. */
|
|
38
|
+
async steer(ctx, message, options) {
|
|
39
|
+
await this.#agent.steer(ctx, message, {
|
|
40
|
+
...options,
|
|
41
|
+
await: acceptanceIsWaitable(ctx, this.#agent.id),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
/** Queue a message that injects when the agent would otherwise stop. */
|
|
45
|
+
async send(ctx, message, options) {
|
|
46
|
+
await this.#agent.send(ctx, message, {
|
|
47
|
+
...options,
|
|
48
|
+
await: acceptanceIsWaitable(ctx, this.#agent.id),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Ask the agent to compact, which it does between turns. */
|
|
52
|
+
async compact(ctx) {
|
|
53
|
+
await this.#agent.compact(ctx, { await: false });
|
|
54
|
+
}
|
|
55
|
+
/** Cancel the agent's active turn. */
|
|
56
|
+
async abort(ctx) {
|
|
57
|
+
await this.#agent.abort(ctx, { await: false });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=AgentRef.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentRef.js","sourceRoot":"","sources":["../sources/AgentRef.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,MAAc;IAC7D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,MAAM,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,QAAQ;IACjB,sCAAsC;IAC7B,MAAM,CAAQ;IAEvB,YAAY,KAAY;QACpB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,8BAA8B;IAC9B,IAAI,EAAE;QACF,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1B,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,KAAK,CACP,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE;YAClC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,wEAAwE;IACxE,KAAK,CAAC,IAAI,CACN,GAAY,EACZ,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE;YACjC,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,OAAO,CAAC,GAAY;QACtB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,sCAAsC;IACtC,KAAK,CAAC,KAAK,CAAC,GAAY;QACpB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;CACJ"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Context } from "@steve.kite/stdlib";
|
|
2
|
+
import type { AgentKV } from "./AgentKV.js";
|
|
3
|
+
import type { AgentPersistence } from "./AgentPersistence.js";
|
|
4
|
+
/**
|
|
5
|
+
* The exclusive ownership of one durable agent store. The storage adapter must back this with
|
|
6
|
+
* the database's hard process-level lock rather than an in-memory convention.
|
|
7
|
+
*/
|
|
8
|
+
export interface AgentStorageLock {
|
|
9
|
+
/** Release the hard lock after the owning AgentSystem has stopped every agent. */
|
|
10
|
+
release(ctx: Context): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
/** What an `AgentStorage` is built from. */
|
|
13
|
+
export interface AgentStorageOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Acquire exclusive ownership of the whole store. This must fail while any other process or
|
|
16
|
+
* AgentSystem owns the same durable store.
|
|
17
|
+
*/
|
|
18
|
+
readonly acquireLock: (ctx: Context) => Promise<AgentStorageLock>;
|
|
19
|
+
/** Shared key-value storage used for state spanning all agents. */
|
|
20
|
+
readonly kv: AgentKV;
|
|
21
|
+
/** Produce the isolated persistence used by one agent. */
|
|
22
|
+
readonly persistence: (agentId: string) => AgentPersistence;
|
|
23
|
+
}
|
|
24
|
+
/** Storage roots shared by an `AgentSystemLocal` collection. */
|
|
25
|
+
export declare class AgentStorage {
|
|
26
|
+
#private;
|
|
27
|
+
/** Shared key-value storage used for state spanning all agents. */
|
|
28
|
+
readonly kv: AgentKV;
|
|
29
|
+
constructor(options: AgentStorageOptions);
|
|
30
|
+
/**
|
|
31
|
+
* Acquire exclusive ownership until the returned lock is released. The adapter's lock
|
|
32
|
+
* enforces this across processes; the local guard also rejects accidental reuse of this
|
|
33
|
+
* object.
|
|
34
|
+
*/
|
|
35
|
+
acquireLock(ctx: Context): Promise<AgentStorageLock>;
|
|
36
|
+
/** The isolated persistence for the given agent. */
|
|
37
|
+
persistence(agentId: string): AgentPersistence;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=AgentStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentStorage.d.ts","sourceRoot":"","sources":["../sources/AgentStorage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,kFAAkF;IAClF,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAED,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAChC;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClE,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,CAAC;CAC/D;AAED,gEAAgE;AAChE,qBAAa,YAAY;;IACrB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IAQrB,YAAY,OAAO,EAAE,mBAAmB,EAIvC;IAED;;;;OAIG;IACG,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBzD;IAED,oDAAoD;IACpD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAE7C;CACJ"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Storage roots shared by an `AgentSystemLocal` collection. */
|
|
2
|
+
export class AgentStorage {
|
|
3
|
+
/** Shared key-value storage used for state spanning all agents. */
|
|
4
|
+
kv;
|
|
5
|
+
/** Acquires the database-backed exclusive lock for this store. */
|
|
6
|
+
#acquireLock;
|
|
7
|
+
/** Produces the isolated persistence used by one agent. */
|
|
8
|
+
#persistence;
|
|
9
|
+
/** Prevents two systems from sharing even one AgentStorage instance. */
|
|
10
|
+
#owned = false;
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.kv = options.kv;
|
|
13
|
+
this.#acquireLock = options.acquireLock;
|
|
14
|
+
this.#persistence = options.persistence;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Acquire exclusive ownership until the returned lock is released. The adapter's lock
|
|
18
|
+
* enforces this across processes; the local guard also rejects accidental reuse of this
|
|
19
|
+
* object.
|
|
20
|
+
*/
|
|
21
|
+
async acquireLock(ctx) {
|
|
22
|
+
if (this.#owned)
|
|
23
|
+
throw new Error("The agent store is already owned by another system.");
|
|
24
|
+
this.#owned = true;
|
|
25
|
+
let lock;
|
|
26
|
+
try {
|
|
27
|
+
lock = await this.#acquireLock(ctx);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
this.#owned = false;
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
let released = false;
|
|
34
|
+
return {
|
|
35
|
+
release: async (releaseCtx) => {
|
|
36
|
+
if (released)
|
|
37
|
+
return;
|
|
38
|
+
await lock.release(releaseCtx);
|
|
39
|
+
released = true;
|
|
40
|
+
this.#owned = false;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** The isolated persistence for the given agent. */
|
|
45
|
+
persistence(agentId) {
|
|
46
|
+
return this.#persistence(agentId);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=AgentStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentStorage.js","sourceRoot":"","sources":["../sources/AgentStorage.ts"],"names":[],"mappings":"AA2BA,gEAAgE;AAChE,MAAM,OAAO,YAAY;IACrB,mEAAmE;IAC1D,EAAE,CAAU;IACrB,kEAAkE;IACzD,YAAY,CAA8C;IACnE,2DAA2D;IAClD,YAAY,CAAwC;IAC7D,wEAAwE;IACxE,MAAM,GAAG,KAAK,CAAC;IAEf,YAAY,OAA4B;QACpC,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAC,GAAY;QAC1B,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACxF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,IAAsB,CAAC;QAC3B,IAAI,CAAC;YACD,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACxC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,MAAM,KAAK,CAAC;QAChB,CAAC;QACD,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO;YACH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBAC1B,IAAI,QAAQ;oBAAE,OAAO;gBACrB,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC/B,QAAQ,GAAG,IAAI,CAAC;gBAChB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACxB,CAAC;SACJ,CAAC;IACN,CAAC;IAED,oDAAoD;IACpD,WAAW,CAAC,OAAe;QACvB,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;CACJ"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { SessionMessage, SessionUserMessage } from "@slopus/happy-providers";
|
|
2
|
+
import type { Context } from "@steve.kite/stdlib";
|
|
3
|
+
import type { Agent } from "./Agent.js";
|
|
4
|
+
import type { AgentBaseAwaitOptions, AgentBaseMessageOptions } from "./AgentBase.js";
|
|
5
|
+
import type { AgentConfig } from "./AgentConfig.js";
|
|
6
|
+
import type { AgentModel } from "./AgentModel.js";
|
|
7
|
+
/** Conversation state installed atomically before a newly created agent starts. */
|
|
8
|
+
export interface AgentInitialContext {
|
|
9
|
+
/** The conversation installed as the agent's history before its first turn runs. */
|
|
10
|
+
readonly messages: readonly SessionMessage[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* A collection of agents addressed by ID: what an owner can ask of the agents it runs. An agent
|
|
14
|
+
* exists only once it has been created with its configuration, which is persisted and stays in
|
|
15
|
+
* effect for the agent's whole life; resolving one that was never created is an error.
|
|
16
|
+
*
|
|
17
|
+
* This is the full surface, including the operations that wait for an agent's run loop to reach a
|
|
18
|
+
* particular point — `delete`, and anything reached through the returned `Agent`. Those are for
|
|
19
|
+
* the caller that owns the agents' lifetime. Code running *inside* an agent, such as a feature
|
|
20
|
+
* hook or a tool, is waited for by that loop and must not wait for it in turn: it should hold an
|
|
21
|
+
* `AgentSystemRef`, whose every operation returns without waiting for a loop.
|
|
22
|
+
*/
|
|
23
|
+
export interface AgentSystem {
|
|
24
|
+
/** The models this collection offers its agents. */
|
|
25
|
+
readonly models: readonly AgentModel[];
|
|
26
|
+
/** Stop every agent and release this system's exclusive ownership of its durable store. */
|
|
27
|
+
close(ctx: Context): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Create an agent with a new system-generated cuid2 identity and the configuration it keeps
|
|
30
|
+
* for its whole life. The configuration and optional initial context are persisted before
|
|
31
|
+
* the agent runs; a creation that fails to produce an agent leaves no identity behind.
|
|
32
|
+
*/
|
|
33
|
+
create(ctx: Context, config: AgentConfig, initialContext?: AgentInitialContext): Promise<Agent>;
|
|
34
|
+
/** Close an agent and release its identity, so the same ID can be created again. */
|
|
35
|
+
delete(ctx: Context, agentId: string): Promise<void>;
|
|
36
|
+
/** The configuration an agent was created with, or undefined when there is no such agent. */
|
|
37
|
+
config(ctx: Context, agentId: string): Promise<AgentConfig | undefined>;
|
|
38
|
+
/** The live agent for an ID, loading it if this process has not seen it yet. */
|
|
39
|
+
resolve(ctx: Context, agentId: string): Promise<Agent>;
|
|
40
|
+
/**
|
|
41
|
+
* Queue a user message for an agent, injected as soon as its current response and tool batch
|
|
42
|
+
* finish.
|
|
43
|
+
*/
|
|
44
|
+
steer(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
|
|
45
|
+
/** Queue a user message for an agent that injects only when the agent would otherwise stop. */
|
|
46
|
+
send(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
|
|
47
|
+
/** Cancel an agent's active turn, leaving its queued messages durable for the next one. */
|
|
48
|
+
abort(ctx: Context, agentId: string, options?: AgentBaseAwaitOptions): Promise<void>;
|
|
49
|
+
/** Ask an agent for its conversation to be replaced by the provider's summary of it. */
|
|
50
|
+
compact(ctx: Context, agentId: string, options?: AgentBaseAwaitOptions): Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=AgentSystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystem.d.ts","sourceRoot":"","sources":["../sources/AgentSystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,mFAAmF;AACnF,MAAM,WAAW,mBAAmB;IAChC,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,CAAC;CAChD;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,WAAW;IACxB,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAEvC,2FAA2F;IAC3F,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;;;OAIG;IACH,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAEhG,oFAAoF;IACpF,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErD,6FAA6F;IAC7F,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAExE,gFAAgF;IAChF,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAEvD;;;OAGG;IACH,KAAK,CACD,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAAG,qBAAqB,GAC1D,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,+FAA+F;IAC/F,IAAI,CACA,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAAG,qBAAqB,GAC1D,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,2FAA2F;IAC3F,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErF,wFAAwF;IACxF,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1F"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystem.js","sourceRoot":"","sources":["../sources/AgentSystem.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Context } from "@steve.kite/stdlib";
|
|
2
|
+
import type { AgentSystemRef } from "./AgentSystemRef.js";
|
|
3
|
+
/**
|
|
4
|
+
* Carry the collection that owns an agent and its features, as a reference.
|
|
5
|
+
*
|
|
6
|
+
* Only the reference travels on a context. Everything that reads one — a feature hook, a tool —
|
|
7
|
+
* is code some run loop is waiting for, while the owner's surface holds the operations that wait
|
|
8
|
+
* for a loop to reach a particular point. A collection therefore puts an `AgentSystemRef` on
|
|
9
|
+
* every context it derives, and agents come back from it as `AgentRef`, so nothing reached
|
|
10
|
+
* through a context can wait for the loop that is waiting for it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function withAgentSystem(ctx: Context, value: AgentSystemRef): Context;
|
|
13
|
+
/** The collection owning the current feature or agent operation. */
|
|
14
|
+
export declare function agentSystem(ctx: Context): AgentSystemRef | undefined;
|
|
15
|
+
//# sourceMappingURL=AgentSystemContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemContext.d.ts","sourceRoot":"","sources":["../sources/AgentSystemContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAQ1D;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAE5E;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAEpE"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createContextNamespace } from "@steve.kite/stdlib";
|
|
2
|
+
/** The context slot that carries the collection owning the current agent or feature operation. */
|
|
3
|
+
const agentSystemNamespace = createContextNamespace("happyAgent.agentSystem", undefined);
|
|
4
|
+
/**
|
|
5
|
+
* Carry the collection that owns an agent and its features, as a reference.
|
|
6
|
+
*
|
|
7
|
+
* Only the reference travels on a context. Everything that reads one — a feature hook, a tool —
|
|
8
|
+
* is code some run loop is waiting for, while the owner's surface holds the operations that wait
|
|
9
|
+
* for a loop to reach a particular point. A collection therefore puts an `AgentSystemRef` on
|
|
10
|
+
* every context it derives, and agents come back from it as `AgentRef`, so nothing reached
|
|
11
|
+
* through a context can wait for the loop that is waiting for it.
|
|
12
|
+
*/
|
|
13
|
+
export function withAgentSystem(ctx, value) {
|
|
14
|
+
return agentSystemNamespace.set(ctx, value);
|
|
15
|
+
}
|
|
16
|
+
/** The collection owning the current feature or agent operation. */
|
|
17
|
+
export function agentSystem(ctx) {
|
|
18
|
+
return agentSystemNamespace.get(ctx);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=AgentSystemContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemContext.js","sourceRoot":"","sources":["../sources/AgentSystemContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAgB,MAAM,oBAAoB,CAAC;AAI1E,kGAAkG;AAClG,MAAM,oBAAoB,GAAG,sBAAsB,CAC/C,wBAAwB,EACxB,SAAS,CACZ,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY,EAAE,KAAqB;IAC/D,OAAO,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,WAAW,CAAC,GAAY;IACpC,OAAO,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { SessionUserMessage } from "@slopus/happy-providers";
|
|
2
|
+
import { type Context } from "@steve.kite/stdlib";
|
|
3
|
+
import { Agent } from "./Agent.js";
|
|
4
|
+
import { type AgentBaseAwaitOptions, type AgentBaseMessageOptions } from "./AgentBase.js";
|
|
5
|
+
import { type AgentConfig } from "./AgentConfig.js";
|
|
6
|
+
import type { AgentFeature } from "./AgentFeature.js";
|
|
7
|
+
import type { AgentModel } from "./AgentModel.js";
|
|
8
|
+
import type { AgentProviders } from "./AgentProviders.js";
|
|
9
|
+
import type { AgentStorage } from "./AgentStorage.js";
|
|
10
|
+
import type { AgentInitialContext, AgentSystem } from "./AgentSystem.js";
|
|
11
|
+
/** Everything `AgentSystemLocal` needs to build and run the agents in its collection. */
|
|
12
|
+
export interface AgentSystemLocalOptions {
|
|
13
|
+
/**
|
|
14
|
+
* The features every agent in this collection runs with, given as instances the caller has
|
|
15
|
+
* already built and ready to serve. One instance serves the whole collection: a hook is told
|
|
16
|
+
* which agent it is running for by the scope it is handed, so any per-agent state a feature
|
|
17
|
+
* keeps in memory has to be keyed by that ID rather than held as a single value.
|
|
18
|
+
*/
|
|
19
|
+
readonly features?: readonly AgentFeature[];
|
|
20
|
+
/** The registry providers are resolved from when an agent is built. */
|
|
21
|
+
readonly providers: AgentProviders;
|
|
22
|
+
/** The registry ID of the provider new agents are created with. */
|
|
23
|
+
readonly provider: string;
|
|
24
|
+
/** The models this collection offers its agents. */
|
|
25
|
+
readonly models: readonly AgentModel[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The `AgentSystem` backed by this process: it lazily builds and owns the `Agent` instances for
|
|
29
|
+
* the identities its storage holds. Concurrent resolutions of the same ID share one load, while a
|
|
30
|
+
* failed load is forgotten so a later resolution can retry.
|
|
31
|
+
*
|
|
32
|
+
* Work serializes per agent rather than per collection: a collection-wide lock would make one
|
|
33
|
+
* agent's feature load block every other agent, including one that load itself resolves.
|
|
34
|
+
*
|
|
35
|
+
* This is the owner's handle, and some of what it offers waits for an agent to reach a point only
|
|
36
|
+
* that agent's run loop can bring it to. Hand an `AgentSystemRef` to anything running inside an
|
|
37
|
+
* agent instead.
|
|
38
|
+
*/
|
|
39
|
+
export declare class AgentSystemLocal implements AgentSystem {
|
|
40
|
+
#private;
|
|
41
|
+
/** The models this collection offers its agents. */
|
|
42
|
+
readonly models: readonly AgentModel[];
|
|
43
|
+
/**
|
|
44
|
+
* Bring up a collection over one storage and carry on where the last process left off.
|
|
45
|
+
*
|
|
46
|
+
* A collection is not a passive registry that happens to be asked for agents later: whatever
|
|
47
|
+
* was running when the previous process ended is still owed an answer, and this is what
|
|
48
|
+
* makes it happen. Every identity the storage holds is examined, and each one that owes work
|
|
49
|
+
* is resolved and resumed, so by the time this returns the collection is not merely built
|
|
50
|
+
* but running.
|
|
51
|
+
*/
|
|
52
|
+
static create(ctx: Context, storage: AgentStorage, config: AgentSystemLocalOptions): Promise<AgentSystemLocal>;
|
|
53
|
+
/**
|
|
54
|
+
* Wire this collection to its storage, providers, and feature configuration, without reading
|
|
55
|
+
* any of it. Private: a collection is brought up by `create`, which also resumes the work
|
|
56
|
+
* the storage was left holding — building one without that is building half of it.
|
|
57
|
+
*/
|
|
58
|
+
private constructor();
|
|
59
|
+
/**
|
|
60
|
+
* Stop every live agent, wait for operations already admitted by this owner, and only then
|
|
61
|
+
* release the database lock. Repeated callers join the same shutdown.
|
|
62
|
+
*/
|
|
63
|
+
close(ctx: Context): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Create an agent with the configuration it keeps for its whole life, and resolve it. The
|
|
66
|
+
* identity is allocated here and nowhere else: it is a cuid2, globally unique, so a new
|
|
67
|
+
* agent never lands on an identity that already exists or on a store something else wrote.
|
|
68
|
+
* The configuration is persisted before the agent runs, so every later process resolves the
|
|
69
|
+
* agent exactly as it was created.
|
|
70
|
+
*
|
|
71
|
+
* Nothing here is undone: an agent whose features refuse to load leaves an identity that
|
|
72
|
+
* exists, is resolvable, and will be built the next time something wants it. Taking a
|
|
73
|
+
* provisional identity back after a failed build would add a compensation that can itself
|
|
74
|
+
* fail.
|
|
75
|
+
*/
|
|
76
|
+
create(ctx: Context, config: AgentConfig, initialContext?: AgentInitialContext): Promise<Agent>;
|
|
77
|
+
/**
|
|
78
|
+
* Close an agent and release its identity, so the same ID can be created again. Used to undo
|
|
79
|
+
* a creation whose follow-up work failed; an ID that was never created is left alone.
|
|
80
|
+
*
|
|
81
|
+
* What the agent wrote is left where it is. The close finishes first, so the store holds a
|
|
82
|
+
* whole conversation rather than a truncated one, and that record is worth more here than the
|
|
83
|
+
* space it takes: whoever deleted the agent may still want to know what it did. The next
|
|
84
|
+
* identity created under this ID starts from an empty store all the same, because creation is
|
|
85
|
+
* what clears it.
|
|
86
|
+
*/
|
|
87
|
+
delete(ctx: Context, agentId: string): Promise<void>;
|
|
88
|
+
/** The configuration an agent was created with, or undefined when there is no such agent. */
|
|
89
|
+
config(ctx: Context, agentId: string): Promise<AgentConfig | undefined>;
|
|
90
|
+
/**
|
|
91
|
+
* The live agent for an ID, loading and starting it if this process has not seen it yet.
|
|
92
|
+
* Concurrent resolutions of the same ID share one load.
|
|
93
|
+
*/
|
|
94
|
+
resolve(ctx: Context, agentId: string): Promise<Agent>;
|
|
95
|
+
/** Queue a steered message for an agent. */
|
|
96
|
+
steer(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
|
|
97
|
+
/** Queue a message for an agent. */
|
|
98
|
+
send(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
|
|
99
|
+
/** Cancel an agent's active turn, leaving its queued messages durable for the next one. */
|
|
100
|
+
abort(ctx: Context, agentId: string, options?: AgentBaseAwaitOptions): Promise<void>;
|
|
101
|
+
/** Ask an agent for its conversation to be replaced by the provider's summary of it. */
|
|
102
|
+
compact(ctx: Context, agentId: string, options?: AgentBaseAwaitOptions): Promise<void>;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=AgentSystemLocal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemLocal.d.ts","sourceRoot":"","sources":["../sources/AgentSystemLocal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAElF,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7E,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,KAAK,qBAAqB,EAAE,KAAK,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAI1F,OAAO,EAAsC,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,mBAAmB,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIzE,yFAAyF;AACzF,MAAM,WAAW,uBAAuB;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;CAC1C;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAiB,YAAW,WAAW;;IAChD,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAwCvC;;;;;;;;OAQG;IACH,OAAa,MAAM,CACf,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,uBAAuB,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAe3B;IAED;;;;OAIG;IACH,OAAO,eAeN;IAED;;;OAGG;IACG,KAAK,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBvC;IAwDD;;;;;;;;;;;OAWG;IACG,MAAM,CACR,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,WAAW,EACnB,cAAc,CAAC,EAAE,mBAAmB,GACrC,OAAO,CAAC,KAAK,CAAC,CAmBhB;IAED;;;;;;;;;OASG;IACG,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzD;IAkBD,6FAA6F;IACvF,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAE5E;IAYD;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAE3D;IA8HD,4CAA4C;IACtC,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAAG,qBAAqB,GAC1D,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,oCAAoC;IAC9B,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAAG,qBAAqB,GAC1D,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,2FAA2F;IACrF,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAIzF;IAED,wFAAwF;IAClF,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAI3F;CACJ"}
|