@ixo/oracle-runtime-workers 0.41.3 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/attachments/download.ts +1 -1
- package/src/core/runtime-context.ts +2 -2
- package/src/do/ambient.ts +2 -1
- package/src/plugin-api/types.ts +4 -1
- package/src/plugins/domain-indexer/domain-indexer.plugin.ts +1 -1
- package/src/plugins/ixo-chain/http.ts +8 -4
- package/src/plugins/ixo-chain/ixo-chain.plugin.ts +14 -1
- package/src/plugins/ixo-chain/queries.ts +26 -0
- package/src/plugins/pod-creator/chain-gateway.ts +123 -31
- package/src/plugins/pod-creator/config.ts +81 -1
- package/src/plugins/pod-creator/create-session-store.ts +159 -7
- package/src/plugins/pod-creator/create-tools.ts +403 -28
- package/src/plugins/pod-creator/domain-card.ts +67 -0
- package/src/plugins/pod-creator/index.ts +24 -2
- package/src/plugins/pod-creator/ixo-chain-gateway.ts +901 -0
- package/src/plugins/pod-creator/matrix-media.ts +486 -0
- package/src/plugins/pod-creator/orchestration-tools.ts +5 -2
- package/src/plugins/pod-creator/pod-creator.plugin.ts +30 -9
- package/src/plugins/pod-creator/stage.ts +30 -0
- package/src/plugins/pod-creator/sub-agents.ts +204 -4
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { ITrxMsgSchema } from '@ixo/ixo-transaction';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
import type { RuntimeContext, UserKvSurface } from '../../plugin-api/types';
|
|
4
|
+
import type { SentPodBatch } from './chain-gateway';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* Per-(user, thread) state machine for the create path's propose → approve →
|
|
@@ -16,9 +18,13 @@ import type { RuntimeContext, UserKvSurface } from '../../plugin-api/types';
|
|
|
16
18
|
* message after seeing the batch before it can be approved, so a single model
|
|
17
19
|
* turn — steered, say, by injected text in the brief or a section — cannot run
|
|
18
20
|
* prepare → approve → sign on its own.
|
|
21
|
+
*
|
|
22
|
+
* After the commit it keeps what was sent for signing (confirmation checks
|
|
23
|
+
* the transaction against it), the POD confirmed from it, and the one domain
|
|
24
|
+
* card step that may follow.
|
|
19
25
|
*/
|
|
20
26
|
export interface CreateSessionStore {
|
|
21
|
-
/** Record a freshly prepared batch;
|
|
27
|
+
/** Record a freshly prepared batch; anything before it in the thread is superseded. */
|
|
22
28
|
prepared(
|
|
23
29
|
userDid: string,
|
|
24
30
|
threadId: string,
|
|
@@ -37,15 +43,57 @@ export interface CreateSessionStore {
|
|
|
37
43
|
requestId: string,
|
|
38
44
|
): Promise<ApproveOutcome>;
|
|
39
45
|
/**
|
|
40
|
-
* Spend the approval for a sign dispatch
|
|
41
|
-
* is the approved pending batch; the approval is cleared when it
|
|
42
|
-
* a second dispatch needs a fresh approve
|
|
46
|
+
* Spend the approval for a sign dispatch of `sent`. Returns true only when
|
|
47
|
+
* `blobId` is the approved pending batch; the approval is cleared when it
|
|
48
|
+
* matches (a second dispatch needs a fresh approve) and `sent` is recorded
|
|
49
|
+
* as what the wallet was asked to sign.
|
|
43
50
|
*/
|
|
44
|
-
consume(
|
|
45
|
-
|
|
51
|
+
consume(
|
|
52
|
+
userDid: string,
|
|
53
|
+
threadId: string,
|
|
54
|
+
blobId: string,
|
|
55
|
+
sent?: SentPodBatch,
|
|
56
|
+
): Promise<boolean>;
|
|
57
|
+
/** The thread's approval, what its last sign request carried, and the POD confirmed from it. */
|
|
58
|
+
read(
|
|
59
|
+
userDid: string,
|
|
60
|
+
threadId: string,
|
|
61
|
+
): Promise<CreateSessionView | undefined>;
|
|
62
|
+
/** Record the POD confirmed from the sent batch (no-op when nothing was sent). */
|
|
63
|
+
confirmed(
|
|
64
|
+
userDid: string,
|
|
65
|
+
threadId: string,
|
|
66
|
+
pod: { podDid: string; txHash: string },
|
|
67
|
+
): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Claim the confirmed POD's one domain card step. `no-pod` when no POD
|
|
70
|
+
* was confirmed in the thread, `claimed` when the card is being added or
|
|
71
|
+
* was added already.
|
|
72
|
+
*/
|
|
73
|
+
claimCard(userDid: string, threadId: string): Promise<CardClaim>;
|
|
74
|
+
/** End a claimed card step: `added` keeps it closed, `released` lets it run again. */
|
|
75
|
+
settleCard(
|
|
76
|
+
userDid: string,
|
|
77
|
+
threadId: string,
|
|
78
|
+
outcome: 'added' | 'released',
|
|
79
|
+
): Promise<void>;
|
|
80
|
+
/** Drop the session (the design was restarted). */
|
|
46
81
|
clear(userDid: string, threadId: string): Promise<void>;
|
|
47
82
|
}
|
|
48
83
|
|
|
84
|
+
/** The session as the create tools read it. */
|
|
85
|
+
export interface CreateSessionView {
|
|
86
|
+
/** The prepared batch while it holds an approval not spent yet. */
|
|
87
|
+
approvedBlobId?: string;
|
|
88
|
+
sent?: SentPodBatch;
|
|
89
|
+
confirmed?: { podDid: string; txHash: string };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export type CardClaim =
|
|
93
|
+
| { status: 'ok'; podDid: string; sent: SentPodBatch }
|
|
94
|
+
| { status: 'no-pod' }
|
|
95
|
+
| { status: 'claimed'; state: 'sending' | 'added' };
|
|
96
|
+
|
|
49
97
|
/** Resolves the create-session store for one request (it lives in the user's database). */
|
|
50
98
|
export type CreateSessionStoreFor = (ctx: RuntimeContext) => CreateSessionStore;
|
|
51
99
|
|
|
@@ -54,11 +102,25 @@ export type ApproveOutcome = 'approved' | 'not-prepared' | 'same-request';
|
|
|
54
102
|
/** `ctx.kv` namespace holding one create session per (user, thread). */
|
|
55
103
|
export const CREATE_SESSION_NAMESPACE = 'pod-creator/create-sessions';
|
|
56
104
|
|
|
105
|
+
const sentSchema = z.object({
|
|
106
|
+
messages: z.array(ITrxMsgSchema),
|
|
107
|
+
profile: z.object({
|
|
108
|
+
name: z.string(),
|
|
109
|
+
description: z.string().optional(),
|
|
110
|
+
}),
|
|
111
|
+
});
|
|
112
|
+
|
|
57
113
|
const createSessionSchema = z.object({
|
|
58
114
|
preparedBlobId: z.string(),
|
|
59
115
|
/** The request (turn) that prepared the batch. */
|
|
60
116
|
preparedRequestId: z.string(),
|
|
61
117
|
approved: z.boolean(),
|
|
118
|
+
/** What the last sign request of the prepared batch carried. */
|
|
119
|
+
sent: sentSchema.optional(),
|
|
120
|
+
/** The POD confirmed from `sent`. */
|
|
121
|
+
confirmed: z.object({ podDid: z.string(), txHash: z.string() }).optional(),
|
|
122
|
+
/** The confirmed POD's domain card: being added (claimed), or added. */
|
|
123
|
+
card: z.enum(['sending', 'added']).optional(),
|
|
62
124
|
});
|
|
63
125
|
|
|
64
126
|
type CreateSession = z.infer<typeof createSessionSchema>;
|
|
@@ -156,6 +218,7 @@ export class KvCreateSessionStore implements CreateSessionStore {
|
|
|
156
218
|
userDid: string,
|
|
157
219
|
threadId: string,
|
|
158
220
|
blobId: string,
|
|
221
|
+
sent?: SentPodBatch,
|
|
159
222
|
): Promise<boolean> {
|
|
160
223
|
let spent = false;
|
|
161
224
|
await this.kv.update(
|
|
@@ -167,13 +230,102 @@ export class KvCreateSessionStore implements CreateSessionStore {
|
|
|
167
230
|
session !== undefined &&
|
|
168
231
|
session.preparedBlobId === blobId &&
|
|
169
232
|
session.approved;
|
|
170
|
-
|
|
233
|
+
if (!session || !spent) return session;
|
|
234
|
+
return {
|
|
235
|
+
...session,
|
|
236
|
+
approved: false,
|
|
237
|
+
...(sent !== undefined ? { sent } : {}),
|
|
238
|
+
};
|
|
171
239
|
},
|
|
172
240
|
this.writeOptions,
|
|
173
241
|
);
|
|
174
242
|
return spent;
|
|
175
243
|
}
|
|
176
244
|
|
|
245
|
+
async read(
|
|
246
|
+
userDid: string,
|
|
247
|
+
threadId: string,
|
|
248
|
+
): Promise<CreateSessionView | undefined> {
|
|
249
|
+
const session = parseSession(
|
|
250
|
+
await this.kv.get(CREATE_SESSION_NAMESPACE, key(userDid, threadId)),
|
|
251
|
+
);
|
|
252
|
+
if (!session) return undefined;
|
|
253
|
+
return {
|
|
254
|
+
...(session.approved ? { approvedBlobId: session.preparedBlobId } : {}),
|
|
255
|
+
...(session.sent ? { sent: session.sent } : {}),
|
|
256
|
+
...(session.confirmed ? { confirmed: session.confirmed } : {}),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async confirmed(
|
|
261
|
+
userDid: string,
|
|
262
|
+
threadId: string,
|
|
263
|
+
pod: { podDid: string; txHash: string },
|
|
264
|
+
): Promise<void> {
|
|
265
|
+
await this.kv.update(
|
|
266
|
+
CREATE_SESSION_NAMESPACE,
|
|
267
|
+
key(userDid, threadId),
|
|
268
|
+
(current) => {
|
|
269
|
+
const session = parseSession(current);
|
|
270
|
+
if (!session?.sent) return session;
|
|
271
|
+
// The card belongs to the POD: another confirmed POD starts afresh.
|
|
272
|
+
const samePod = session.confirmed?.podDid === pod.podDid;
|
|
273
|
+
const { card: _card, ...rest } = session;
|
|
274
|
+
return {
|
|
275
|
+
...(samePod ? session : rest),
|
|
276
|
+
confirmed: { podDid: pod.podDid, txHash: pod.txHash },
|
|
277
|
+
};
|
|
278
|
+
},
|
|
279
|
+
this.writeOptions,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async claimCard(userDid: string, threadId: string): Promise<CardClaim> {
|
|
284
|
+
let claim: CardClaim = { status: 'no-pod' };
|
|
285
|
+
await this.kv.update(
|
|
286
|
+
CREATE_SESSION_NAMESPACE,
|
|
287
|
+
key(userDid, threadId),
|
|
288
|
+
(current) => {
|
|
289
|
+
const session = parseSession(current);
|
|
290
|
+
if (!session?.confirmed || !session.sent) {
|
|
291
|
+
claim = { status: 'no-pod' };
|
|
292
|
+
return session;
|
|
293
|
+
}
|
|
294
|
+
if (session.card) {
|
|
295
|
+
claim = { status: 'claimed', state: session.card };
|
|
296
|
+
return session;
|
|
297
|
+
}
|
|
298
|
+
claim = {
|
|
299
|
+
status: 'ok',
|
|
300
|
+
podDid: session.confirmed.podDid,
|
|
301
|
+
sent: session.sent,
|
|
302
|
+
};
|
|
303
|
+
return { ...session, card: 'sending' };
|
|
304
|
+
},
|
|
305
|
+
this.writeOptions,
|
|
306
|
+
);
|
|
307
|
+
return claim;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async settleCard(
|
|
311
|
+
userDid: string,
|
|
312
|
+
threadId: string,
|
|
313
|
+
outcome: 'added' | 'released',
|
|
314
|
+
): Promise<void> {
|
|
315
|
+
await this.kv.update(
|
|
316
|
+
CREATE_SESSION_NAMESPACE,
|
|
317
|
+
key(userDid, threadId),
|
|
318
|
+
(current) => {
|
|
319
|
+
const session = parseSession(current);
|
|
320
|
+
if (!session || session.card !== 'sending') return session;
|
|
321
|
+
if (outcome === 'added') return { ...session, card: 'added' };
|
|
322
|
+
const { card: _card, ...rest } = session;
|
|
323
|
+
return rest;
|
|
324
|
+
},
|
|
325
|
+
this.writeOptions,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
177
329
|
async clear(userDid: string, threadId: string): Promise<void> {
|
|
178
330
|
await this.kv.delete(CREATE_SESSION_NAMESPACE, key(userDid, threadId));
|
|
179
331
|
}
|