@ixo/oracle-runtime-workers 0.29.0 → 0.29.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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixo/oracle-runtime-workers",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.1",
|
|
4
4
|
"description": "QiForge oracle runtime for Cloudflare Workers — Durable Object per user (SQLite in WASM over DO storage), Matrix E2EE gateway Durable Object, Hono HTTP/SSE shell.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -65,9 +65,9 @@
|
|
|
65
65
|
"@ixo/impactxclient-sdk": "^3.0.0",
|
|
66
66
|
"protobufjs": "^7.6.5",
|
|
67
67
|
"@ixo/topic-protocol": "1.0.0-rc.8",
|
|
68
|
-
"@ixo/ixo-transaction": "0.2.0",
|
|
69
68
|
"@ixo/common": "1.7.1",
|
|
70
|
-
"@ixo/ucan": "2.3.0"
|
|
69
|
+
"@ixo/ucan": "2.3.0",
|
|
70
|
+
"@ixo/ixo-transaction": "0.2.0"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@cloudflare/vitest-pool-workers": "^0.22.0",
|
|
@@ -257,34 +257,70 @@ const memoSchema = z
|
|
|
257
257
|
.describe('An optional note shown to the owner and kept on chain.');
|
|
258
258
|
|
|
259
259
|
/**
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
* checked by the handler against its catalogue schema.
|
|
260
|
+
* A catalogue field reduced to its basic type: no descriptions, patterns or
|
|
261
|
+
* limits (those stay in describe_chain_messages and the handler's check).
|
|
263
262
|
*/
|
|
264
|
-
export function
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
export function fieldsOnly(schema: z.core.$ZodType): z.ZodType {
|
|
264
|
+
if (schema instanceof z.ZodObject)
|
|
265
|
+
return z.strictObject(
|
|
266
|
+
Object.fromEntries(
|
|
267
|
+
Object.entries(schema.shape).map(([key, field]) => [
|
|
268
|
+
key,
|
|
269
|
+
fieldsOnly(field),
|
|
270
|
+
]),
|
|
271
|
+
),
|
|
272
|
+
);
|
|
273
|
+
if (schema instanceof z.ZodOptional)
|
|
274
|
+
return fieldsOnly(schema.unwrap()).optional();
|
|
275
|
+
if (schema instanceof z.ZodArray) return z.array(fieldsOnly(schema.element));
|
|
276
|
+
if (schema instanceof z.ZodString) return z.string();
|
|
277
|
+
if (schema instanceof z.ZodNumber) return z.number();
|
|
278
|
+
if (schema instanceof z.ZodBoolean) return z.boolean();
|
|
279
|
+
if (schema instanceof z.ZodLiteral) return z.literal([...schema.values]);
|
|
280
|
+
throw new Error(
|
|
281
|
+
`No model-facing form for a ${schema._zod.def.type} field in the chain transaction catalogue`,
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* One message type as the model is given it: its field names and basic
|
|
287
|
+
* types, so a provider that holds a tool call to its schema sends every
|
|
288
|
+
* field. Loose, so a field the type does not have reaches the handler,
|
|
289
|
+
* which names it.
|
|
290
|
+
*/
|
|
291
|
+
function messageFieldsOnly(schema: z.ZodObject) {
|
|
292
|
+
return z.looseObject(
|
|
293
|
+
Object.fromEntries(
|
|
294
|
+
Object.entries(schema.shape).map(([key, field]) => [
|
|
295
|
+
key,
|
|
296
|
+
fieldsOnly(field),
|
|
297
|
+
]),
|
|
298
|
+
),
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* The schema the model is given: per type, its fields (messageFieldsOnly),
|
|
304
|
+
* so a type adds its short field list and the rules are fetched with
|
|
305
|
+
* describe_chain_messages when needed. Each message is then checked by the
|
|
306
|
+
* handler against its full catalogue schema.
|
|
307
|
+
*/
|
|
308
|
+
export function chainTransactionSchemaFor(
|
|
309
|
+
catalog: Readonly<Record<string, { schema: z.ZodObject }>>,
|
|
310
|
+
) {
|
|
311
|
+
const [first, ...rest] = Object.values(catalog).map((entry) =>
|
|
312
|
+
messageFieldsOnly(entry.schema),
|
|
313
|
+
);
|
|
314
|
+
if (!first) throw new Error('The chain transaction catalogue is empty');
|
|
267
315
|
return z.strictObject({
|
|
268
316
|
messages: z
|
|
269
|
-
.array(
|
|
270
|
-
z
|
|
271
|
-
.object({
|
|
272
|
-
type: z
|
|
273
|
-
.enum(types)
|
|
274
|
-
.describe(
|
|
275
|
-
'The message type; describe_chain_messages lists its fields.',
|
|
276
|
-
),
|
|
277
|
-
})
|
|
278
|
-
.catchall(z.unknown()),
|
|
279
|
-
)
|
|
317
|
+
.array(z.discriminatedUnion('type', [first, ...rest]))
|
|
280
318
|
.min(1)
|
|
281
319
|
.max(CHAIN_TX_MAX_MESSAGES),
|
|
282
320
|
memo: memoSchema,
|
|
283
321
|
});
|
|
284
322
|
}
|
|
285
|
-
const chainTransactionSchema = chainTransactionSchemaFor(
|
|
286
|
-
CHAIN_TX_MESSAGE_TYPES,
|
|
287
|
-
);
|
|
323
|
+
const chainTransactionSchema = chainTransactionSchemaFor(CHAIN_TX_CATALOG);
|
|
288
324
|
|
|
289
325
|
/**
|
|
290
326
|
* The request tool's description: what it does, the discovery step, one
|
|
@@ -511,22 +547,35 @@ async function requestChainTransaction(
|
|
|
511
547
|
/**
|
|
512
548
|
* Each message against its type's catalogue schema (strict: a field the
|
|
513
549
|
* type does not have, the owner's identity included, is refused). The
|
|
514
|
-
* model-facing schema only
|
|
515
|
-
*
|
|
550
|
+
* model-facing schema only names the fields and their basic types, so this
|
|
551
|
+
* is where a message's formats and limits are checked, on a model turn as on
|
|
552
|
+
* a direct call.
|
|
516
553
|
*/
|
|
517
554
|
function strictChainTxMessages(
|
|
518
|
-
messages: readonly
|
|
555
|
+
messages: readonly unknown[],
|
|
519
556
|
): { messages: ChainTxMessageInput[] } | { issues: string[] } {
|
|
520
557
|
const checked: ChainTxMessageInput[] = [];
|
|
521
558
|
const issues: string[] = [];
|
|
522
559
|
messages.forEach((message, index) => {
|
|
523
|
-
const
|
|
560
|
+
const type = chainTxTypeOf(message);
|
|
561
|
+
if (!type) {
|
|
562
|
+
issues.push(`messages[${index}].type: not a known message type`);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
const result = CHAIN_TX_CATALOG[type].schema.safeParse(message);
|
|
524
566
|
if (result.success) checked.push(result.data);
|
|
525
567
|
else issues.push(...issuesOf(result.error, ['messages', index]));
|
|
526
568
|
});
|
|
527
569
|
return issues.length ? { issues } : { messages: checked };
|
|
528
570
|
}
|
|
529
571
|
|
|
572
|
+
function chainTxTypeOf(message: unknown): ChainTxMessageType | null {
|
|
573
|
+
if (typeof message !== 'object' || message === null || !('type' in message))
|
|
574
|
+
return null;
|
|
575
|
+
const { type } = message;
|
|
576
|
+
return CHAIN_TX_MESSAGE_TYPES.find((known) => known === type) ?? null;
|
|
577
|
+
}
|
|
578
|
+
|
|
530
579
|
function chainTxShapeRefusal(
|
|
531
580
|
issues: readonly string[],
|
|
532
581
|
): HubActionRequestResult {
|