@kuralle-agents/cf-agent 0.11.0 → 0.13.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/dist/BridgeSessionStore.js +2 -0
- package/dist/KuralleAgent.d.ts +7 -1
- package/dist/KuralleAgent.js +8 -0
- package/dist/OrchestrationStore.js +14 -1
- package/dist/SqlTraceStore.d.ts +11 -0
- package/dist/SqlTraceStore.js +50 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/types.d.ts +2 -0
- package/package.json +8 -7
|
@@ -52,6 +52,7 @@ export class BridgeSessionStore {
|
|
|
52
52
|
// Restore the durable run journal so durable tools / suspend-resume can find
|
|
53
53
|
// the run (SessionRunStore reads it off the Session object).
|
|
54
54
|
session[DURABLE_RUNS_KEY] = orchState?.durableRuns ?? {};
|
|
55
|
+
session.version = orchState?.version ?? 0;
|
|
55
56
|
return session;
|
|
56
57
|
}
|
|
57
58
|
/**
|
|
@@ -72,6 +73,7 @@ export class BridgeSessionStore {
|
|
|
72
73
|
})),
|
|
73
74
|
state: session.state,
|
|
74
75
|
durableRuns: session[DURABLE_RUNS_KEY],
|
|
76
|
+
version: session.version ?? 0,
|
|
75
77
|
};
|
|
76
78
|
await this.orchestration.save(session.id, state);
|
|
77
79
|
}
|
package/dist/KuralleAgent.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { type HarnessConfig } from '@kuralle-agents/core';
|
|
|
23
23
|
import type { PersistentMemoryStore, SignalDelivery, ScheduledJob, Scheduler, WakeJobPayload } from '@kuralle-agents/core';
|
|
24
24
|
import type { StreamTextOnFinishCallback, ToolSet } from 'ai';
|
|
25
25
|
import type { OnChatMessageOptions } from '@cloudflare/ai-chat';
|
|
26
|
-
import type { StreamAdapterConfig } from './types.js';
|
|
26
|
+
import type { StreamAdapterConfig, SqlExecutor } from './types.js';
|
|
27
27
|
/**
|
|
28
28
|
* Abstract base class for running Kuralle agents on Cloudflare.
|
|
29
29
|
*
|
|
@@ -75,6 +75,12 @@ export declare abstract class KuralleAgent<Env = unknown, State = unknown> exten
|
|
|
75
75
|
* CF's AIChatAgent exposes this.sql as a tagged template function.
|
|
76
76
|
*/
|
|
77
77
|
private getSql;
|
|
78
|
+
/**
|
|
79
|
+
* The DO's SQL executor, for subclasses that need to read/write Kuralle session
|
|
80
|
+
* state out-of-band (e.g. a payment-confirmation webhook handler that runs
|
|
81
|
+
* outside a chat turn). Pair with `BridgeSessionStore` + `getDurableObjectId()`.
|
|
82
|
+
*/
|
|
83
|
+
protected getSqlExecutor(): SqlExecutor;
|
|
78
84
|
/**
|
|
79
85
|
* Get the Durable Object ID as the session identifier.
|
|
80
86
|
*/
|
package/dist/KuralleAgent.js
CHANGED
|
@@ -78,6 +78,14 @@ export class KuralleAgent extends AIChatAgent {
|
|
|
78
78
|
getSql() {
|
|
79
79
|
return durableAgentSurface(this).sql.bind(this);
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* The DO's SQL executor, for subclasses that need to read/write Kuralle session
|
|
83
|
+
* state out-of-band (e.g. a payment-confirmation webhook handler that runs
|
|
84
|
+
* outside a chat turn). Pair with `BridgeSessionStore` + `getDurableObjectId()`.
|
|
85
|
+
*/
|
|
86
|
+
getSqlExecutor() {
|
|
87
|
+
return this.getSql();
|
|
88
|
+
}
|
|
81
89
|
/**
|
|
82
90
|
* Get the Durable Object ID as the session identifier.
|
|
83
91
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StaleWriteError } from '@kuralle-agents/core';
|
|
1
2
|
/**
|
|
2
3
|
* Lightweight store for Kuralle orchestration state, keyed by session id.
|
|
3
4
|
*
|
|
@@ -54,7 +55,19 @@ export class OrchestrationStore {
|
|
|
54
55
|
}
|
|
55
56
|
async save(id, state) {
|
|
56
57
|
this.ensureTable();
|
|
57
|
-
const
|
|
58
|
+
const existing = await this.get(id);
|
|
59
|
+
const expected = state.version ?? 0;
|
|
60
|
+
if (existing) {
|
|
61
|
+
const stored = existing.version ?? 0;
|
|
62
|
+
if (stored !== expected) {
|
|
63
|
+
throw new StaleWriteError(id, expected, stored);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else if (expected !== 0) {
|
|
67
|
+
throw new StaleWriteError(id, expected, 0);
|
|
68
|
+
}
|
|
69
|
+
const toSave = { ...state, version: expected + 1 };
|
|
70
|
+
const json = JSON.stringify(toSave);
|
|
58
71
|
this.sql `
|
|
59
72
|
INSERT INTO kuralle_orchestration (id, state, updated_at)
|
|
60
73
|
VALUES (${id}, ${json}, datetime('now'))
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AgentSpan, AgentTrace, TraceListWindow, TraceStore } from '@kuralle-agents/core';
|
|
2
|
+
import type { SqlExecutor } from './types.js';
|
|
3
|
+
export declare class SqlTraceStore implements TraceStore {
|
|
4
|
+
private readonly sql;
|
|
5
|
+
constructor(sql: SqlExecutor);
|
|
6
|
+
write(span: AgentSpan): void;
|
|
7
|
+
putSpan(span: AgentSpan): void;
|
|
8
|
+
getTrace(traceId: string): Promise<AgentTrace | null>;
|
|
9
|
+
listTraces(sessionId: string, window?: TraceListWindow): Promise<AgentTrace[]>;
|
|
10
|
+
cleanup(maxAgeMs: number): Promise<number>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { traceFromSpans } from '@kuralle-agents/core/tracing';
|
|
2
|
+
export class SqlTraceStore {
|
|
3
|
+
sql;
|
|
4
|
+
constructor(sql) {
|
|
5
|
+
this.sql = sql;
|
|
6
|
+
this.sql `CREATE TABLE IF NOT EXISTS kuralle_trace_spans (
|
|
7
|
+
trace_id TEXT NOT NULL,
|
|
8
|
+
span_id TEXT NOT NULL,
|
|
9
|
+
session_id TEXT NOT NULL,
|
|
10
|
+
started_at INTEGER NOT NULL,
|
|
11
|
+
payload TEXT NOT NULL,
|
|
12
|
+
PRIMARY KEY (trace_id, span_id)
|
|
13
|
+
)`;
|
|
14
|
+
this.sql `CREATE INDEX IF NOT EXISTS kuralle_trace_session_started_idx
|
|
15
|
+
ON kuralle_trace_spans (session_id, started_at DESC)`;
|
|
16
|
+
}
|
|
17
|
+
write(span) { this.putSpan(span); }
|
|
18
|
+
putSpan(span) {
|
|
19
|
+
this.sql `INSERT INTO kuralle_trace_spans (trace_id, span_id, session_id, started_at, payload)
|
|
20
|
+
VALUES (${span.traceId}, ${span.spanId}, ${span.attributes.sessionId}, ${span.startTime}, ${JSON.stringify(span)})
|
|
21
|
+
ON CONFLICT(trace_id, span_id) DO UPDATE SET
|
|
22
|
+
session_id = excluded.session_id, started_at = excluded.started_at, payload = excluded.payload`;
|
|
23
|
+
}
|
|
24
|
+
async getTrace(traceId) {
|
|
25
|
+
const rows = this.sql `SELECT trace_id, payload FROM kuralle_trace_spans
|
|
26
|
+
WHERE trace_id = ${traceId} ORDER BY started_at ASC`;
|
|
27
|
+
return traceFromSpans(rows.map((row) => JSON.parse(row.payload)));
|
|
28
|
+
}
|
|
29
|
+
async listTraces(sessionId, window) {
|
|
30
|
+
const from = window?.from?.getTime() ?? 0;
|
|
31
|
+
const to = window?.to?.getTime() ?? Number.MAX_SAFE_INTEGER;
|
|
32
|
+
const limit = window?.limit ?? 100;
|
|
33
|
+
const rows = this.sql `SELECT trace_id, MIN(started_at) AS started_at
|
|
34
|
+
FROM kuralle_trace_spans WHERE session_id = ${sessionId}
|
|
35
|
+
GROUP BY trace_id HAVING MIN(started_at) >= ${from} AND MIN(started_at) <= ${to}
|
|
36
|
+
ORDER BY started_at DESC LIMIT ${limit}`;
|
|
37
|
+
const traces = await Promise.all(rows.map((row) => this.getTrace(row.trace_id)));
|
|
38
|
+
return traces.filter((trace) => trace !== null);
|
|
39
|
+
}
|
|
40
|
+
async cleanup(maxAgeMs) {
|
|
41
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
42
|
+
const before = this.sql `SELECT COUNT(*) AS count FROM (
|
|
43
|
+
SELECT trace_id FROM kuralle_trace_spans GROUP BY trace_id HAVING MIN(started_at) < ${cutoff}
|
|
44
|
+
)`[0]?.count ?? 0;
|
|
45
|
+
this.sql `DELETE FROM kuralle_trace_spans WHERE trace_id IN (
|
|
46
|
+
SELECT trace_id FROM kuralle_trace_spans GROUP BY trace_id HAVING MIN(started_at) < ${cutoff}
|
|
47
|
+
)`;
|
|
48
|
+
return Number(before);
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export { KuralleAgent, KuralleAgent as CfChatAgent } from './KuralleAgent.js';
|
|
|
27
27
|
export { BridgeSessionStore } from './BridgeSessionStore.js';
|
|
28
28
|
export { OrchestrationStore } from './OrchestrationStore.js';
|
|
29
29
|
export { SqlPersistentMemoryStore } from './SqlPersistentMemoryStore.js';
|
|
30
|
+
export { SqlTraceStore } from './SqlTraceStore.js';
|
|
30
31
|
export { createSqlExecutor } from './sqlExecutor.js';
|
|
31
32
|
export { createSSEResponse } from './StreamAdapter.js';
|
|
32
33
|
export { lastUserInputFromMessages } from './cfMessageInput.js';
|
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export { KuralleAgent, KuralleAgent as CfChatAgent } from './KuralleAgent.js';
|
|
|
27
27
|
export { BridgeSessionStore } from './BridgeSessionStore.js';
|
|
28
28
|
export { OrchestrationStore } from './OrchestrationStore.js';
|
|
29
29
|
export { SqlPersistentMemoryStore } from './SqlPersistentMemoryStore.js';
|
|
30
|
+
export { SqlTraceStore } from './SqlTraceStore.js';
|
|
30
31
|
export { createSqlExecutor } from './sqlExecutor.js';
|
|
31
32
|
export { createSSEResponse } from './StreamAdapter.js';
|
|
32
33
|
export { lastUserInputFromMessages } from './cfMessageInput.js';
|
package/dist/types.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface OrchestrationState {
|
|
|
35
35
|
* with "Run not found" on CF.
|
|
36
36
|
*/
|
|
37
37
|
durableRuns?: SessionDurableRuns;
|
|
38
|
+
/** Optimistic-concurrency version for orchestration row CAS (C2). */
|
|
39
|
+
version?: number;
|
|
38
40
|
}
|
|
39
41
|
/**
|
|
40
42
|
* Configuration for the stream adapter.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kuralle-agents/cf-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Kuralle agent integration for Cloudflare Workers with AIChatAgent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,21 +21,22 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@cloudflare/ai-chat": "^0.8.4",
|
|
23
23
|
"ai": "^6.0.90",
|
|
24
|
-
"@kuralle-agents/core": "0.
|
|
25
|
-
"@kuralle-agents/
|
|
26
|
-
"@kuralle-agents/
|
|
24
|
+
"@kuralle-agents/core": "0.13.0",
|
|
25
|
+
"@kuralle-agents/realtime-audio": "0.13.0",
|
|
26
|
+
"@kuralle-agents/messaging": "0.13.0"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"agents": ">=0.14.0 <1.0.0",
|
|
30
30
|
"zod": "^4.0.0",
|
|
31
|
-
"@kuralle-agents/voice-protocol": "0.
|
|
31
|
+
"@kuralle-agents/voice-protocol": "0.13.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@cloudflare/vitest-pool-workers": "^0.12.7",
|
|
35
|
+
"@cloudflare/workers-types": "^4.0.0",
|
|
35
36
|
"agents": "^0.15.0",
|
|
36
37
|
"typescript": "^5.7.0",
|
|
37
38
|
"vitest": "^3.2.4",
|
|
38
|
-
"@kuralle-agents/voice-protocol": "0.
|
|
39
|
+
"@kuralle-agents/voice-protocol": "0.13.0"
|
|
39
40
|
},
|
|
40
41
|
"engines": {
|
|
41
42
|
"node": ">=20"
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
"repository": {
|
|
54
55
|
"type": "git",
|
|
55
56
|
"url": "git+https://github.com/kuralle/kuralle-agents.git",
|
|
56
|
-
"directory": "packages/
|
|
57
|
+
"directory": "packages/cf-agent"
|
|
57
58
|
},
|
|
58
59
|
"scripts": {
|
|
59
60
|
"prebuild": "rm -rf dist",
|