@ixo/oracle-runtime-workers 0.38.0 → 0.40.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 -4
- package/src/action-interactions/routes.ts +78 -0
- package/src/action-interactions/store.ts +1038 -0
- package/src/channels/replies.ts +8 -4
- package/src/core/capability-expiry.ts +62 -0
- package/src/core/capability-router.ts +126 -95
- package/src/core/context-budget.ts +116 -4
- package/src/core/domain-context/document.ts +74 -2
- package/src/core/domain-context/index.ts +1 -0
- package/src/core/domain-context/resolver.ts +9 -6
- package/src/core/domain-context/turn-context.ts +62 -13
- package/src/core/domain-context/types.ts +17 -0
- package/src/core/env.ts +21 -2
- package/src/core/index.ts +4 -0
- package/src/core/llm.ts +29 -0
- package/src/core/main-agent-types.ts +45 -4
- package/src/core/main-agent.ts +210 -122
- package/src/core/manifest.ts +109 -24
- package/src/core/mcp-result.ts +56 -0
- package/src/core/meta-tools.ts +258 -110
- package/src/core/middlewares/capability-gate.ts +77 -28
- package/src/core/middlewares/context-guard.ts +154 -21
- package/src/core/middlewares/result-cap.ts +1 -1
- package/src/core/middlewares/summarization.ts +9 -0
- package/src/core/middlewares/tool-marks.ts +11 -2
- package/src/core/middlewares/tool-repetition-guard.ts +61 -1
- package/src/core/middlewares/turn-boundary.ts +22 -12
- package/src/core/operating-guides.ts +126 -0
- package/src/core/plugins/skills/skills-tools.ts +6 -31
- package/src/core/plugins/skills/skills.plugin.ts +4 -3
- package/src/core/plugins/weather/weather.plugin.ts +1 -0
- package/src/core/prompt-composer.ts +188 -111
- package/src/core/read-result-tool.ts +48 -14
- package/src/core/registries.ts +13 -5
- package/src/core/state.ts +4 -3
- package/src/core/sub-agent-fallback.ts +1 -0
- package/src/core/subagent-as-tool.ts +4 -1
- package/src/core/tool-access.ts +3 -32
- package/src/core/wrap-plugin-tool.ts +2 -1
- package/src/do/contracts.ts +45 -1
- package/src/do/transcript.ts +40 -11
- package/src/do/turn-metadata.ts +16 -4
- package/src/do/user-oracle-do.ts +358 -62
- package/src/index.ts +1 -0
- package/src/memory/session-history-indexer.ts +60 -14
- package/src/plugin-api/oracle-plugin.ts +4 -5
- package/src/plugin-api/types.ts +32 -3
- package/src/plugins/action-proposals/action-proposals.plugin.ts +7 -2
- package/src/plugins/agui/agui.plugin.ts +1 -0
- package/src/plugins/compact-schema.ts +80 -0
- package/src/plugins/composio/composio.plugin.ts +1 -0
- package/src/plugins/domain-indexer/domain-indexer.plugin.ts +4 -3
- package/src/plugins/editor/editor.plugin.ts +4 -0
- package/src/plugins/firecrawl/firecrawl-agent.ts +2 -0
- package/src/plugins/firecrawl/firecrawl.plugin.ts +1 -0
- package/src/plugins/flows/flows.plugin.ts +37 -6
- package/src/plugins/flows/prompts.ts +1 -1
- package/src/plugins/flows/tools/authoring.ts +5 -7
- package/src/plugins/flows/tools/discovery.ts +1 -4
- package/src/plugins/flows/tools/forms.ts +2 -8
- package/src/plugins/flows/tools/linkage.ts +1 -4
- package/src/plugins/flows/tools/settings.ts +1 -4
- package/src/plugins/flows/translator.ts +16 -5
- package/src/plugins/flows/types.ts +27 -48
- package/src/plugins/hub-actions/hub-actions.plugin.ts +30 -4
- package/src/plugins/index.ts +2 -2
- package/src/plugins/ixo-chain/ixo-chain.plugin.ts +29 -5
- package/src/plugins/ixo-chain/kinds/core.ts +2 -2
- package/src/plugins/ixo-chain/kinds/types.ts +34 -5
- package/src/plugins/ixo-chain/queries.ts +10 -1
- package/src/plugins/ixo-transaction/ixo-transaction.plugin.ts +1 -0
- package/src/plugins/matrix-group-chats/index.ts +1 -0
- package/src/plugins/memory/memory-tools.ts +4 -4
- package/src/plugins/memory/memory.plugin.ts +27 -1
- package/src/plugins/memory/oracle-document-tools.ts +24 -49
- package/src/plugins/pod-creator/pod-creator.plugin.ts +1 -0
- package/src/plugins/portal/portal.plugin.ts +3 -1
- package/src/plugins/sandbox/sandbox-write-blob.ts +3 -15
- package/src/plugins/sandbox/sandbox.plugin.ts +19 -2
- package/src/plugins/tasks/manifest.ts +1 -0
- package/src/plugins/tasks/tasks-tools.ts +34 -39
- package/src/plugins/user-preferences/user-preferences-tool.ts +11 -37
- package/src/plugins/user-preferences/user-preferences.plugin.ts +4 -0
- package/src/plugins/vfs/vfs-tools.ts +6 -6
- package/src/plugins/vfs/vfs.plugin.ts +4 -5
- package/src/plugins/yoma/yoma.plugin.ts +1 -0
- package/src/shell/app.ts +241 -6
- package/src/sqlite/serialization.ts +12 -0
- package/src/sqlite/sqlite-saver.ts +17 -0
- package/src/tasks/schedule-input.ts +5 -22
|
@@ -98,18 +98,11 @@ export const stepInputsSchema = z
|
|
|
98
98
|
export const conditionSchema = z.object({
|
|
99
99
|
source: z
|
|
100
100
|
.enum(['configured_input', 'runtime_output'])
|
|
101
|
-
.describe(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
),
|
|
107
|
-
field: nameSchema.describe('Field on the upstream step to inspect.'),
|
|
108
|
-
is: z.enum(CONDITION_OPERATORS).describe('Comparison operator.'),
|
|
109
|
-
value: z
|
|
110
|
-
.unknown()
|
|
111
|
-
.optional()
|
|
112
|
-
.describe('Value to compare against (omit for isEmpty/isNotEmpty).'),
|
|
101
|
+
.describe('Read authored inputs or successful runtime output.'),
|
|
102
|
+
fromStep: stepIdSchema.describe('The upstream step.'),
|
|
103
|
+
field: nameSchema.describe('Its field to inspect.'),
|
|
104
|
+
is: z.enum(CONDITION_OPERATORS),
|
|
105
|
+
value: z.unknown().optional().describe('Omit for isEmpty/isNotEmpty.'),
|
|
113
106
|
});
|
|
114
107
|
|
|
115
108
|
export const semanticGateSchema = z
|
|
@@ -128,20 +121,18 @@ export const hookSchema = z.object({
|
|
|
128
121
|
});
|
|
129
122
|
|
|
130
123
|
export const dueSchema = z.object({
|
|
131
|
-
at: nameSchema.optional().describe('Absolute
|
|
124
|
+
at: nameSchema.optional().describe('Absolute (ISO 8601).'),
|
|
132
125
|
within: nameSchema
|
|
133
126
|
.optional()
|
|
134
|
-
.describe(
|
|
135
|
-
'Duration from when the step becomes active (ISO 8601 duration).',
|
|
136
|
-
),
|
|
127
|
+
.describe('ISO 8601 duration from when the step becomes active.'),
|
|
137
128
|
afterCommitment: nameSchema
|
|
138
129
|
.optional()
|
|
139
|
-
.describe('
|
|
130
|
+
.describe('ISO 8601 duration from commitment.'),
|
|
140
131
|
});
|
|
141
132
|
|
|
142
133
|
export const onEventSchema = z.object({
|
|
143
|
-
fromStep: stepIdSchema.describe('
|
|
144
|
-
event: nameSchema.describe('
|
|
134
|
+
fromStep: stepIdSchema.describe('The upstream step.'),
|
|
135
|
+
event: nameSchema.describe('The event it emits.'),
|
|
145
136
|
});
|
|
146
137
|
|
|
147
138
|
/**
|
|
@@ -150,38 +141,34 @@ export const onEventSchema = z.object({
|
|
|
150
141
|
* is only attached on read (see FlowStepRead).
|
|
151
142
|
*/
|
|
152
143
|
export const flowStepSchema = z.object({
|
|
153
|
-
id: stepIdSchema.describe(
|
|
154
|
-
'Stable, human-readable step id, e.g. "load-batches".',
|
|
155
|
-
),
|
|
144
|
+
id: stepIdSchema.describe('Stable and readable, e.g. "load-batches".'),
|
|
156
145
|
action: nameSchema
|
|
157
146
|
.min(1)
|
|
158
|
-
.describe('
|
|
147
|
+
.describe('From list_actions, e.g. "qi/email.send".'),
|
|
159
148
|
title: nameSchema.optional(),
|
|
160
149
|
description: descriptionSchema.optional(),
|
|
161
150
|
phase: nameSchema
|
|
162
151
|
.min(1)
|
|
163
152
|
.optional()
|
|
164
|
-
.describe(
|
|
165
|
-
'Stable semantic group for this step, such as "discovery" or "deployment".',
|
|
166
|
-
),
|
|
153
|
+
.describe('Stable semantic group, e.g. "discovery".'),
|
|
167
154
|
execution: z
|
|
168
155
|
.enum(['human-only', 'agent-capable'])
|
|
169
156
|
.optional()
|
|
170
157
|
.describe(
|
|
171
|
-
'
|
|
158
|
+
'Only a person may run it, or also a suitably skilled, authorised Flow Agent.',
|
|
172
159
|
),
|
|
173
160
|
|
|
174
161
|
inputs: stepInputsSchema
|
|
175
162
|
.optional()
|
|
176
163
|
.describe(
|
|
177
|
-
'
|
|
178
|
-
'Never
|
|
164
|
+
'A value may reference upstream output: "{{step-id.output.field}}". ' +
|
|
165
|
+
'Never a PIN, mnemonic, password, token or API key: the portal collects those at run time.',
|
|
179
166
|
),
|
|
180
167
|
form: z
|
|
181
168
|
.record(z.string(), z.unknown())
|
|
182
169
|
.optional()
|
|
183
170
|
.describe(
|
|
184
|
-
'
|
|
171
|
+
'Form steps: pre-filled answers by question name; the user submits in the portal.',
|
|
185
172
|
),
|
|
186
173
|
|
|
187
174
|
after: z
|
|
@@ -189,13 +176,11 @@ export const flowStepSchema = z.object({
|
|
|
189
176
|
.max(MAX_FLOW_STEPS)
|
|
190
177
|
.optional()
|
|
191
178
|
.describe(
|
|
192
|
-
'
|
|
179
|
+
'Ordering only, not an auto-trigger; pair with an input reference for a data dependency.',
|
|
193
180
|
),
|
|
194
181
|
runWhen: conditionSchema
|
|
195
182
|
.optional()
|
|
196
|
-
.describe(
|
|
197
|
-
'Gate this step on an upstream configured input or runtime output.',
|
|
198
|
-
),
|
|
183
|
+
.describe('Gate on an upstream configured input or runtime output.'),
|
|
199
184
|
conditions: z
|
|
200
185
|
.array(conditionSchema)
|
|
201
186
|
.max(
|
|
@@ -203,7 +188,7 @@ export const flowStepSchema = z.object({
|
|
|
203
188
|
`A step may have at most ${MAX_CONDITIONS_PER_STEP} conditions.`,
|
|
204
189
|
)
|
|
205
190
|
.optional()
|
|
206
|
-
.describe('
|
|
191
|
+
.describe('Several gates, all must pass.'),
|
|
207
192
|
semanticGate: semanticGateSchema
|
|
208
193
|
.optional()
|
|
209
194
|
.describe(
|
|
@@ -212,24 +197,23 @@ export const flowStepSchema = z.object({
|
|
|
212
197
|
onEvent: onEventSchema
|
|
213
198
|
.optional()
|
|
214
199
|
.describe(
|
|
215
|
-
'Advanced:
|
|
200
|
+
'Advanced: run when an upstream step emits an event; event-capable actions only.',
|
|
216
201
|
),
|
|
217
202
|
|
|
218
203
|
trigger: z
|
|
219
204
|
.enum(['manual', 'flow-start'])
|
|
220
205
|
.optional()
|
|
221
|
-
.describe('
|
|
206
|
+
.describe('Default "manual".'),
|
|
222
207
|
due: dueSchema.optional(),
|
|
223
208
|
|
|
224
209
|
assignTo: didSchema
|
|
225
210
|
.optional()
|
|
226
211
|
.describe(
|
|
227
|
-
'
|
|
228
|
-
"step's authorised actors) — only assign a DID the user named and confirmed.",
|
|
212
|
+
'Assigning AUTHORISES this DID to run the step: only a DID the user named and confirmed.',
|
|
229
213
|
),
|
|
230
214
|
commitTo: nameSchema
|
|
231
215
|
.optional()
|
|
232
|
-
.describe('Commitment window
|
|
216
|
+
.describe('Commitment window, ISO 8601 duration.'),
|
|
233
217
|
|
|
234
218
|
on: z
|
|
235
219
|
.record(z.string(), z.array(hookSchema))
|
|
@@ -243,12 +227,12 @@ export const flowStepSchema = z.object({
|
|
|
243
227
|
)
|
|
244
228
|
.optional()
|
|
245
229
|
.describe(
|
|
246
|
-
'Governed skill ids
|
|
230
|
+
'Governed skill ids for agent-capable execution; the first matches the Flow Agent.',
|
|
247
231
|
),
|
|
248
232
|
requireConfirmation: z
|
|
249
233
|
.boolean()
|
|
250
234
|
.optional()
|
|
251
|
-
.describe('
|
|
235
|
+
.describe('The portal confirms before this step runs.'),
|
|
252
236
|
});
|
|
253
237
|
|
|
254
238
|
/**
|
|
@@ -266,12 +250,7 @@ export const sizedFlowStepSchema = flowStepSchema.refine(
|
|
|
266
250
|
*/
|
|
267
251
|
export const flowSpecSchema = z
|
|
268
252
|
.object({
|
|
269
|
-
ref: z
|
|
270
|
-
.string()
|
|
271
|
-
.optional()
|
|
272
|
-
.describe(
|
|
273
|
-
'Opaque flow handle. Omit when creating; the plugin assigns it.',
|
|
274
|
-
),
|
|
253
|
+
ref: z.string().optional().describe('Omit when creating.'),
|
|
275
254
|
title: nameSchema.min(1),
|
|
276
255
|
goal: descriptionSchema.optional(),
|
|
277
256
|
steps: z
|
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
} from '../../plugin-api/types';
|
|
29
29
|
import { ixoAddressOf } from '../../core/user-identity';
|
|
30
30
|
import { toolNotRunMessage } from '../../core/tool-not-run';
|
|
31
|
+
import { compactJsonSchema } from '../compact-schema';
|
|
31
32
|
import {
|
|
32
33
|
CHAIN_TX_CATALOG,
|
|
33
34
|
CHAIN_TX_GENERAL_RULES,
|
|
@@ -80,8 +81,22 @@ export const requestOperationJsonSchema = {
|
|
|
80
81
|
(branch) => !RUNTIME_BUILT_KINDS.includes(String(branchKind(branch))),
|
|
81
82
|
),
|
|
82
83
|
};
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
/**
|
|
85
|
+
* What the tool binds: each kind's fields, required keys and types, without
|
|
86
|
+
* the protocol's limits and patterns, over a third of its characters. The
|
|
87
|
+
* handler checks a call against {@link strictOperations}, then
|
|
88
|
+
* `parseOperation`.
|
|
89
|
+
*/
|
|
90
|
+
const requestSchema = z.strictObject({
|
|
91
|
+
operation: z.fromJSONSchema(compactJsonSchema(requestOperationJsonSchema)),
|
|
92
|
+
});
|
|
93
|
+
/** Each requestable kind's whole protocol schema, for a refusal naming the field. */
|
|
94
|
+
const strictOperations = new Map(
|
|
95
|
+
requestOperationJsonSchema.oneOf.map((branch) => [
|
|
96
|
+
String(branchKind(branch)),
|
|
97
|
+
z.fromJSONSchema(branch),
|
|
98
|
+
]),
|
|
99
|
+
);
|
|
85
100
|
const statusSchema = z.strictObject({
|
|
86
101
|
actionId: z.string().regex(/^[A-Za-z0-9_-]{32}$/),
|
|
87
102
|
});
|
|
@@ -641,6 +656,16 @@ async function requestHubAction(
|
|
|
641
656
|
const parsed = requestSchema.safeParse(input);
|
|
642
657
|
if (!parsed.success)
|
|
643
658
|
return { status: 'unavailable', reason: 'An operation is required.' };
|
|
659
|
+
const limits = strictOperations
|
|
660
|
+
.get(String(kind))
|
|
661
|
+
?.safeParse(parsed.data.operation);
|
|
662
|
+
if (limits && !limits.success)
|
|
663
|
+
return {
|
|
664
|
+
status: 'unavailable',
|
|
665
|
+
reason: `The requested operation is unsupported or incomplete (${limits.error.issues
|
|
666
|
+
.map((issue) => `${pathText(issue.path)}: ${issue.message}`)
|
|
667
|
+
.join('; ')}).`,
|
|
668
|
+
};
|
|
644
669
|
if (ctx.config.HUB_ACTIONS_ENABLED !== 'true' || !ctx.hubActions)
|
|
645
670
|
return {
|
|
646
671
|
status: 'unavailable',
|
|
@@ -1179,6 +1204,7 @@ const manifest: PluginManifest = {
|
|
|
1179
1204
|
tags: ['actions', 'channels'],
|
|
1180
1205
|
category: 'integration',
|
|
1181
1206
|
visibility: 'on-demand',
|
|
1207
|
+
brief: 'prepare chain transactions to sign in Auth Hub',
|
|
1182
1208
|
stability: 'experimental',
|
|
1183
1209
|
};
|
|
1184
1210
|
|
|
@@ -1227,7 +1253,7 @@ export class HubActionsPlugin extends OraclePlugin {
|
|
|
1227
1253
|
{
|
|
1228
1254
|
name: 'hub_action_options',
|
|
1229
1255
|
description:
|
|
1230
|
-
"Read
|
|
1256
|
+
"Read the owner’s confirmed Gmail and Calendar connections, requestable documents, action resources and bank tokens (`transfer.tokens`: denom, symbol, decimals, verified, balance in base units). Use each returned service, identifier and label to prepare a related Hub review. A Gmail profile connection does not authorize sending. For a token that is not verified, name its full denom and say it is unverified; its amounts are base units. ownerDid is the authenticated user's DID and ownerAddress their IXO account address.",
|
|
1231
1257
|
schema: discoverSchema,
|
|
1232
1258
|
effect: 'read',
|
|
1233
1259
|
handler: hubActionOptions,
|
|
@@ -1235,7 +1261,7 @@ export class HubActionsPlugin extends OraclePlugin {
|
|
|
1235
1261
|
{
|
|
1236
1262
|
name: 'request_hub_action',
|
|
1237
1263
|
description:
|
|
1238
|
-
'Prepare a supported operation for the authenticated channel owner to review in Auth Hub. Never approves, signs, or executes. For email, propose one plain-text message to one recipient using a confirmed Gmail send connection. Supply only the operation candidate; the runtime supplies identity and turn binding. Coin sends and other chain transactions have their own tool (request_chain_transaction). Never prepare a replacement email after an unknown send without the user checking Gmail’s Sent folder and asking again.',
|
|
1264
|
+
'Prepare a supported operation for the authenticated channel owner to review in Auth Hub. Never approves, signs, or executes. For email, propose one plain-text message to one recipient using a confirmed Gmail send connection. Supply only the operation candidate; the runtime supplies identity and turn binding. Coin sends and other chain transactions have their own tool (request_chain_transaction). Never prepare a replacement email after an unknown send without the user checking Gmail’s Sent folder and asking again. Limits are checked on the call; `startsAt` and `endsAt` are ISO 8601 with an offset, a saved `filename` ends in .txt, a form field `id` is lower_snake_case.',
|
|
1239
1265
|
schema: requestSchema,
|
|
1240
1266
|
effect: 'write',
|
|
1241
1267
|
handler: requestHubAction,
|
package/src/plugins/index.ts
CHANGED
|
@@ -8,8 +8,8 @@ export { HubActionsPlugin } from './hub-actions/hub-actions.plugin';
|
|
|
8
8
|
* plugins. Each is gated the same way as on Node: `autoDetect` on its env
|
|
9
9
|
* key where one exists (memory / sandbox / firecrawl / composio), always-on
|
|
10
10
|
* otherwise (domain-indexer; ixo-chain unless `IXO_CHAIN_TOOLS=off`; vfs
|
|
11
|
-
* self-gates on `ctx.ucan.hasSigningKey()`; pod-creator and
|
|
12
|
-
* on-demand and stay hidden until `load_capability`).
|
|
11
|
+
* self-gates on `ctx.ucan.hasSigningKey()`; sandbox, vfs, pod-creator and
|
|
12
|
+
* ixo-chain are on-demand and stay hidden until `load_capability`).
|
|
13
13
|
*
|
|
14
14
|
* A host opts in by spreading `BUNDLED_WORKERS_PLUGINS` into
|
|
15
15
|
* `createOracleWorker({ plugins })` — plugins whose env keys are absent are
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
type Source,
|
|
24
24
|
} from './http';
|
|
25
25
|
import { KINDS, kindByName, kindNames } from './kinds/registry';
|
|
26
|
-
import type
|
|
26
|
+
import { argKeys, type KindDef } from './kinds/types';
|
|
27
27
|
import {
|
|
28
28
|
chainLookup,
|
|
29
29
|
cutRow,
|
|
@@ -426,11 +426,11 @@ const manifest: PluginManifest = {
|
|
|
426
426
|
{
|
|
427
427
|
user: 'Did I get paid for my claims in collection 8250?',
|
|
428
428
|
thought:
|
|
429
|
-
"The user's claims there (evaluation and payment status) and the collection's payment terms, in one lookup.",
|
|
429
|
+
"The user's claims there (agent: their own address; evaluation and payment status) and the collection's payment terms, in one lookup.",
|
|
430
430
|
tool: 'chain_lookup',
|
|
431
431
|
args: {
|
|
432
432
|
requests: [
|
|
433
|
-
{ kind: 'claims', args: { collectionId: '8250' } },
|
|
433
|
+
{ kind: 'claims', args: { agent: 'ixo1…', collectionId: '8250' } },
|
|
434
434
|
{ kind: 'claim_collection', args: { id: '8250' } },
|
|
435
435
|
],
|
|
436
436
|
},
|
|
@@ -452,10 +452,11 @@ const manifest: PluginManifest = {
|
|
|
452
452
|
// Hosts that want it on every turn set `visibility: 'always'` through
|
|
453
453
|
// `manifestOverrides`.
|
|
454
454
|
visibility: 'on-demand',
|
|
455
|
+
brief: 'read the IXO chain: balances, entities, claims, tokens',
|
|
455
456
|
stability: 'beta',
|
|
456
457
|
};
|
|
457
458
|
|
|
458
|
-
/** Read-only and transfer rule; also in the tool descriptions,
|
|
459
|
+
/** Read-only and transfer rule; also in the tool descriptions, so each tool reads correctly on its own. */
|
|
459
460
|
const READ_ONLY_RULE =
|
|
460
461
|
"Read-only. For a transfer use this turn's transfer tools; on a channel read `hub_action_options` first (the Hub applies the account's limits).";
|
|
461
462
|
/** Chain text is written by anyone; also in the `chain_lookup` description. */
|
|
@@ -478,6 +479,29 @@ const LOOKUP_UNITS_RULE =
|
|
|
478
479
|
const NAMES_RULE =
|
|
479
480
|
'Call people and things by their `names` entry; give an address or DID only when asked; beside a `selfChosen` name the user did not pick, also give the short address (first 12 … last 6 characters).';
|
|
480
481
|
|
|
482
|
+
/**
|
|
483
|
+
* What the list of arguments alone would mislead on: `claims` with a
|
|
484
|
+
* `collectionId` reads as the collection's claims, but it stays one agent's.
|
|
485
|
+
*/
|
|
486
|
+
const ARG_NOTES: Record<string, string> = {
|
|
487
|
+
claims: ' [default: user]',
|
|
488
|
+
claim_collection: ' [totals]',
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Every kind's arguments besides `address` and `first`, from the kinds' own
|
|
493
|
+
* schemas: known without a `describe_chain_kinds` round trip, and they cannot
|
|
494
|
+
* drift.
|
|
495
|
+
*/
|
|
496
|
+
export const KIND_ARGS = KINDS.flatMap((kind) => {
|
|
497
|
+
const keys = argKeys(kind.args).keys.filter(
|
|
498
|
+
(key) => key !== 'address' && key !== 'first',
|
|
499
|
+
);
|
|
500
|
+
return keys.length
|
|
501
|
+
? [`${kind.name}(${keys.join(',')})${ARG_NOTES[kind.name] ?? ''}`]
|
|
502
|
+
: [];
|
|
503
|
+
}).join(' ');
|
|
504
|
+
|
|
481
505
|
/** Says the overview is broad and costly; its units, text and names rules are `chain_lookup`'s, bound beside it. */
|
|
482
506
|
const OVERVIEW_DESCRIPTION = [
|
|
483
507
|
"A broad look at an IXO account (default: the user's) by `sections` (default: all): per section: counts, top 3 rows, `more` (the request for the rest).",
|
|
@@ -543,7 +567,7 @@ export class IxoChainPlugin extends OraclePlugin {
|
|
|
543
567
|
name: 'chain_lookup',
|
|
544
568
|
description: [
|
|
545
569
|
'IXO chain data: 1–8 `requests` `{ kind, args }`, each answered on its own (`ok`, or `reason` + `retryable`).',
|
|
546
|
-
|
|
570
|
+
`\`args\`: account args take ixo1… or did:ixo:ixo1… (default: the user); \`address\` on most kinds, \`first\` 1–20 on lists; others: ${KIND_ARGS}. \`describe_chain_kinds\` explains a kind.`,
|
|
547
571
|
'`source`: `chain` live, `blocksync` indexed (seconds behind).',
|
|
548
572
|
LOOKUP_UNITS_RULE,
|
|
549
573
|
NETWORK_RULE,
|
|
@@ -63,7 +63,7 @@ const STATUSES =
|
|
|
63
63
|
const claimsKind = defineKind({
|
|
64
64
|
name: 'claims',
|
|
65
65
|
summary:
|
|
66
|
-
|
|
66
|
+
"One agent's claims (default: the user; `collectionId` needs `agent`), newest first, with evaluation and payment status. A collection's totals are in `claim_collection`.",
|
|
67
67
|
explain: [
|
|
68
68
|
'Each claim: claimId, collectionId, agent, submissionDate, `evaluation` (status, date) and `paymentsStatus` per payment leg (e.g. `approval: PAID`).',
|
|
69
69
|
STATUSES,
|
|
@@ -73,7 +73,7 @@ const claimsKind = defineKind({
|
|
|
73
73
|
source: 'blocksync',
|
|
74
74
|
list: true,
|
|
75
75
|
args: CORE_ARGS.claims,
|
|
76
|
-
example: {
|
|
76
|
+
example: { first: 5 },
|
|
77
77
|
plan: (args, ctx) => blocksyncPlan({ kind: 'claims', ...args }, ctx),
|
|
78
78
|
});
|
|
79
79
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* {@link defineKind}: `chain_lookup`'s tool schema only names the kind, so
|
|
10
10
|
* the catalogue does not cost context on every turn.
|
|
11
11
|
*/
|
|
12
|
-
import
|
|
12
|
+
import { z } from 'zod';
|
|
13
13
|
import type { UserIdentity } from '../../../core/user-identity';
|
|
14
14
|
import type { TokenDisplay } from '../denoms';
|
|
15
15
|
import type { ChainCall, Failure, Outcome, Source } from '../http';
|
|
@@ -109,8 +109,37 @@ export interface KindDef {
|
|
|
109
109
|
plan(rawArgs: unknown, ctx: KindContext): KindPlan | KindInvalid;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
/** The
|
|
113
|
-
function
|
|
112
|
+
/** The names a kind's arguments take, in schema order, with the required ones. */
|
|
113
|
+
export function argKeys(args: z.ZodType): {
|
|
114
|
+
keys: string[];
|
|
115
|
+
required: string[];
|
|
116
|
+
} {
|
|
117
|
+
const { properties = {}, required = [] } = z.toJSONSchema(args, {
|
|
118
|
+
io: 'input',
|
|
119
|
+
unrepresentable: 'any',
|
|
120
|
+
});
|
|
121
|
+
return { keys: Object.keys(properties), required };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** A kind's valid keys as a clause of its refusal. */
|
|
125
|
+
function validKeys(args: z.ZodType): string {
|
|
126
|
+
const { keys, required } = argKeys(args);
|
|
127
|
+
if (!keys.length) return 'This kind takes no args.';
|
|
128
|
+
const list = keys
|
|
129
|
+
.map((key) => (required.includes(key) ? `${key} (required)` : key))
|
|
130
|
+
.join(', ');
|
|
131
|
+
return `Its args: ${list}.`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The argument problems as one sentence, with the kind's valid keys, so the
|
|
136
|
+
* model can correct the request without describing the kind first.
|
|
137
|
+
*/
|
|
138
|
+
function invalidArgs(
|
|
139
|
+
name: string,
|
|
140
|
+
error: z.ZodError,
|
|
141
|
+
args: z.ZodType,
|
|
142
|
+
): KindInvalid {
|
|
114
143
|
const issues = error.issues
|
|
115
144
|
.slice(0, 3)
|
|
116
145
|
.map((issue) =>
|
|
@@ -120,7 +149,7 @@ function invalidArgs(name: string, error: z.ZodError): KindInvalid {
|
|
|
120
149
|
)
|
|
121
150
|
.join('; ');
|
|
122
151
|
return {
|
|
123
|
-
invalid: `Invalid args for kind "${name}" (${issues}).
|
|
152
|
+
invalid: `Invalid args for kind "${name}" (${issues}). ${validKeys(args)} describe_chain_kinds with ["${name}"] explains them.`,
|
|
124
153
|
};
|
|
125
154
|
}
|
|
126
155
|
|
|
@@ -150,7 +179,7 @@ export function defineKind<S extends z.ZodType>(spec: {
|
|
|
150
179
|
const parsed = spec.args.safeParse(rawArgs ?? {});
|
|
151
180
|
return parsed.success
|
|
152
181
|
? spec.plan(parsed.data, ctx)
|
|
153
|
-
: invalidArgs(spec.name, parsed.error);
|
|
182
|
+
: invalidArgs(spec.name, parsed.error, spec.args);
|
|
154
183
|
},
|
|
155
184
|
};
|
|
156
185
|
}
|
|
@@ -69,7 +69,9 @@ export const CORE_ARGS = {
|
|
|
69
69
|
collectionId: z
|
|
70
70
|
.string()
|
|
71
71
|
.optional()
|
|
72
|
-
.describe(
|
|
72
|
+
.describe(
|
|
73
|
+
'Only this agent\'s claims in this collection, e.g. "8250"; needs `agent`.',
|
|
74
|
+
),
|
|
73
75
|
first: firstArg,
|
|
74
76
|
after: z
|
|
75
77
|
.string()
|
|
@@ -290,6 +292,13 @@ export function requestField(
|
|
|
290
292
|
): FieldPlan {
|
|
291
293
|
switch (request.kind) {
|
|
292
294
|
case 'claims': {
|
|
295
|
+
// A collection alone would quietly mean "the user's claims in it",
|
|
296
|
+
// which a question about the collection never asks: whose claims is
|
|
297
|
+
// said, or the collection's own counts are read instead.
|
|
298
|
+
if (request.collectionId !== undefined && request.agent === undefined)
|
|
299
|
+
return invalid(
|
|
300
|
+
`claims lists one agent's claims. For collection ${request.collectionId} as a whole (count, approved, rejected), use claim_collection with id "${request.collectionId}"; for one agent's claims in it, pass agent too (the user's own address for theirs).`,
|
|
301
|
+
);
|
|
293
302
|
const agent = accountOf(request.agent, identity, 'agent');
|
|
294
303
|
if (!agent.ok) return invalid(agent.detail);
|
|
295
304
|
if (
|
|
@@ -96,6 +96,7 @@ const manifest: PluginManifest = {
|
|
|
96
96
|
tags: ['ixo', 'transaction', 'wallet', 'portal', 'cosmos'],
|
|
97
97
|
category: 'integration',
|
|
98
98
|
visibility: 'on-demand',
|
|
99
|
+
brief: 'prepare chain transactions for wallet signing in Portal',
|
|
99
100
|
stability: 'experimental',
|
|
100
101
|
};
|
|
101
102
|
|
|
@@ -30,10 +30,10 @@ export const MEMORY_CLEAR_MCP_NAME = 'memory-engine__clear';
|
|
|
30
30
|
* knowledge from chat without a per-oracle code change: the Memory Engine
|
|
31
31
|
* itself checks on chain that the caller is a member (controller, owner,
|
|
32
32
|
* Matrix admin or DAO member) of the oracle's domain entity and refuses
|
|
33
|
-
* everyone else, so
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* everyone else, so offering the tool to every user grants nothing. Forks
|
|
34
|
+
* that want a different surface (drop `clear`, add `delete_edge`) pass an
|
|
35
|
+
* explicit list via plugin options. Everything but search and add stays
|
|
36
|
+
* behind `load_capability` (the plugin manifest's `onDemandTools`).
|
|
37
37
|
*/
|
|
38
38
|
export const DEFAULT_MEMORY_TOOLS = [
|
|
39
39
|
MEMORY_SEARCH_MCP_NAME,
|
|
@@ -12,10 +12,18 @@ import {
|
|
|
12
12
|
createDefaultMemoryMcpFactory,
|
|
13
13
|
DEFAULT_MEMORY_TOOLS,
|
|
14
14
|
fetchMemoryTools,
|
|
15
|
+
MEMORY_ADD_ORACLE_KNOWLEDGE_MCP_NAME,
|
|
16
|
+
MEMORY_CLEAR_MCP_NAME,
|
|
17
|
+
MEMORY_DELETE_EDGE_MCP_NAME,
|
|
18
|
+
MEMORY_DELETE_EPISODE_MCP_NAME,
|
|
15
19
|
type MemoryMcpFactory,
|
|
16
20
|
} from './memory-tools';
|
|
17
21
|
import { oracleEntityDidSchema } from './memory-entity';
|
|
18
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
ADD_ORACLE_DOCUMENT_TOOL_NAME,
|
|
24
|
+
createOracleDocumentTools,
|
|
25
|
+
DELETE_ORACLE_DOCUMENT_TOOL_NAME,
|
|
26
|
+
} from './oracle-document-tools';
|
|
19
27
|
|
|
20
28
|
const configSchema = z.object({
|
|
21
29
|
MEMORY_MCP_URL: z.string().url('MEMORY_MCP_URL must be a valid HTTP(S) URL.'),
|
|
@@ -51,6 +59,24 @@ const manifest: PluginManifest = {
|
|
|
51
59
|
tags: ['memory', 'recall', 'artifacts', 'personalization'],
|
|
52
60
|
category: 'memory',
|
|
53
61
|
visibility: 'always',
|
|
62
|
+
brief: 'add or delete oracle documents, knowledge; delete memories',
|
|
63
|
+
// Recall and saving are bound on every call. A message about memory says
|
|
64
|
+
// "Memory" to the router, and only the rare admin work needs the rest: on
|
|
65
|
+
// the first full lab run none of its 31 preloads was used.
|
|
66
|
+
routable: false,
|
|
67
|
+
// Search and add stay bound: they serve ordinary conversation. So does
|
|
68
|
+
// `list_oracle_documents`: with the domain's document index in the prompt,
|
|
69
|
+
// a catalogue line alone did not get a model to look past that index. These
|
|
70
|
+
// serve a controller curating the oracle, or a user asking to forget, and
|
|
71
|
+
// carry most of the plugin's tool text.
|
|
72
|
+
onDemandTools: [
|
|
73
|
+
MEMORY_ADD_ORACLE_KNOWLEDGE_MCP_NAME,
|
|
74
|
+
MEMORY_DELETE_EPISODE_MCP_NAME,
|
|
75
|
+
MEMORY_DELETE_EDGE_MCP_NAME,
|
|
76
|
+
MEMORY_CLEAR_MCP_NAME,
|
|
77
|
+
ADD_ORACLE_DOCUMENT_TOOL_NAME,
|
|
78
|
+
DELETE_ORACLE_DOCUMENT_TOOL_NAME,
|
|
79
|
+
],
|
|
54
80
|
stability: 'stable',
|
|
55
81
|
requires: [MEMORY_CAPABILITY],
|
|
56
82
|
};
|