@ixo/oracle-runtime-workers 0.30.0 → 0.31.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/runtime-context.ts +3 -0
- 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 +142 -42
- package/src/hub-actions/client.ts +87 -7
- package/src/hub-actions/hub-text.ts +82 -0
- package/src/hub-actions/request.ts +7 -4
- package/src/hub-actions/store.ts +5 -1
- package/src/hub-actions/transfer.ts +23 -6
- package/src/index.ts +1 -0
- package/src/plugin-api/index.ts +1 -0
- package/src/plugin-api/types.ts +43 -2
- package/src/plugins/attachments/view-attachment-tool.ts +7 -3
- package/src/plugins/hub-actions/hub-actions.plugin.ts +96 -17
- package/src/plugins/ixo-chain/blocksync.ts +6 -2
- package/src/plugins/ixo-chain/http.ts +16 -8
- 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 +926 -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 +534 -0
- package/src/plugins/yoma/text.ts +16 -0
- package/src/plugins/yoma/work.ts +190 -0
- package/src/plugins/yoma/yoma.plugin.ts +2162 -0
- package/src/sqlite/serialization.ts +2 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a person's logged work stands: whether it was approved and whether
|
|
3
|
+
* it was paid, read live from Blocksync (the same query as Jambo's
|
|
4
|
+
* `fetchClaimsByAgentAddress`), never from memory. Approval and payment are
|
|
5
|
+
* told apart. The job's name is its claim form's title.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
import type { ChainCall, Outcome } from '../ixo-chain/http';
|
|
9
|
+
import {
|
|
10
|
+
coinSchema,
|
|
11
|
+
COLLECTION_ID,
|
|
12
|
+
fetchEntities,
|
|
13
|
+
loadForm,
|
|
14
|
+
nodesOf,
|
|
15
|
+
paymentsSchema,
|
|
16
|
+
positiveCoins,
|
|
17
|
+
templateTitle,
|
|
18
|
+
type Coin,
|
|
19
|
+
type RawEntity,
|
|
20
|
+
} from './catalog';
|
|
21
|
+
import { blocksyncRead, literal } from './reads';
|
|
22
|
+
|
|
23
|
+
/** A cursor is Blocksync's opaque base64. */
|
|
24
|
+
const CURSOR = /^[A-Za-z0-9+/=_-]{1,200}$/;
|
|
25
|
+
|
|
26
|
+
/** ixo.claims.v1beta1.EvaluationStatus, in words a person reads. */
|
|
27
|
+
const CHECK_LABEL: Record<number, { state: string; label: string }> = {
|
|
28
|
+
0: { state: 'being_checked', label: 'Being checked' },
|
|
29
|
+
1: { state: 'approved', label: 'Approved ✓' },
|
|
30
|
+
2: { state: 'not_approved', label: 'Not approved' },
|
|
31
|
+
3: { state: 'disputed', label: 'With support' },
|
|
32
|
+
4: { state: 'not_approved', label: 'Not approved' },
|
|
33
|
+
// Flagged: a reviewer wants another look before deciding.
|
|
34
|
+
5: { state: 'being_checked', label: 'Being checked again' },
|
|
35
|
+
};
|
|
36
|
+
const BEING_CHECKED = { state: 'being_checked', label: 'Being checked' };
|
|
37
|
+
|
|
38
|
+
/** ixo.claims.v1beta1.PaymentStatus of the approval payment. */
|
|
39
|
+
const PAYMENT_LABEL: Record<string, { state: string; label: string }> = {
|
|
40
|
+
PAID: { state: 'paid', label: 'Paid' },
|
|
41
|
+
PROMISED: { state: 'on_its_way', label: 'On its way' },
|
|
42
|
+
AUTHORIZED: { state: 'on_its_way', label: 'On its way' },
|
|
43
|
+
GUARANTEED: { state: 'on_its_way', label: 'On its way' },
|
|
44
|
+
FAILED: { state: 'problem', label: 'Payment problem — the team is on it' },
|
|
45
|
+
DISPUTED_PAYMENT: { state: 'problem', label: 'Payment is being looked into' },
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const claimSchema = z.object({
|
|
49
|
+
claimId: z.string().max(200),
|
|
50
|
+
collectionId: z.string().regex(COLLECTION_ID),
|
|
51
|
+
submissionDate: z.string().nullable(),
|
|
52
|
+
paymentsStatus: z
|
|
53
|
+
.object({ approval: z.string().optional() })
|
|
54
|
+
.passthrough()
|
|
55
|
+
.nullable(),
|
|
56
|
+
evaluationByClaimId: z
|
|
57
|
+
.object({
|
|
58
|
+
status: z.number().int(),
|
|
59
|
+
evaluationDate: z.string().nullable(),
|
|
60
|
+
amount: z.array(coinSchema).max(20).nullable().optional(),
|
|
61
|
+
})
|
|
62
|
+
.nullable(),
|
|
63
|
+
});
|
|
64
|
+
type RawClaim = z.infer<typeof claimSchema>;
|
|
65
|
+
|
|
66
|
+
const pageSchema = z.object({
|
|
67
|
+
totalCount: z.number().int().optional(),
|
|
68
|
+
pageInfo: z
|
|
69
|
+
.object({
|
|
70
|
+
hasNextPage: z.boolean().optional(),
|
|
71
|
+
endCursor: z.string().nullable().optional(),
|
|
72
|
+
})
|
|
73
|
+
.optional(),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
const collectionSchema = z.object({
|
|
77
|
+
id: z.string(),
|
|
78
|
+
protocol: z.string(),
|
|
79
|
+
payments: paymentsSchema,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export interface WorkItem {
|
|
83
|
+
collectionId: string;
|
|
84
|
+
job: string;
|
|
85
|
+
sentOn?: string;
|
|
86
|
+
check: { state: string; label: string };
|
|
87
|
+
checkedOn?: string;
|
|
88
|
+
payment: { state: string; label: string };
|
|
89
|
+
/** What approval pays: the evaluation's amount, else the collection's. */
|
|
90
|
+
reward: Coin[];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WorkPage {
|
|
94
|
+
items: WorkItem[];
|
|
95
|
+
total: number;
|
|
96
|
+
hasNextPage: boolean;
|
|
97
|
+
endCursor?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function paymentOf(claim: RawClaim, reward: Coin[]): WorkItem['payment'] {
|
|
101
|
+
const known = PAYMENT_LABEL[claim.paymentsStatus?.approval ?? ''];
|
|
102
|
+
if (known) return known;
|
|
103
|
+
if (claim.evaluationByClaimId?.status !== 1)
|
|
104
|
+
return { state: 'not_due', label: '—' };
|
|
105
|
+
return reward.length
|
|
106
|
+
? { state: 'not_paid_yet', label: 'Not paid yet' }
|
|
107
|
+
: { state: 'no_payment', label: 'No payment for this one' };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** One page of the account's claims, newest first, with each job's name. */
|
|
111
|
+
export async function loadWork(
|
|
112
|
+
call: ChainCall,
|
|
113
|
+
input: { address: string; first: number; after?: string },
|
|
114
|
+
): Promise<Outcome<WorkPage>> {
|
|
115
|
+
const after =
|
|
116
|
+
input.after && CURSOR.test(input.after)
|
|
117
|
+
? `, after: ${literal(input.after)}`
|
|
118
|
+
: '';
|
|
119
|
+
const claims = await blocksyncRead(call, [
|
|
120
|
+
{
|
|
121
|
+
alias: 'w',
|
|
122
|
+
field: `w: claims(filter: { agentAddress: { equalTo: ${literal(input.address)} } }, first: ${input.first}${after}, orderBy: SUBMISSION_DATE_DESC) { totalCount pageInfo { hasNextPage endCursor } nodes { claimId collectionId submissionDate paymentsStatus evaluationByClaimId { status evaluationDate amount } } }`,
|
|
123
|
+
},
|
|
124
|
+
]);
|
|
125
|
+
if (!claims.ok) return claims;
|
|
126
|
+
const parsedPage = pageSchema.safeParse(claims.value.w);
|
|
127
|
+
const page = parsedPage.success ? parsedPage.data : undefined;
|
|
128
|
+
const nodes = nodesOf(claims.value.w, claimSchema);
|
|
129
|
+
const endCursor = page?.pageInfo?.endCursor;
|
|
130
|
+
const base: Omit<WorkPage, 'items'> = {
|
|
131
|
+
total: page?.totalCount ?? nodes.length,
|
|
132
|
+
hasNextPage: page?.pageInfo?.hasNextPage === true,
|
|
133
|
+
...(endCursor && CURSOR.test(endCursor) ? { endCursor } : {}),
|
|
134
|
+
};
|
|
135
|
+
if (!nodes.length) return { ok: true, value: { items: [], ...base } };
|
|
136
|
+
|
|
137
|
+
// Names: each collection's protocol, then its claim form's title. A name
|
|
138
|
+
// that cannot be read falls back to the collection id; the statuses stand.
|
|
139
|
+
const collectionIds = [...new Set(nodes.map((n) => n.collectionId))];
|
|
140
|
+
const collections = await blocksyncRead(call, [
|
|
141
|
+
{
|
|
142
|
+
alias: 'c',
|
|
143
|
+
field: `c: claimCollections(filter: { id: { in: [${collectionIds.map(literal).join(', ')}] } }, first: ${collectionIds.length}) { nodes { id protocol payments } }`,
|
|
144
|
+
},
|
|
145
|
+
]);
|
|
146
|
+
const byId = new Map(
|
|
147
|
+
(collections.ok ? nodesOf(collections.value.c, collectionSchema) : []).map(
|
|
148
|
+
(c) => [c.id, c],
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
const protocolIds = [...new Set([...byId.values()].map((c) => c.protocol))];
|
|
152
|
+
const protocols = protocolIds.length
|
|
153
|
+
? await fetchEntities(call, protocolIds)
|
|
154
|
+
: { ok: true as const, value: new Map<string, RawEntity>() };
|
|
155
|
+
const titles = new Map(
|
|
156
|
+
await Promise.all(
|
|
157
|
+
protocolIds.map(async (id) => {
|
|
158
|
+
const form = protocols.ok
|
|
159
|
+
? await loadForm(call, protocols.value.get(id), 'claim')
|
|
160
|
+
: undefined;
|
|
161
|
+
return [id, form?.ok ? templateTitle(form.value) : undefined] as const;
|
|
162
|
+
}),
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const items = nodes.map((claim): WorkItem => {
|
|
167
|
+
const collection = byId.get(claim.collectionId);
|
|
168
|
+
const evaluation = claim.evaluationByClaimId;
|
|
169
|
+
const paid = positiveCoins(evaluation?.amount);
|
|
170
|
+
const reward = paid.length
|
|
171
|
+
? paid
|
|
172
|
+
: positiveCoins(collection?.payments?.approval?.amount);
|
|
173
|
+
return {
|
|
174
|
+
collectionId: claim.collectionId,
|
|
175
|
+
job:
|
|
176
|
+
(collection && titles.get(collection.protocol)) ??
|
|
177
|
+
`Opportunity ${claim.collectionId}`,
|
|
178
|
+
...(claim.submissionDate
|
|
179
|
+
? { sentOn: claim.submissionDate.slice(0, 10) }
|
|
180
|
+
: {}),
|
|
181
|
+
check: CHECK_LABEL[evaluation?.status ?? 0] ?? BEING_CHECKED,
|
|
182
|
+
...(evaluation?.evaluationDate
|
|
183
|
+
? { checkedOn: evaluation.evaluationDate.slice(0, 10) }
|
|
184
|
+
: {}),
|
|
185
|
+
payment: paymentOf(claim, reward),
|
|
186
|
+
reward,
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
return { ok: true, value: { items, ...base } };
|
|
190
|
+
}
|