@ixo/oracle-runtime-workers 0.30.0 → 0.32.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/package.json +7 -5
- package/src/attachments/channel-links.ts +135 -0
- package/src/attachments/channel.ts +203 -0
- package/src/attachments/download.ts +23 -6
- package/src/attachments/index.ts +23 -0
- package/src/attachments/pipeline.ts +120 -42
- package/src/attachments/retention.ts +11 -3
- package/src/attachments/sanitize.ts +20 -8
- package/src/attachments/types.ts +7 -0
- package/src/attachments/view.ts +24 -7
- package/src/channels/contract.ts +69 -0
- package/src/channels/turns.ts +23 -1
- package/src/core/main-agent-types.ts +2 -0
- package/src/core/middlewares/tool-repetition-guard.ts +6 -3
- package/src/core/middlewares/turn-boundary.ts +6 -1
- package/src/core/runtime-context.ts +3 -0
- package/src/core/tool-not-run.ts +30 -0
- package/src/core/wrap-plugin-tool.ts +9 -1
- package/src/delivery/plan.ts +3 -1
- package/src/do/contracts.ts +3 -0
- package/src/do/turn-attachments.ts +103 -0
- package/src/do/user-oracle-do.ts +220 -57
- package/src/hub-actions/chain-tx-refusals.ts +217 -0
- package/src/hub-actions/client.ts +170 -26
- package/src/hub-actions/hub-text.ts +82 -0
- package/src/hub-actions/request.ts +39 -29
- package/src/hub-actions/store.ts +5 -1
- package/src/hub-actions/transfer.ts +99 -32
- package/src/index.ts +1 -0
- package/src/plugin-api/index.ts +1 -0
- package/src/plugin-api/types.ts +102 -20
- package/src/plugins/attachments/view-attachment-tool.ts +7 -3
- package/src/plugins/hub-actions/chain-tx-catalog.ts +1239 -0
- package/src/plugins/hub-actions/hub-actions.plugin.ts +490 -232
- package/src/plugins/ixo-chain/blocksync.ts +6 -2
- package/src/plugins/ixo-chain/http.ts +16 -8
- package/src/plugins/ixo-chain/ixo-chain.plugin.ts +1 -1
- package/src/plugins/ixo-chain/kinds/chain/index.ts +2 -0
- package/src/plugins/ixo-chain/kinds/chain/validators.ts +151 -0
- package/src/plugins/ixo-chain/rest.ts +7 -1
- package/src/plugins/yoma/catalog.ts +780 -0
- package/src/plugins/yoma/clef.ts +98 -0
- package/src/plugins/yoma/drafts.ts +339 -0
- package/src/plugins/yoma/engine.ts +978 -0
- package/src/plugins/yoma/index.ts +13 -0
- package/src/plugins/yoma/judge.ts +358 -0
- package/src/plugins/yoma/permission.ts +62 -0
- package/src/plugins/yoma/reads.ts +195 -0
- package/src/plugins/yoma/submission.ts +531 -0
- package/src/plugins/yoma/text.ts +16 -0
- package/src/plugins/yoma/work.ts +190 -0
- package/src/plugins/yoma/yoma.plugin.ts +2171 -0
- package/src/sqlite/serialization.ts +2 -0
package/src/do/user-oracle-do.ts
CHANGED
|
@@ -46,11 +46,15 @@ import type {
|
|
|
46
46
|
ActionProposalSubject,
|
|
47
47
|
} from '@ixo/ixo-transaction/action-proposals';
|
|
48
48
|
import { ChannelTurns } from '../channels/turns';
|
|
49
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
HubActionClient,
|
|
51
|
+
type HubOperationStatus,
|
|
52
|
+
type HubReviewStatus,
|
|
53
|
+
} from '../hub-actions/client';
|
|
50
54
|
import { chainTxOperation, prepareHubAction } from '../hub-actions/request';
|
|
51
55
|
import {
|
|
52
56
|
bankReceiptSummary,
|
|
53
|
-
|
|
57
|
+
chainTxAmountsInBaseUnits,
|
|
54
58
|
} from '../hub-actions/transfer';
|
|
55
59
|
import {
|
|
56
60
|
HUB_CHECK_AFTER_EXPIRY_MS,
|
|
@@ -126,6 +130,7 @@ import {
|
|
|
126
130
|
offloadInlinePayloads,
|
|
127
131
|
parseAttachmentInputs,
|
|
128
132
|
prepareAttachments,
|
|
133
|
+
ChannelAttachmentLinkStore,
|
|
129
134
|
type AttachmentViewSurface,
|
|
130
135
|
type MatrixMediaSource,
|
|
131
136
|
type ViewAttachmentDeps,
|
|
@@ -135,6 +140,12 @@ import {
|
|
|
135
140
|
readBytesCapped,
|
|
136
141
|
AttachmentTextCacheStore,
|
|
137
142
|
} from '../attachments';
|
|
143
|
+
import {
|
|
144
|
+
channelTurnLinks,
|
|
145
|
+
prepareTurnAttachments,
|
|
146
|
+
turnAttachmentInputs,
|
|
147
|
+
turnChannelMediaSource,
|
|
148
|
+
} from './turn-attachments';
|
|
138
149
|
import type { RuntimeCore } from '../core';
|
|
139
150
|
import {
|
|
140
151
|
createLlmAdapter,
|
|
@@ -430,6 +441,7 @@ import {
|
|
|
430
441
|
} from './ucan-service';
|
|
431
442
|
import type {
|
|
432
443
|
ChainTxMessageInput,
|
|
444
|
+
HubActionStatusRead,
|
|
433
445
|
UcanDelegation,
|
|
434
446
|
UserContextData,
|
|
435
447
|
} from '../plugin-api/types';
|
|
@@ -564,6 +576,7 @@ function hasUserContext(value: unknown): boolean {
|
|
|
564
576
|
function admissionApplies(req: TurnRequest): boolean {
|
|
565
577
|
return (
|
|
566
578
|
!req.attachments?.length &&
|
|
579
|
+
!req.channel?.attachments?.length &&
|
|
567
580
|
!req.taskRunId &&
|
|
568
581
|
!req.sessionId.startsWith(TASK_SESSION_PREFIX) &&
|
|
569
582
|
req.roomKind !== 'group'
|
|
@@ -625,6 +638,14 @@ const ACTION_TICK_BUDGET_MS = 15_000;
|
|
|
625
638
|
const ACTION_PRUNE_INTERVAL_MS = 60 * 60_000;
|
|
626
639
|
/** How long the Hub's capabilities answer is reused per object. */
|
|
627
640
|
const HUB_CAPABILITIES_CACHE_MS = 60_000;
|
|
641
|
+
/**
|
|
642
|
+
* A capabilities read on a turn's critical path (the chain transaction
|
|
643
|
+
* tool's types): a short timeout, and after a failed read none for this
|
|
644
|
+
* long, so a slow or failing Hub costs a turn at most this timeout once per
|
|
645
|
+
* window instead of the full Hub timeout on every turn.
|
|
646
|
+
*/
|
|
647
|
+
const HUB_TURN_CAPABILITIES_TIMEOUT_MS = 3_000;
|
|
648
|
+
const HUB_CAPABILITIES_FAILURE_CACHE_MS = 30_000;
|
|
628
649
|
/** A Hub network name as the chain-id config key it is configured under. */
|
|
629
650
|
/**
|
|
630
651
|
* Whether two Hub outcomes are the same event. Receipts are compared in the
|
|
@@ -1041,11 +1062,17 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
1041
1062
|
private actionProposals: ActionProposalStore | null = null;
|
|
1042
1063
|
private hubActionStore: HubActionStore | null = null;
|
|
1043
1064
|
private hubActionClient: HubActionClient | null = null;
|
|
1044
|
-
/** The Hub's capabilities for this oracle account, reused for `HUB_CAPABILITIES_CACHE_MS
|
|
1065
|
+
/** The Hub's capabilities for this oracle account, reused for `HUB_CAPABILITIES_CACHE_MS` (and on a turn, while a read fails). */
|
|
1045
1066
|
private hubCapabilities: {
|
|
1046
1067
|
value: ActionCapabilitiesV1;
|
|
1047
1068
|
at: number;
|
|
1048
1069
|
} | null = null;
|
|
1070
|
+
/** The last failed capabilities read: a turn does not read again within `HUB_CAPABILITIES_FAILURE_CACHE_MS`. */
|
|
1071
|
+
private hubCapabilitiesFailure: { error: unknown; at: number } | null =
|
|
1072
|
+
null;
|
|
1073
|
+
/** A turn's capabilities read in flight, shared by concurrent turns. */
|
|
1074
|
+
private hubTurnCapabilitiesRead: Promise<ActionCapabilitiesV1> | null =
|
|
1075
|
+
null;
|
|
1049
1076
|
/** The last `hub_action_options` answer for this owner (Gmail connection checks). */
|
|
1050
1077
|
private lastHubOptions: {
|
|
1051
1078
|
value: HubActionOptionsV2 | HubActionOptionsV3;
|
|
@@ -1058,6 +1085,8 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
1058
1085
|
private lastActionPruneAt: number | null = null;
|
|
1059
1086
|
/** Text `view_attachment` extracted, per session (`attachments/view-cache.ts`). */
|
|
1060
1087
|
private attachmentTextCache: AttachmentTextCacheStore | null = null;
|
|
1088
|
+
/** The links behind the `channel:` references of each session's files. */
|
|
1089
|
+
private channelAttachmentLinks: ChannelAttachmentLinkStore | null = null;
|
|
1061
1090
|
/** Large texts of document ingestion, in memory (a few, minutes). */
|
|
1062
1091
|
private readonly ingestTextLru = new IngestTextLru();
|
|
1063
1092
|
/**
|
|
@@ -2019,6 +2048,10 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
2019
2048
|
});
|
|
2020
2049
|
await this.resultStore.setup();
|
|
2021
2050
|
this.attachmentTextCache = new AttachmentTextCacheStore(liveDb, console);
|
|
2051
|
+
this.channelAttachmentLinks = new ChannelAttachmentLinkStore(
|
|
2052
|
+
liveDb,
|
|
2053
|
+
console,
|
|
2054
|
+
);
|
|
2022
2055
|
// Constructing it touches no SQL. Only an observe turn records (and so
|
|
2023
2056
|
// creates `domain_context_runs`); a session delete never creates it but
|
|
2024
2057
|
// still removes rows an earlier observe deployment left behind.
|
|
@@ -2258,7 +2291,10 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
2258
2291
|
...(this.hubActionStore && this.hubActionClient
|
|
2259
2292
|
? {
|
|
2260
2293
|
hubActions: {
|
|
2261
|
-
capabilities: () =>
|
|
2294
|
+
capabilities: (opts) =>
|
|
2295
|
+
opts?.turn
|
|
2296
|
+
? this.turnHubCapabilities()
|
|
2297
|
+
: this.cachedHubCapabilities(),
|
|
2262
2298
|
options: (input) => this.hubActionOptions(input),
|
|
2263
2299
|
request: (input: {
|
|
2264
2300
|
ownerDid: string;
|
|
@@ -2273,8 +2309,11 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
2273
2309
|
}) => this.requestHubAction(input),
|
|
2274
2310
|
chainTransaction: (input) =>
|
|
2275
2311
|
this.chainTransactionHubAction(input),
|
|
2276
|
-
status: (
|
|
2277
|
-
|
|
2312
|
+
status: (
|
|
2313
|
+
ownerDid: string,
|
|
2314
|
+
actionId: string,
|
|
2315
|
+
opts?: { timeoutMs?: number },
|
|
2316
|
+
) => this.hubActionStatusForTool(ownerDid, actionId, opts),
|
|
2278
2317
|
},
|
|
2279
2318
|
}
|
|
2280
2319
|
: {}),
|
|
@@ -2363,9 +2402,12 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
2363
2402
|
this.hubActionStore = null;
|
|
2364
2403
|
this.hubActionClient = null;
|
|
2365
2404
|
this.hubCapabilities = null;
|
|
2405
|
+
this.hubCapabilitiesFailure = null;
|
|
2406
|
+
this.hubTurnCapabilitiesRead = null;
|
|
2366
2407
|
this.lastHubOptions = null;
|
|
2367
2408
|
this.topicProposals = null;
|
|
2368
2409
|
this.attachmentTextCache = null;
|
|
2410
|
+
this.channelAttachmentLinks = null;
|
|
2369
2411
|
this.domainContextStore = null;
|
|
2370
2412
|
// Its store is bound to the database just dropped: a caller that sees
|
|
2371
2413
|
// no scheduler boots again instead of reading a closed connection.
|
|
@@ -3329,7 +3371,10 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3329
3371
|
// The gateway parses with @ixo/action-protocol 0.4.1, whose bank
|
|
3330
3372
|
// receipt is exact: the 0.5.0 `denom`/`amountBaseUnits` fields are
|
|
3331
3373
|
// dropped here (the owner-facing amount line comes from
|
|
3332
|
-
// hub_action_status instead), so the emitted shape stays 0.4.1.
|
|
3374
|
+
// hub_action_status instead), so the emitted shape stays 0.4.1. Every
|
|
3375
|
+
// other receipt goes as Auth Hub signed it, a failure's `detail`
|
|
3376
|
+
// included: the gateway confirms an outcome by comparing the whole
|
|
3377
|
+
// receipt with Auth Hub's copy. Only what the model sees drops it.
|
|
3333
3378
|
const hubActionOutcomes = (
|
|
3334
3379
|
await this.hubOutcomesForRun(ownerDid, result.sessionId, result.runId)
|
|
3335
3380
|
).map((outcome) => ({ ...outcome, receipt: v1Receipt(outcome.receipt) }));
|
|
@@ -3498,16 +3543,57 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3498
3543
|
}
|
|
3499
3544
|
|
|
3500
3545
|
/** The Hub's capabilities, cached per object for `HUB_CAPABILITIES_CACHE_MS`. */
|
|
3501
|
-
private async cachedHubCapabilities(
|
|
3546
|
+
private async cachedHubCapabilities(
|
|
3547
|
+
timeoutMs?: number,
|
|
3548
|
+
): Promise<ActionCapabilitiesV1> {
|
|
3502
3549
|
const client = this.hubActionClient;
|
|
3503
3550
|
if (!client) throw new Error('Hub actions are unavailable');
|
|
3504
3551
|
const now = Date.now();
|
|
3505
3552
|
const cached = this.hubCapabilities ?? null;
|
|
3506
3553
|
if (cached && now - cached.at < HUB_CAPABILITIES_CACHE_MS)
|
|
3507
3554
|
return cached.value;
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3555
|
+
try {
|
|
3556
|
+
const value = await client.capabilities(timeoutMs);
|
|
3557
|
+
this.hubCapabilities = { value, at: Date.now() };
|
|
3558
|
+
this.hubCapabilitiesFailure = null;
|
|
3559
|
+
return value;
|
|
3560
|
+
} catch (error) {
|
|
3561
|
+
this.hubCapabilitiesFailure = { error, at: Date.now() };
|
|
3562
|
+
throw error;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
/**
|
|
3567
|
+
* The capabilities for a turn's tool list: the cached ones while fresh;
|
|
3568
|
+
* else one read with `HUB_TURN_CAPABILITIES_TIMEOUT_MS`, shared by
|
|
3569
|
+
* concurrent turns and not repeated within
|
|
3570
|
+
* `HUB_CAPABILITIES_FAILURE_CACHE_MS` of a failed read. While reads
|
|
3571
|
+
* fail, the last capabilities read are answered (the Hub enforces its
|
|
3572
|
+
* own on every prepare); with none, the failure.
|
|
3573
|
+
*/
|
|
3574
|
+
private async turnHubCapabilities(): Promise<ActionCapabilitiesV1> {
|
|
3575
|
+
const cached = this.hubCapabilities;
|
|
3576
|
+
if (cached && Date.now() - cached.at < HUB_CAPABILITIES_CACHE_MS)
|
|
3577
|
+
return cached.value;
|
|
3578
|
+
const failure = this.hubCapabilitiesFailure;
|
|
3579
|
+
if (
|
|
3580
|
+
failure &&
|
|
3581
|
+
Date.now() - failure.at < HUB_CAPABILITIES_FAILURE_CACHE_MS
|
|
3582
|
+
) {
|
|
3583
|
+
if (cached) return cached.value;
|
|
3584
|
+
throw failure.error;
|
|
3585
|
+
}
|
|
3586
|
+
this.hubTurnCapabilitiesRead ??= this.cachedHubCapabilities(
|
|
3587
|
+
HUB_TURN_CAPABILITIES_TIMEOUT_MS,
|
|
3588
|
+
).finally(() => {
|
|
3589
|
+
this.hubTurnCapabilitiesRead = null;
|
|
3590
|
+
});
|
|
3591
|
+
try {
|
|
3592
|
+
return await this.hubTurnCapabilitiesRead;
|
|
3593
|
+
} catch (error) {
|
|
3594
|
+
if (cached) return cached.value;
|
|
3595
|
+
throw error;
|
|
3596
|
+
}
|
|
3511
3597
|
}
|
|
3512
3598
|
|
|
3513
3599
|
/**
|
|
@@ -3560,13 +3646,14 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3560
3646
|
/**
|
|
3561
3647
|
* One chain transaction of the model's messages. The network is the
|
|
3562
3648
|
* account's capability, the chain id this Worker's own for that
|
|
3563
|
-
* network; the signer and the owner's identity in
|
|
3649
|
+
* network; the signer and the owner's identity in the messages come
|
|
3564
3650
|
* from the owner's DID (`chainTxOperation`). The model names none of
|
|
3565
|
-
* them. Bank steps name a listed token and a display amount
|
|
3566
|
-
*
|
|
3567
|
-
* must be current), and each
|
|
3568
|
-
* checked against the listed
|
|
3569
|
-
* is sent: the Hub
|
|
3651
|
+
* them. Bank steps name a listed token and a display amount, stake
|
|
3652
|
+
* steps an amount of IXO: with at least one of either, the owner's
|
|
3653
|
+
* options are read once, fresh (the balances must be current), and each
|
|
3654
|
+
* amount is converted to base units and checked against the listed
|
|
3655
|
+
* balance (`chainTxAmountsInBaseUnits`). No fee is sent: the Hub
|
|
3656
|
+
* simulates gas and sets it.
|
|
3570
3657
|
*/
|
|
3571
3658
|
private async chainTransactionHubAction(input: {
|
|
3572
3659
|
ownerDid: string;
|
|
@@ -3598,7 +3685,9 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3598
3685
|
HUB_NETWORK_CHAIN[capabilities.network]
|
|
3599
3686
|
];
|
|
3600
3687
|
const tokens = input.messages.some(
|
|
3601
|
-
(message) =>
|
|
3688
|
+
(message) =>
|
|
3689
|
+
message.type === 'cosmos.bank.send' ||
|
|
3690
|
+
message.type === 'cosmos.staking.delegate',
|
|
3602
3691
|
)
|
|
3603
3692
|
? ((await this.hubActionOptions(input, true)).transfer?.tokens ?? null)
|
|
3604
3693
|
: null;
|
|
@@ -3607,30 +3696,64 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3607
3696
|
chainId,
|
|
3608
3697
|
network: capabilities.network,
|
|
3609
3698
|
memo: input.memo,
|
|
3610
|
-
messages:
|
|
3699
|
+
messages: chainTxAmountsInBaseUnits(input.messages, tokens),
|
|
3611
3700
|
});
|
|
3612
3701
|
return this.requestHubAction({ ...input, operation }, true);
|
|
3613
3702
|
}
|
|
3614
3703
|
|
|
3615
3704
|
/**
|
|
3616
|
-
* `
|
|
3617
|
-
*
|
|
3705
|
+
* `ctx.hubActions.status` (and `hub_action_status`): Auth Hub's review
|
|
3706
|
+
* and operation status, the outcome and, for a bank send, the
|
|
3707
|
+
* owner-facing line (amount from the token stored at preparation). An
|
|
3708
|
+
* action this object never prepared is `held: false`, without a Hub
|
|
3709
|
+
* read.
|
|
3618
3710
|
*/
|
|
3619
3711
|
private async hubActionStatusForTool(
|
|
3620
3712
|
ownerDid: string,
|
|
3621
3713
|
actionId: string,
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3714
|
+
opts: { timeoutMs?: number } = {},
|
|
3715
|
+
): Promise<HubActionStatusRead> {
|
|
3716
|
+
const read = await this.statusHubAction(
|
|
3717
|
+
ownerDid,
|
|
3718
|
+
actionId,
|
|
3719
|
+
opts.timeoutMs,
|
|
3720
|
+
);
|
|
3721
|
+
if (!read)
|
|
3722
|
+
return {
|
|
3723
|
+
held: false,
|
|
3724
|
+
reviewStatus: null,
|
|
3725
|
+
operationStatus: null,
|
|
3726
|
+
outcome: null,
|
|
3727
|
+
summary: null,
|
|
3728
|
+
};
|
|
3729
|
+
const token = read.outcome
|
|
3730
|
+
? await this.hubActionStore!.token(ownerDid, actionId)
|
|
3731
|
+
: null;
|
|
3732
|
+
return {
|
|
3733
|
+
held: true,
|
|
3734
|
+
reviewStatus: read.reviewStatus,
|
|
3735
|
+
operationStatus: read.operationStatus,
|
|
3736
|
+
outcome: read.outcome,
|
|
3737
|
+
summary: read.outcome
|
|
3738
|
+
? bankReceiptSummary(read.outcome.receipt, token)
|
|
3739
|
+
: null,
|
|
3740
|
+
};
|
|
3627
3741
|
}
|
|
3628
3742
|
|
|
3743
|
+
/**
|
|
3744
|
+
* One authenticated status read of a held action (null: not held), its
|
|
3745
|
+
* outcome recorded when new. An outcome for another revision than the
|
|
3746
|
+
* one Auth Hub reports is not taken (`outcome: null`).
|
|
3747
|
+
*/
|
|
3629
3748
|
private async statusHubAction(
|
|
3630
3749
|
ownerDid: string,
|
|
3631
3750
|
actionId: string,
|
|
3632
3751
|
timeoutMs?: number,
|
|
3633
|
-
): Promise<
|
|
3752
|
+
): Promise<{
|
|
3753
|
+
reviewStatus: HubReviewStatus;
|
|
3754
|
+
operationStatus: HubOperationStatus;
|
|
3755
|
+
outcome: ActionOutcomeV1 | null;
|
|
3756
|
+
} | null> {
|
|
3634
3757
|
const held = await this.hubActionStore?.get(ownerDid, actionId);
|
|
3635
3758
|
if (!held || !this.hubActionClient) return null;
|
|
3636
3759
|
const status = await this.hubActionClient.status(actionId, timeoutMs);
|
|
@@ -3639,16 +3762,20 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3639
3762
|
canonicalJson(status.reference) !== canonicalJson(held.reference)
|
|
3640
3763
|
)
|
|
3641
3764
|
throw new Error('Hub status does not match the prepared action');
|
|
3765
|
+
const read = {
|
|
3766
|
+
reviewStatus: status.reviewStatus,
|
|
3767
|
+
operationStatus: status.operationStatus,
|
|
3768
|
+
};
|
|
3642
3769
|
if (status.outcome) {
|
|
3643
3770
|
if (
|
|
3644
3771
|
status.revision !== status.outcome.authorizedRevision ||
|
|
3645
3772
|
status.digest !== status.outcome.authorizedDigest
|
|
3646
3773
|
)
|
|
3647
|
-
return null;
|
|
3774
|
+
return { ...read, outcome: null };
|
|
3648
3775
|
if (await this.hubActionStore!.recordOutcome(status.outcome))
|
|
3649
3776
|
this.markDirty();
|
|
3650
3777
|
}
|
|
3651
|
-
return status.outcome;
|
|
3778
|
+
return { ...read, outcome: status.outcome };
|
|
3652
3779
|
}
|
|
3653
3780
|
|
|
3654
3781
|
/**
|
|
@@ -3687,11 +3814,13 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3687
3814
|
// refreshed writes it, at most one per poll.
|
|
3688
3815
|
this.markDirty();
|
|
3689
3816
|
try {
|
|
3690
|
-
const fresh =
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3817
|
+
const fresh = (
|
|
3818
|
+
await this.statusHubAction(
|
|
3819
|
+
ownerDid,
|
|
3820
|
+
row.reference.id,
|
|
3821
|
+
HUB_POLL_TIMEOUT_MS,
|
|
3822
|
+
)
|
|
3823
|
+
)?.outcome;
|
|
3695
3824
|
if (fresh && (!latest || fresh.sequence > latest.sequence))
|
|
3696
3825
|
latest = fresh;
|
|
3697
3826
|
} catch (error) {
|
|
@@ -3848,6 +3977,13 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
3848
3977
|
`[user-do] could not delete the cached attachment text of ${sessionId}: ${err instanceof Error ? err.message : String(err)}`,
|
|
3849
3978
|
);
|
|
3850
3979
|
});
|
|
3980
|
+
await this.channelAttachmentLinks
|
|
3981
|
+
?.forgetSession(sessionId)
|
|
3982
|
+
.catch((err: unknown) => {
|
|
3983
|
+
console.warn(
|
|
3984
|
+
`[user-do] could not delete the channel file links of ${sessionId}; they expire with the links: ${err instanceof Error ? err.message : String(err)}`,
|
|
3985
|
+
);
|
|
3986
|
+
});
|
|
3851
3987
|
await this.resultStore
|
|
3852
3988
|
?.deleteForSession(sessionId)
|
|
3853
3989
|
.catch((err: unknown) => {
|
|
@@ -7038,6 +7174,8 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
7038
7174
|
signal: AbortSignal;
|
|
7039
7175
|
/** Attachments of the turn now running (not necessarily persisted yet). */
|
|
7040
7176
|
turnMetas: readonly AttachmentMeta[];
|
|
7177
|
+
/** The links of this turn's channel files (earlier ones come from the store). */
|
|
7178
|
+
channelLinks: ReturnType<typeof channelTurnLinks>;
|
|
7041
7179
|
}): Promise<AttachmentViewSurface> {
|
|
7042
7180
|
const saver = this.saver!;
|
|
7043
7181
|
const offloaded = await saver.hasThreadMessageMatching(input.sessionId, {
|
|
@@ -7048,6 +7186,12 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
7048
7186
|
findPersistedAttachmentMeta(saver, input.sessionId, ref);
|
|
7049
7187
|
const viewDeps = (): ViewAttachmentDeps => ({
|
|
7050
7188
|
source: this.matrixMediaSource(),
|
|
7189
|
+
channel: turnChannelMediaSource({
|
|
7190
|
+
sessionId: input.sessionId,
|
|
7191
|
+
turnLinks: input.channelLinks,
|
|
7192
|
+
store: this.channelAttachmentLinks,
|
|
7193
|
+
channelServiceDid: this.env.CHANNEL_SERVICE_DID,
|
|
7194
|
+
}),
|
|
7051
7195
|
extraction: this.extractionProvider(input.ambientLlm, input.platform),
|
|
7052
7196
|
caps: getModelCapabilities(input.model),
|
|
7053
7197
|
roomId: input.roomId,
|
|
@@ -7390,32 +7534,47 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
7390
7534
|
// native capabilities, send images/files inline when it reads them,
|
|
7391
7535
|
// otherwise the `vision` role turns them into text on the platform key;
|
|
7392
7536
|
// originals are archived to the user's sandbox when one is reachable.
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
)
|
|
7537
|
+
// A channel turn's files are read by their `channel:` reference; their
|
|
7538
|
+
// links stay on the server (the run request and the session's link
|
|
7539
|
+
// store), out of every message and note.
|
|
7540
|
+
const attachmentInputs = turnAttachmentInputs(req, body.attachments);
|
|
7396
7541
|
const attachmentModel =
|
|
7397
7542
|
effectiveModel && isAllowedModel(effectiveModel)
|
|
7398
7543
|
? effectiveModel
|
|
7399
7544
|
: getDefaultModelId(core.validatedEnv);
|
|
7400
|
-
const
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7545
|
+
const turnLinks = channelTurnLinks(req);
|
|
7546
|
+
const channelMedia = turnLinks.length
|
|
7547
|
+
? turnChannelMediaSource({
|
|
7548
|
+
sessionId: req.sessionId,
|
|
7549
|
+
turnLinks,
|
|
7550
|
+
store: this.channelAttachmentLinks,
|
|
7551
|
+
channelServiceDid: this.env.CHANNEL_SERVICE_DID,
|
|
7552
|
+
})
|
|
7553
|
+
: undefined;
|
|
7554
|
+
if (turnLinks.length && !run.resumed)
|
|
7555
|
+
await this.channelAttachmentLinks?.put(req.sessionId, turnLinks);
|
|
7556
|
+
const { prepared, metas: turnMetas } = await prepareTurnAttachments({
|
|
7557
|
+
inputs: attachmentInputs,
|
|
7558
|
+
resumed: run.resumed,
|
|
7559
|
+
prepare: async () =>
|
|
7560
|
+
prepareAttachments(
|
|
7561
|
+
{
|
|
7562
|
+
text: body.message,
|
|
7563
|
+
attachments: attachmentInputs,
|
|
7564
|
+
roomId: sessionRoomId,
|
|
7565
|
+
model: attachmentModel,
|
|
7566
|
+
caps: getModelCapabilities(attachmentModel),
|
|
7567
|
+
},
|
|
7568
|
+
{
|
|
7569
|
+
source: this.matrixMediaSource(),
|
|
7570
|
+
...(channelMedia ? { channel: channelMedia } : {}),
|
|
7571
|
+
extraction: this.extractionProvider(baseAmbient.llm, core.llm),
|
|
7572
|
+
sandbox: await this.sandboxArchiveConfig(req.identity.userDid),
|
|
7573
|
+
signal: abortController.signal,
|
|
7574
|
+
logger: console,
|
|
7575
|
+
},
|
|
7576
|
+
),
|
|
7577
|
+
});
|
|
7419
7578
|
if (prepared) {
|
|
7420
7579
|
console.log(
|
|
7421
7580
|
`[user-do] attachments: ${attachmentInputs.length} attached, ${prepared.extracted.length} extracted, ${Array.isArray(prepared.content) ? prepared.content.length - 1 : 0} native`,
|
|
@@ -7439,7 +7598,8 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
7439
7598
|
ambientLlm: baseAmbient.llm,
|
|
7440
7599
|
platform: core.llm,
|
|
7441
7600
|
signal: abortController.signal,
|
|
7442
|
-
turnMetas
|
|
7601
|
+
turnMetas,
|
|
7602
|
+
channelLinks: turnLinks,
|
|
7443
7603
|
});
|
|
7444
7604
|
|
|
7445
7605
|
// Request metadata (editor room, space, session run, entity) → state,
|
|
@@ -7773,6 +7933,9 @@ export function createUserOracleDO(opts: UserOracleDOOptions) {
|
|
|
7773
7933
|
provider: req.channel.provider,
|
|
7774
7934
|
bindingId: req.channel.bindingId,
|
|
7775
7935
|
bindingRevision: req.channel.bindingRevision,
|
|
7936
|
+
...(req.channel.attachments?.length
|
|
7937
|
+
? { attachments: req.channel.attachments }
|
|
7938
|
+
: {}),
|
|
7776
7939
|
},
|
|
7777
7940
|
}
|
|
7778
7941
|
: {}),
|