@ixo/editor 4.3.1 → 5.1.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/dist/{chunk-B7UIUYP5.mjs → chunk-75MWYZJ2.mjs} +1365 -144
- package/dist/chunk-75MWYZJ2.mjs.map +1 -0
- package/dist/{chunk-LXEEL4NA.mjs → chunk-AT7JTDI3.mjs} +2 -2
- package/dist/{chunk-JMWCQ67Z.mjs → chunk-ZA2A4NPL.mjs} +6346 -1147
- package/dist/chunk-ZA2A4NPL.mjs.map +1 -0
- package/dist/core/index.d.ts +130 -24
- package/dist/core/index.mjs +388 -4
- package/dist/core/index.mjs.map +1 -1
- package/dist/{decompile-rdAf19Es.d.ts → decompile-DssmD-Wl.d.ts} +210 -2
- package/dist/{graphql-client-DJcK_z3q.d.ts → graphql-client-DwJcFIxW.d.ts} +32 -1
- package/dist/{index-ClqpuDwu.d.ts → index-CwNHHLM8.d.ts} +117 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +3 -3
- package/dist/mantine/index.d.ts +4 -4
- package/dist/mantine/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-B7UIUYP5.mjs.map +0 -1
- package/dist/chunk-JMWCQ67Z.mjs.map +0 -1
- /package/dist/{chunk-LXEEL4NA.mjs.map → chunk-AT7JTDI3.mjs.map} +0 -0
|
@@ -15,7 +15,6 @@ var ACTION_TYPE_ALIASES = {
|
|
|
15
15
|
"proposal.vote": "qi/proposal.vote",
|
|
16
16
|
"protocol.select": "qi/protocol.select",
|
|
17
17
|
"domain.sign": "qi/domain.sign",
|
|
18
|
-
"domain.card-build": "qi/domain.card-build",
|
|
19
18
|
"domain.card-preview": "qi/domain.card-preview",
|
|
20
19
|
"credential.store": "qi/credential.store",
|
|
21
20
|
// POD setup flow — camelCase orchestrator labels → canonical action types
|
|
@@ -62,7 +61,6 @@ var CAN_TO_TYPE = {
|
|
|
62
61
|
"matrix/dm": "qi/matrix.dm",
|
|
63
62
|
"proposal/create": "qi/proposal.create",
|
|
64
63
|
"proposal/vote": "qi/proposal.vote",
|
|
65
|
-
"domain/card-build": "qi/domain.card-build",
|
|
66
64
|
"domain/card-preview": "qi/domain.card-preview",
|
|
67
65
|
"domain/sign": "qi/domain.sign",
|
|
68
66
|
"credential/store": "qi/credential.store",
|
|
@@ -77,7 +75,17 @@ var CAN_TO_TYPE = {
|
|
|
77
75
|
"pod/entity-single-selection": "qi/pod.entity-single-selection",
|
|
78
76
|
"pod/governance-config": "qi/pod.governance-config",
|
|
79
77
|
"pod/member-multi-select": "qi/pod.member-multi-select",
|
|
80
|
-
"pod/list-domain-flows": "qi/pod.list-domain-flows"
|
|
78
|
+
"pod/list-domain-flows": "qi/pod.list-domain-flows",
|
|
79
|
+
"wallet/generate": "qi/wallet.generate",
|
|
80
|
+
"wallet/fund": "qi/wallet.fund",
|
|
81
|
+
"iid/create": "qi/iid.create",
|
|
82
|
+
"matrix/register": "qi/matrix.register",
|
|
83
|
+
"entity/createOracle": "qi/entity.createOracle",
|
|
84
|
+
"sandbox/provision": "qi/sandbox.provision",
|
|
85
|
+
"oracle/contract": "qi/oracle.contract",
|
|
86
|
+
"oracle/storeSecrets": "qi/oracle.storeSecrets",
|
|
87
|
+
"oracle/storeConfig": "qi/oracle.storeConfig",
|
|
88
|
+
"oracle/configureOracle": "qi/oracle.configureOracle"
|
|
81
89
|
};
|
|
82
90
|
var TYPE_TO_CAN = Object.fromEntries(Object.entries(CAN_TO_TYPE).map(([can, type]) => [type, can]));
|
|
83
91
|
function canToType(can) {
|
|
@@ -150,6 +158,30 @@ function buildServicesFromHandlers(handlers) {
|
|
|
150
158
|
} : void 0,
|
|
151
159
|
matrix: handlers?.storeMatrixCredential ? {
|
|
152
160
|
storeCredential: async (params) => handlers.storeMatrixCredential(params)
|
|
161
|
+
} : void 0,
|
|
162
|
+
oracle: handlers?.generateWallet ? {
|
|
163
|
+
generateWallet: async () => handlers.generateWallet(),
|
|
164
|
+
fundWallet: async (params) => handlers.fundWallet(params),
|
|
165
|
+
createIidDocument: async (params) => handlers.createIidDocument(params),
|
|
166
|
+
registerMatrixAccount: async (params) => handlers.registerMatrixAccount(params),
|
|
167
|
+
createOracleEntity: async (params) => handlers.createOracleEntity(params),
|
|
168
|
+
contract: async (params) => handlers.oracleContract(params),
|
|
169
|
+
provisionSandbox: async (params) => handlers.provisionSandbox(params),
|
|
170
|
+
storeSecrets: async (params) => handlers.storeSecrets(params),
|
|
171
|
+
storeConfig: async (params) => handlers.storeOracleConfig(params),
|
|
172
|
+
validateMcpServer: handlers.validateMcpServer || (async () => ({ success: false, error: "Handler not configured" })),
|
|
173
|
+
encryptForOracle: async (params) => handlers.encryptSecretForOracle(params),
|
|
174
|
+
readStoredSecrets: async (params) => handlers.readStoredSecrets(params),
|
|
175
|
+
getNetworkConstants: async (params) => handlers.getNetworkConstants(params),
|
|
176
|
+
deploySetup: handlers.deploySetup || (async () => {
|
|
177
|
+
throw new Error("deploySetup handler not configured");
|
|
178
|
+
}),
|
|
179
|
+
deployStart: handlers.deployStart || (async () => {
|
|
180
|
+
throw new Error("deployStart handler not configured");
|
|
181
|
+
}),
|
|
182
|
+
updateOracleDomain: handlers.updateOracleDomain || (async () => {
|
|
183
|
+
throw new Error("updateOracleDomain handler not configured");
|
|
184
|
+
})
|
|
153
185
|
} : void 0
|
|
154
186
|
};
|
|
155
187
|
}
|
|
@@ -308,12 +340,31 @@ registerAction({
|
|
|
308
340
|
{ path: "nftContractAddress", displayName: "NFT Contract Address", type: "string", description: "NFT staking contract address \u2014 nftStaking only" },
|
|
309
341
|
{ path: "tokenConfig", displayName: "Token Config", type: "object", description: "Token configuration \u2014 tokenStaking only" }
|
|
310
342
|
],
|
|
343
|
+
events: [
|
|
344
|
+
{
|
|
345
|
+
name: "configured",
|
|
346
|
+
displayName: "Members Configured",
|
|
347
|
+
description: "Fires when membership configuration is complete.",
|
|
348
|
+
payloadSchema: [
|
|
349
|
+
{
|
|
350
|
+
path: "memberConfig",
|
|
351
|
+
displayName: "Member Config",
|
|
352
|
+
type: "object",
|
|
353
|
+
description: "Full member configuration (members, multisigThreshold, nftContractAddress, or tokenConfig depending on group type)"
|
|
354
|
+
}
|
|
355
|
+
],
|
|
356
|
+
pendingDisplayFields: ["memberConfig.memberCount"]
|
|
357
|
+
}
|
|
358
|
+
],
|
|
311
359
|
run: async (inputs) => {
|
|
312
360
|
const groupType = inputs.groupType || "categorical";
|
|
313
361
|
if (groupType === "nftStaking") {
|
|
314
362
|
const addr = String(inputs.nftContractAddress || "").trim();
|
|
315
363
|
if (!addr) throw new Error("NFT contract address is required for nftStaking groups");
|
|
316
|
-
return {
|
|
364
|
+
return {
|
|
365
|
+
output: { nftContractAddress: addr },
|
|
366
|
+
events: [{ name: "configured", payload: { memberConfig: { nftContractAddress: addr, memberCount: 0 } } }]
|
|
367
|
+
};
|
|
317
368
|
}
|
|
318
369
|
if (groupType === "tokenStaking") {
|
|
319
370
|
const tokenConfig = inputs.tokenConfig;
|
|
@@ -326,7 +377,10 @@ registerAction({
|
|
|
326
377
|
const supply = Number(tokenConfig.tokenSupply);
|
|
327
378
|
if (isNaN(supply) || supply <= 0) throw new Error("Token supply must be a positive number");
|
|
328
379
|
}
|
|
329
|
-
return {
|
|
380
|
+
return {
|
|
381
|
+
output: { tokenConfig },
|
|
382
|
+
events: [{ name: "configured", payload: { memberConfig: { tokenConfig, memberCount: 0 } } }]
|
|
383
|
+
};
|
|
330
384
|
}
|
|
331
385
|
const members = Array.isArray(inputs.members) ? inputs.members : [];
|
|
332
386
|
if (members.length === 0) throw new Error("At least one member is required");
|
|
@@ -337,7 +391,10 @@ registerAction({
|
|
|
337
391
|
const threshold = Number(inputs.multisigThreshold);
|
|
338
392
|
if (!Number.isInteger(threshold) || threshold < 1) throw new Error("Multisig threshold must be a positive integer");
|
|
339
393
|
if (threshold > members.length) throw new Error(`Threshold (${threshold}) cannot exceed member count (${members.length})`);
|
|
340
|
-
return {
|
|
394
|
+
return {
|
|
395
|
+
output: { members, multisigThreshold: threshold },
|
|
396
|
+
events: [{ name: "configured", payload: { memberConfig: { members, multisigThreshold: threshold, memberCount: members.length } } }]
|
|
397
|
+
};
|
|
341
398
|
}
|
|
342
399
|
const hasAdmin = members.some((m) => String(m.role || "").toLowerCase() === "admin");
|
|
343
400
|
if (!hasAdmin) throw new Error("At least one member must have the Admin role");
|
|
@@ -345,7 +402,10 @@ registerAction({
|
|
|
345
402
|
const vp = Number(m.votingPower);
|
|
346
403
|
if (!Number.isInteger(vp) || vp <= 0) throw new Error(`Voting power must be a positive integer (got ${m.votingPower} for ${m.did})`);
|
|
347
404
|
}
|
|
348
|
-
return {
|
|
405
|
+
return {
|
|
406
|
+
output: { members },
|
|
407
|
+
events: [{ name: "configured", payload: { memberConfig: { members, memberCount: members.length } } }]
|
|
408
|
+
};
|
|
349
409
|
}
|
|
350
410
|
});
|
|
351
411
|
|
|
@@ -361,6 +421,19 @@ registerAction({
|
|
|
361
421
|
{ path: "groupType", displayName: "Group Type", type: "string", description: "Governance group type (categorical | multisig | nftStaking | tokenStaking)" },
|
|
362
422
|
{ path: "governance", displayName: "Governance Settings", type: "object", description: "Cosmos group decision policy parameters" }
|
|
363
423
|
],
|
|
424
|
+
events: [
|
|
425
|
+
{
|
|
426
|
+
name: "configured",
|
|
427
|
+
displayName: "Governance Configured",
|
|
428
|
+
description: "Fires when governance group type and decision policy are configured.",
|
|
429
|
+
payloadSchema: [
|
|
430
|
+
{ path: "governanceConfig.groupName", displayName: "Group Name", type: "string" },
|
|
431
|
+
{ path: "governanceConfig.groupType", displayName: "Group Type", type: "string" },
|
|
432
|
+
{ path: "governanceConfig.governance", displayName: "Governance Settings", type: "object" }
|
|
433
|
+
],
|
|
434
|
+
pendingDisplayFields: ["governanceConfig.groupName", "governanceConfig.groupType"]
|
|
435
|
+
}
|
|
436
|
+
],
|
|
364
437
|
run: async (inputs) => {
|
|
365
438
|
const groupName = String(inputs.groupName || "").trim();
|
|
366
439
|
if (!groupName) throw new Error("groupName is required");
|
|
@@ -387,7 +460,10 @@ registerAction({
|
|
|
387
460
|
throw new Error("threshold + vetoThreshold cannot exceed 1.0");
|
|
388
461
|
}
|
|
389
462
|
}
|
|
390
|
-
return {
|
|
463
|
+
return {
|
|
464
|
+
output: { groupName, groupType, governance },
|
|
465
|
+
events: [{ name: "configured", payload: { governanceConfig: { groupName, groupType, governance } } }]
|
|
466
|
+
};
|
|
391
467
|
}
|
|
392
468
|
});
|
|
393
469
|
|
|
@@ -2233,16 +2309,119 @@ var tempDomainCreatorSurvey = {
|
|
|
2233
2309
|
};
|
|
2234
2310
|
|
|
2235
2311
|
// src/core/lib/actionRegistry/actions/domainSign.ts
|
|
2312
|
+
function resolveEntityTypeFromSchema(schemaType) {
|
|
2313
|
+
const normalized = schemaType.replace(/^schema:/i, "").toLowerCase();
|
|
2314
|
+
const schemaToEntity = {
|
|
2315
|
+
organization: "dao",
|
|
2316
|
+
nonprofit: "dao",
|
|
2317
|
+
corporation: "dao",
|
|
2318
|
+
governmentorganization: "dao"
|
|
2319
|
+
};
|
|
2320
|
+
if (schemaToEntity[normalized]) return schemaToEntity[normalized];
|
|
2321
|
+
const allowed = /* @__PURE__ */ new Set(["dao", "protocol", "oracle", "investment", "project", "asset"]);
|
|
2322
|
+
return allowed.has(normalized) ? normalized : "dao";
|
|
2323
|
+
}
|
|
2324
|
+
function parseJsonInput(value) {
|
|
2325
|
+
if (!value) return null;
|
|
2326
|
+
if (typeof value === "object" && !Array.isArray(value)) return value;
|
|
2327
|
+
if (typeof value === "string") {
|
|
2328
|
+
try {
|
|
2329
|
+
const parsed = JSON.parse(value);
|
|
2330
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
2331
|
+
} catch {
|
|
2332
|
+
return null;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
return null;
|
|
2336
|
+
}
|
|
2337
|
+
function parseDuration(raw) {
|
|
2338
|
+
const seconds = parseInt(raw, 10) || 0;
|
|
2339
|
+
if (seconds % (7 * 86400) === 0) return { amount: seconds / (7 * 86400), unit: "weeks" };
|
|
2340
|
+
if (seconds % 86400 === 0) return { amount: seconds / 86400, unit: "days" };
|
|
2341
|
+
if (seconds % 3600 === 0) return { amount: seconds / 3600, unit: "hours" };
|
|
2342
|
+
if (seconds % 60 === 0) return { amount: seconds / 60, unit: "minutes" };
|
|
2343
|
+
return { amount: seconds, unit: "seconds" };
|
|
2344
|
+
}
|
|
2345
|
+
function buildGroupConfig(groupType, governance, memberConfig) {
|
|
2346
|
+
const duration = parseDuration(governance.votingPeriod || "604800s");
|
|
2347
|
+
const thresholdNum = parseFloat(governance.threshold || "0.51");
|
|
2348
|
+
const baseConfig = {
|
|
2349
|
+
proposalDurationAmount: duration.amount,
|
|
2350
|
+
proposalDurationUnit: duration.unit,
|
|
2351
|
+
proposalSubmissionPolicy: "members",
|
|
2352
|
+
voteSwitching: false
|
|
2353
|
+
};
|
|
2354
|
+
if (groupType === "multisig") {
|
|
2355
|
+
const members2 = memberConfig?.members || [];
|
|
2356
|
+
return {
|
|
2357
|
+
threshold: memberConfig?.multisigThreshold || 1,
|
|
2358
|
+
membershipCategory: [{ members: members2.map((m) => m.did) }]
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2361
|
+
if (groupType === "nftStaking") {
|
|
2362
|
+
return {
|
|
2363
|
+
...baseConfig,
|
|
2364
|
+
nftContractAddress: memberConfig?.nftContractAddress || "",
|
|
2365
|
+
unstakingDuration: governance.unstakingDuration ? parseDuration(governance.unstakingDuration) : void 0
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
if (groupType === "tokenStaking") {
|
|
2369
|
+
const tokenConfig = memberConfig?.tokenConfig || {};
|
|
2370
|
+
return {
|
|
2371
|
+
...baseConfig,
|
|
2372
|
+
passingThreshold: thresholdNum === 0.5 ? "majority" : "percentage",
|
|
2373
|
+
passingThresholdPercentage: Math.round(thresholdNum * 100),
|
|
2374
|
+
tokenName: tokenConfig.tokenName || "",
|
|
2375
|
+
tokenSymbol: tokenConfig.tokenSymbol || "",
|
|
2376
|
+
tokenSupply: tokenConfig.tokenSupply || 0,
|
|
2377
|
+
distributionCategory: tokenConfig.distributionCategory || [],
|
|
2378
|
+
unstakingDuration: governance.unstakingDuration ? parseDuration(governance.unstakingDuration) : void 0
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
const members = memberConfig?.members || [];
|
|
2382
|
+
const byRole = /* @__PURE__ */ new Map();
|
|
2383
|
+
for (const m of members) {
|
|
2384
|
+
const role = m.role || "member";
|
|
2385
|
+
const existing = byRole.get(role);
|
|
2386
|
+
if (existing) {
|
|
2387
|
+
existing.dids.push(m.did);
|
|
2388
|
+
} else {
|
|
2389
|
+
byRole.set(role, { dids: [m.did], weight: m.votingPower || 1 });
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
return {
|
|
2393
|
+
...baseConfig,
|
|
2394
|
+
passingThreshold: thresholdNum === 0.5 ? "majority" : "percentage",
|
|
2395
|
+
passingThresholdPercentage: Math.round(thresholdNum * 100),
|
|
2396
|
+
membershipCategory: Array.from(byRole.values()).map(({ dids, weight }) => ({
|
|
2397
|
+
members: dids.map((did) => ({ memberAddress: did })),
|
|
2398
|
+
weightPerMember: weight
|
|
2399
|
+
}))
|
|
2400
|
+
};
|
|
2401
|
+
}
|
|
2236
2402
|
registerAction({
|
|
2237
2403
|
type: "qi/domain.sign",
|
|
2238
2404
|
can: "domain/sign",
|
|
2239
2405
|
sideEffect: true,
|
|
2240
2406
|
defaultRequiresConfirmation: true,
|
|
2241
2407
|
requiredCapability: "flow/block/execute",
|
|
2408
|
+
eligibleForEventTrigger: true,
|
|
2242
2409
|
outputSchema: [
|
|
2243
2410
|
{ path: "entityDid", displayName: "Entity DID", type: "string", description: "The DID of the newly created domain entity" },
|
|
2244
2411
|
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The on-chain transaction hash for domain creation" }
|
|
2245
2412
|
],
|
|
2413
|
+
events: [
|
|
2414
|
+
{
|
|
2415
|
+
name: "created",
|
|
2416
|
+
displayName: "Domain Created",
|
|
2417
|
+
description: "Fires after the domain entity is successfully created on-chain.",
|
|
2418
|
+
payloadSchema: [
|
|
2419
|
+
{ path: "entityDid", displayName: "Entity DID", type: "string", description: "DID of the newly created domain" },
|
|
2420
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "On-chain transaction hash" }
|
|
2421
|
+
],
|
|
2422
|
+
pendingDisplayFields: ["entityDid"]
|
|
2423
|
+
}
|
|
2424
|
+
],
|
|
2246
2425
|
run: async (inputs, ctx) => {
|
|
2247
2426
|
const handlers = ctx.handlers;
|
|
2248
2427
|
if (!handlers) {
|
|
@@ -2267,8 +2446,7 @@ registerAction({
|
|
|
2267
2446
|
if (!domainCardData?.credentialSubject?.name) {
|
|
2268
2447
|
throw new Error("domainCardData is missing or invalid (credentialSubject.name required)");
|
|
2269
2448
|
}
|
|
2270
|
-
const
|
|
2271
|
-
const entityType = String(inputs.entityType || "").trim() || (domainCardData.credentialSubject?.type?.[0] ? extractEntityType(domainCardData.credentialSubject.type[0]) : "dao");
|
|
2449
|
+
const entityType = String(inputs.entityType || "").trim() || (domainCardData.credentialSubject?.type?.[0] ? resolveEntityTypeFromSchema(domainCardData.credentialSubject.type[0]) : "dao");
|
|
2272
2450
|
const issuerDid = handlers.getEntityDid?.() || handlers.getCurrentUser?.()?.address;
|
|
2273
2451
|
if (!issuerDid) throw new Error("Unable to determine issuer DID");
|
|
2274
2452
|
const entityDidPlaceholder = "did:ixo:entity:pending";
|
|
@@ -2313,18 +2491,27 @@ registerAction({
|
|
|
2313
2491
|
serviceEndpoint: uploadResult.url,
|
|
2314
2492
|
description: `Domain Card for ${domainCardData.credentialSubject?.name || "Domain"}`
|
|
2315
2493
|
});
|
|
2316
|
-
let
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2494
|
+
let governanceGroupLinkedEntities = [];
|
|
2495
|
+
const govConfig = parseJsonInput(inputs.governanceConfig);
|
|
2496
|
+
const memberConfig = parseJsonInput(inputs.memberConfig);
|
|
2497
|
+
if (govConfig && handlers.createGovernanceGroup) {
|
|
2498
|
+
const groupType = govConfig.groupType;
|
|
2499
|
+
const governance = govConfig.governance || {};
|
|
2500
|
+
const config = buildGroupConfig(groupType, governance, memberConfig);
|
|
2501
|
+
const groupResult = await handlers.createGovernanceGroup({
|
|
2502
|
+
groupType,
|
|
2503
|
+
name: govConfig.groupName || domainCardData.credentialSubject?.name || "Governance Group",
|
|
2504
|
+
config
|
|
2505
|
+
});
|
|
2506
|
+
governanceGroupLinkedEntities = [
|
|
2507
|
+
{
|
|
2508
|
+
id: groupResult.coreAddress,
|
|
2509
|
+
type: "group",
|
|
2510
|
+
relationship: "governs",
|
|
2511
|
+
service: ""
|
|
2322
2512
|
}
|
|
2323
|
-
|
|
2324
|
-
linkedEntitiesData = inputs.linkedEntities;
|
|
2325
|
-
}
|
|
2513
|
+
];
|
|
2326
2514
|
}
|
|
2327
|
-
const governanceGroupLinkedEntities = buildGovernanceGroupLinkedEntities(parseLinkedEntities(JSON.stringify(linkedEntitiesData)));
|
|
2328
2515
|
const endDate = domainCardData.endDate || validUntil;
|
|
2329
2516
|
const { entityDid: newEntityDid, transactionHash } = await handlers.createDomain({
|
|
2330
2517
|
entityType,
|
|
@@ -2337,81 +2524,8 @@ registerAction({
|
|
|
2337
2524
|
output: {
|
|
2338
2525
|
entityDid: newEntityDid,
|
|
2339
2526
|
transactionHash
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
|
-
}
|
|
2343
|
-
});
|
|
2344
|
-
|
|
2345
|
-
// src/core/lib/actionRegistry/actions/domainCardBuild.ts
|
|
2346
|
-
registerAction({
|
|
2347
|
-
type: "qi/domain.card-build",
|
|
2348
|
-
can: "domain/card-build",
|
|
2349
|
-
sideEffect: false,
|
|
2350
|
-
defaultRequiresConfirmation: false,
|
|
2351
|
-
outputSchema: [
|
|
2352
|
-
{
|
|
2353
|
-
path: "domainCardData",
|
|
2354
|
-
displayName: "Domain Card Data",
|
|
2355
|
-
type: "object",
|
|
2356
|
-
description: "Unsigned domain card envelope { credentialSubject, validFrom, validUntil } ready for preview and signing"
|
|
2357
|
-
},
|
|
2358
|
-
{ path: "unsignedCredential", displayName: "Unsigned Credential", type: "object", description: "The full unsigned W3C Verifiable Credential" },
|
|
2359
|
-
{ path: "credentialSubject", displayName: "Credential Subject", type: "object", description: "The ixo:DomainCard credentialSubject extracted from the survey" },
|
|
2360
|
-
{ path: "surveyData", displayName: "Survey Answers", type: "object", description: "Raw survey answers used to build the card" },
|
|
2361
|
-
{ path: "entityType", displayName: "Entity Type", type: "string", description: "Resolved entity type (from survey or configured default)" },
|
|
2362
|
-
{ path: "issuerDid", displayName: "Issuer DID", type: "string", description: "DID of the user or entity that built the card" }
|
|
2363
|
-
],
|
|
2364
|
-
run: async (inputs, ctx) => {
|
|
2365
|
-
const handlers = ctx.handlers;
|
|
2366
|
-
if (!handlers) throw new Error("Handlers not available");
|
|
2367
|
-
const configEntityType = String(inputs.entityType || "dao").trim();
|
|
2368
|
-
let surveyData = {};
|
|
2369
|
-
if (inputs.surveyData) {
|
|
2370
|
-
if (typeof inputs.surveyData === "string") {
|
|
2371
|
-
try {
|
|
2372
|
-
surveyData = JSON.parse(inputs.surveyData);
|
|
2373
|
-
} catch {
|
|
2374
|
-
throw new Error("surveyData must be valid JSON");
|
|
2375
|
-
}
|
|
2376
|
-
} else if (typeof inputs.surveyData === "object" && !Array.isArray(inputs.surveyData)) {
|
|
2377
|
-
surveyData = inputs.surveyData;
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
if (!surveyData || Object.keys(surveyData).length === 0) {
|
|
2381
|
-
throw new Error("surveyData is required to build a domain card");
|
|
2382
|
-
}
|
|
2383
|
-
const issuerDid = handlers.getEntityDid?.() || handlers.getCurrentUser?.()?.address;
|
|
2384
|
-
if (!issuerDid) throw new Error("Unable to determine issuer DID");
|
|
2385
|
-
const entityDidPlaceholder = "did:ixo:entity:pending";
|
|
2386
|
-
const credentialSubject = transformSurveyToCredentialSubject(surveyData, entityDidPlaceholder);
|
|
2387
|
-
const validFrom = surveyData["schema:validFrom"] || (/* @__PURE__ */ new Date()).toISOString();
|
|
2388
|
-
const validUntil = surveyData["schema:validUntil"] || (() => {
|
|
2389
|
-
const d = new Date(validFrom);
|
|
2390
|
-
d.setFullYear(d.getFullYear() + 5);
|
|
2391
|
-
return d.toISOString();
|
|
2392
|
-
})();
|
|
2393
|
-
const unsignedCredential = buildVerifiableCredential({
|
|
2394
|
-
entityDid: entityDidPlaceholder,
|
|
2395
|
-
issuerDid,
|
|
2396
|
-
credentialSubject,
|
|
2397
|
-
validFrom,
|
|
2398
|
-
validUntil
|
|
2399
|
-
});
|
|
2400
|
-
const resolvedEntityType = surveyData["type_2"] || surveyData["daoType"] || configEntityType;
|
|
2401
|
-
const domainCardData = {
|
|
2402
|
-
credentialSubject,
|
|
2403
|
-
validFrom,
|
|
2404
|
-
validUntil
|
|
2405
|
-
};
|
|
2406
|
-
return {
|
|
2407
|
-
output: {
|
|
2408
|
-
domainCardData,
|
|
2409
|
-
unsignedCredential,
|
|
2410
|
-
credentialSubject,
|
|
2411
|
-
surveyData,
|
|
2412
|
-
entityType: resolvedEntityType,
|
|
2413
|
-
issuerDid
|
|
2414
|
-
}
|
|
2527
|
+
},
|
|
2528
|
+
events: [{ name: "created", payload: { entityDid: newEntityDid, transactionHash } }]
|
|
2415
2529
|
};
|
|
2416
2530
|
}
|
|
2417
2531
|
});
|
|
@@ -2433,6 +2547,18 @@ registerAction({
|
|
|
2433
2547
|
{ path: "status", displayName: "Status", type: "string", description: "pending | loading | ready | approved | error" },
|
|
2434
2548
|
{ path: "approvedAt", displayName: "Approved At", type: "number", description: "Timestamp when the user approved the preview" }
|
|
2435
2549
|
],
|
|
2550
|
+
events: [
|
|
2551
|
+
{
|
|
2552
|
+
name: "approved",
|
|
2553
|
+
displayName: "Preview Approved",
|
|
2554
|
+
description: "Fires when the user approves the oracle-enriched domain card preview.",
|
|
2555
|
+
payloadSchema: [
|
|
2556
|
+
{ path: "domainCardData", displayName: "Domain Card Data", type: "object", description: "Approved domain card envelope ready for signing" },
|
|
2557
|
+
{ path: "approvedAt", displayName: "Approved At", type: "number", description: "Timestamp of approval" }
|
|
2558
|
+
],
|
|
2559
|
+
pendingDisplayFields: ["approvedAt"]
|
|
2560
|
+
}
|
|
2561
|
+
],
|
|
2436
2562
|
run: async (inputs) => {
|
|
2437
2563
|
let domainCardData = inputs.domainCardData;
|
|
2438
2564
|
if (typeof domainCardData === "string") {
|
|
@@ -2456,13 +2582,15 @@ registerAction({
|
|
|
2456
2582
|
domainPreviewData = void 0;
|
|
2457
2583
|
}
|
|
2458
2584
|
}
|
|
2585
|
+
const now = Date.now();
|
|
2459
2586
|
return {
|
|
2460
2587
|
output: {
|
|
2461
2588
|
domainCardData,
|
|
2462
2589
|
domainPreviewData,
|
|
2463
2590
|
status: "approved",
|
|
2464
|
-
approvedAt:
|
|
2465
|
-
}
|
|
2591
|
+
approvedAt: now
|
|
2592
|
+
},
|
|
2593
|
+
events: [{ name: "approved", payload: { domainCardData, approvedAt: now } }]
|
|
2466
2594
|
};
|
|
2467
2595
|
}
|
|
2468
2596
|
});
|
|
@@ -2608,6 +2736,853 @@ registerAction({
|
|
|
2608
2736
|
}
|
|
2609
2737
|
});
|
|
2610
2738
|
|
|
2739
|
+
// src/core/lib/actionRegistry/actions/walletGenerate.ts
|
|
2740
|
+
registerAction({
|
|
2741
|
+
type: "qi/wallet.generate",
|
|
2742
|
+
can: "wallet/generate",
|
|
2743
|
+
sideEffect: false,
|
|
2744
|
+
defaultRequiresConfirmation: false,
|
|
2745
|
+
outputSchema: [
|
|
2746
|
+
{ path: "address", displayName: "Wallet Address", type: "string", description: "The generated IXO wallet address" },
|
|
2747
|
+
{ path: "did", displayName: "DID", type: "string", description: "The DID derived from the wallet address" },
|
|
2748
|
+
{ path: "pubKey", displayName: "Public Key", type: "string", description: "The secp256k1 public key (hex)" },
|
|
2749
|
+
{ path: "mnemonic", displayName: "Mnemonic", type: "string", description: "The BIP39 mnemonic seed phrase" }
|
|
2750
|
+
],
|
|
2751
|
+
run: async (_inputs, ctx) => {
|
|
2752
|
+
if (!ctx.services.oracle?.generateWallet) {
|
|
2753
|
+
throw new Error("oracle.generateWallet handler not available");
|
|
2754
|
+
}
|
|
2755
|
+
const result = await ctx.services.oracle.generateWallet();
|
|
2756
|
+
return { output: result };
|
|
2757
|
+
}
|
|
2758
|
+
});
|
|
2759
|
+
|
|
2760
|
+
// src/core/lib/actionRegistry/actions/walletFund.ts
|
|
2761
|
+
registerAction({
|
|
2762
|
+
type: "qi/wallet.fund",
|
|
2763
|
+
can: "wallet/fund",
|
|
2764
|
+
sideEffect: true,
|
|
2765
|
+
defaultRequiresConfirmation: true,
|
|
2766
|
+
outputSchema: [
|
|
2767
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The funding transaction hash" }
|
|
2768
|
+
],
|
|
2769
|
+
run: async (inputs, ctx) => {
|
|
2770
|
+
if (!ctx.services.oracle?.fundWallet) {
|
|
2771
|
+
throw new Error("oracle.fundWallet handler not available");
|
|
2772
|
+
}
|
|
2773
|
+
if (!inputs.address) throw new Error("address is required");
|
|
2774
|
+
const result = await ctx.services.oracle.fundWallet({
|
|
2775
|
+
address: inputs.address,
|
|
2776
|
+
amount: inputs.amount || 25e4
|
|
2777
|
+
});
|
|
2778
|
+
return { output: result };
|
|
2779
|
+
}
|
|
2780
|
+
});
|
|
2781
|
+
|
|
2782
|
+
// src/core/lib/actionRegistry/actions/walletGenerateAndFund.ts
|
|
2783
|
+
registerAction({
|
|
2784
|
+
type: "qi/wallet.generateAndFund",
|
|
2785
|
+
can: "wallet/generateAndFund",
|
|
2786
|
+
sideEffect: true,
|
|
2787
|
+
defaultRequiresConfirmation: false,
|
|
2788
|
+
outputSchema: [
|
|
2789
|
+
{ path: "address", displayName: "Wallet Address", type: "string", description: "The generated IXO wallet address" },
|
|
2790
|
+
{ path: "did", displayName: "DID", type: "string", description: "The DID derived from the wallet address" },
|
|
2791
|
+
{ path: "pubKey", displayName: "Public Key", type: "string", description: "The secp256k1 public key (hex)" },
|
|
2792
|
+
{ path: "mnemonic", displayName: "Mnemonic", type: "string", description: "The BIP39 mnemonic seed phrase" },
|
|
2793
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The funding transaction hash" }
|
|
2794
|
+
],
|
|
2795
|
+
run: async (inputs, ctx) => {
|
|
2796
|
+
if (!ctx.services.oracle?.generateWallet) {
|
|
2797
|
+
throw new Error("oracle.generateWallet handler not available");
|
|
2798
|
+
}
|
|
2799
|
+
if (!ctx.services.oracle?.fundWallet) {
|
|
2800
|
+
throw new Error("oracle.fundWallet handler not available");
|
|
2801
|
+
}
|
|
2802
|
+
const walletResult = await ctx.services.oracle.generateWallet();
|
|
2803
|
+
if (!walletResult?.address) {
|
|
2804
|
+
throw new Error("generateWallet did not return an address");
|
|
2805
|
+
}
|
|
2806
|
+
const fundResult = await ctx.services.oracle.fundWallet({
|
|
2807
|
+
address: walletResult.address,
|
|
2808
|
+
amount: inputs.amount || 25e4
|
|
2809
|
+
});
|
|
2810
|
+
if (!fundResult?.transactionHash) {
|
|
2811
|
+
throw new Error("fundWallet did not return a transactionHash");
|
|
2812
|
+
}
|
|
2813
|
+
return {
|
|
2814
|
+
output: {
|
|
2815
|
+
address: walletResult.address,
|
|
2816
|
+
did: walletResult.did,
|
|
2817
|
+
pubKey: walletResult.pubKey,
|
|
2818
|
+
mnemonic: walletResult.mnemonic,
|
|
2819
|
+
transactionHash: fundResult.transactionHash
|
|
2820
|
+
}
|
|
2821
|
+
};
|
|
2822
|
+
}
|
|
2823
|
+
});
|
|
2824
|
+
|
|
2825
|
+
// src/core/lib/actionRegistry/actions/iidCreate.ts
|
|
2826
|
+
registerAction({
|
|
2827
|
+
type: "qi/iid.create",
|
|
2828
|
+
can: "iid/create",
|
|
2829
|
+
sideEffect: true,
|
|
2830
|
+
defaultRequiresConfirmation: false,
|
|
2831
|
+
outputSchema: [
|
|
2832
|
+
{ path: "did", displayName: "DID", type: "string", description: "The IID document DID" },
|
|
2833
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The IID creation transaction hash" }
|
|
2834
|
+
],
|
|
2835
|
+
run: async (inputs, ctx) => {
|
|
2836
|
+
if (!ctx.services.oracle?.createIidDocument) {
|
|
2837
|
+
throw new Error("oracle.createIidDocument handler not available");
|
|
2838
|
+
}
|
|
2839
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required");
|
|
2840
|
+
if (!inputs.did) throw new Error("did is required");
|
|
2841
|
+
if (!inputs.address) throw new Error("address is required");
|
|
2842
|
+
if (!inputs.pubKey) throw new Error("pubKey is required");
|
|
2843
|
+
const result = await ctx.services.oracle.createIidDocument({
|
|
2844
|
+
mnemonic: inputs.mnemonic,
|
|
2845
|
+
did: inputs.did,
|
|
2846
|
+
address: inputs.address,
|
|
2847
|
+
pubKey: inputs.pubKey
|
|
2848
|
+
});
|
|
2849
|
+
return { output: result };
|
|
2850
|
+
}
|
|
2851
|
+
});
|
|
2852
|
+
|
|
2853
|
+
// src/core/lib/actionRegistry/actions/matrixRegister.ts
|
|
2854
|
+
registerAction({
|
|
2855
|
+
type: "qi/matrix.register",
|
|
2856
|
+
can: "matrix/register",
|
|
2857
|
+
sideEffect: true,
|
|
2858
|
+
defaultRequiresConfirmation: false,
|
|
2859
|
+
outputSchema: [
|
|
2860
|
+
{ path: "matrixUserId", displayName: "Matrix User ID", type: "string", description: "The Matrix user ID" },
|
|
2861
|
+
{ path: "matrixAccessToken", displayName: "Matrix Access Token", type: "string", description: "The Matrix access token" },
|
|
2862
|
+
{ path: "matrixRoomId", displayName: "Matrix Room ID", type: "string", description: "The Matrix room ID" },
|
|
2863
|
+
{ path: "matrixDeviceId", displayName: "Matrix Device ID", type: "string", description: "The Matrix device ID" },
|
|
2864
|
+
{ path: "matrixMnemonic", displayName: "Matrix Mnemonic", type: "string", description: "The Matrix account mnemonic" },
|
|
2865
|
+
{ path: "matrixPassword", displayName: "Matrix Password", type: "string", description: "The Matrix account password" },
|
|
2866
|
+
{ path: "matrixRecoveryPhrase", displayName: "Recovery Phrase", type: "string", description: "The Matrix recovery phrase" },
|
|
2867
|
+
{ path: "matrixHomeServerUrl", displayName: "Matrix Homeserver", type: "string", description: "The Matrix homeserver URL" }
|
|
2868
|
+
],
|
|
2869
|
+
run: async (inputs, ctx) => {
|
|
2870
|
+
if (!ctx.services.oracle?.registerMatrixAccount) {
|
|
2871
|
+
throw new Error("oracle.registerMatrixAccount handler not available");
|
|
2872
|
+
}
|
|
2873
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required");
|
|
2874
|
+
if (!inputs.address) throw new Error("address is required");
|
|
2875
|
+
if (!inputs.did) throw new Error("did is required");
|
|
2876
|
+
if (!inputs.pin) throw new Error("pin is required");
|
|
2877
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
2878
|
+
const result = await ctx.services.oracle.registerMatrixAccount({
|
|
2879
|
+
mnemonic: inputs.mnemonic,
|
|
2880
|
+
address: inputs.address,
|
|
2881
|
+
did: inputs.did,
|
|
2882
|
+
pin: inputs.pin,
|
|
2883
|
+
oracleName: inputs.oracleName,
|
|
2884
|
+
avatarUrl: inputs.avatarUrl
|
|
2885
|
+
});
|
|
2886
|
+
return { output: result };
|
|
2887
|
+
}
|
|
2888
|
+
});
|
|
2889
|
+
|
|
2890
|
+
// src/core/lib/actionRegistry/actions/identityCreate.ts
|
|
2891
|
+
registerAction({
|
|
2892
|
+
type: "qi/identity.create",
|
|
2893
|
+
can: "identity/create",
|
|
2894
|
+
sideEffect: true,
|
|
2895
|
+
defaultRequiresConfirmation: false,
|
|
2896
|
+
outputSchema: [
|
|
2897
|
+
{ path: "did", displayName: "DID", type: "string", description: "The IID document DID" },
|
|
2898
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The IID creation transaction hash" },
|
|
2899
|
+
{ path: "alreadyExisted", displayName: "Already Existed", type: "boolean", description: "Whether the IID document already existed" },
|
|
2900
|
+
{ path: "matrixUserId", displayName: "Matrix User ID", type: "string", description: "The Matrix user ID" },
|
|
2901
|
+
{ path: "matrixAccessToken", displayName: "Matrix Access Token", type: "string", description: "The Matrix access token" },
|
|
2902
|
+
{ path: "matrixRoomId", displayName: "Matrix Room ID", type: "string", description: "The Matrix room ID" },
|
|
2903
|
+
{ path: "matrixDeviceId", displayName: "Matrix Device ID", type: "string", description: "The Matrix device ID" },
|
|
2904
|
+
{ path: "matrixMnemonic", displayName: "Matrix Mnemonic", type: "string", description: "The Matrix account mnemonic" },
|
|
2905
|
+
{ path: "matrixPassword", displayName: "Matrix Password", type: "string", description: "The Matrix account password" },
|
|
2906
|
+
{ path: "matrixRecoveryPhrase", displayName: "Recovery Phrase", type: "string", description: "The Matrix recovery phrase" },
|
|
2907
|
+
{ path: "matrixHomeServerUrl", displayName: "Matrix Homeserver", type: "string", description: "The Matrix homeserver URL" }
|
|
2908
|
+
],
|
|
2909
|
+
run: async (rawInputs, ctx) => {
|
|
2910
|
+
const form = (() => {
|
|
2911
|
+
const raw = rawInputs.formAnswers;
|
|
2912
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
2913
|
+
try {
|
|
2914
|
+
const parsed = JSON.parse(raw);
|
|
2915
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
2916
|
+
} catch {
|
|
2917
|
+
return {};
|
|
2918
|
+
}
|
|
2919
|
+
})();
|
|
2920
|
+
const inputs = {
|
|
2921
|
+
// Rename: form.logoUrl → avatarUrl for the registerMatrixAccount handler
|
|
2922
|
+
avatarUrl: form.logoUrl,
|
|
2923
|
+
...form,
|
|
2924
|
+
...rawInputs
|
|
2925
|
+
};
|
|
2926
|
+
if (!ctx.services.oracle?.createIidDocument) {
|
|
2927
|
+
throw new Error("oracle.createIidDocument handler not available");
|
|
2928
|
+
}
|
|
2929
|
+
if (!ctx.services.oracle?.registerMatrixAccount) {
|
|
2930
|
+
throw new Error("oracle.registerMatrixAccount handler not available");
|
|
2931
|
+
}
|
|
2932
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required");
|
|
2933
|
+
if (!inputs.did) throw new Error("did is required");
|
|
2934
|
+
if (!inputs.address) throw new Error("address is required");
|
|
2935
|
+
if (!inputs.pubKey) throw new Error("pubKey is required");
|
|
2936
|
+
if (!inputs.pin) throw new Error("pin is required");
|
|
2937
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
2938
|
+
const iidResult = await ctx.services.oracle.createIidDocument({
|
|
2939
|
+
mnemonic: inputs.mnemonic,
|
|
2940
|
+
did: inputs.did,
|
|
2941
|
+
address: inputs.address,
|
|
2942
|
+
pubKey: inputs.pubKey
|
|
2943
|
+
});
|
|
2944
|
+
if (!iidResult?.transactionHash && !iidResult?.alreadyExisted) {
|
|
2945
|
+
throw new Error("IID creation returned success without a transaction hash or alreadyExisted flag");
|
|
2946
|
+
}
|
|
2947
|
+
const matrixResult = await ctx.services.oracle.registerMatrixAccount({
|
|
2948
|
+
mnemonic: inputs.mnemonic,
|
|
2949
|
+
address: inputs.address,
|
|
2950
|
+
did: inputs.did,
|
|
2951
|
+
pin: inputs.pin,
|
|
2952
|
+
oracleName: inputs.oracleName,
|
|
2953
|
+
avatarUrl: inputs.avatarUrl
|
|
2954
|
+
});
|
|
2955
|
+
if (!matrixResult?.matrixUserId) {
|
|
2956
|
+
throw new Error("Matrix registration returned success without a matrixUserId");
|
|
2957
|
+
}
|
|
2958
|
+
return {
|
|
2959
|
+
output: {
|
|
2960
|
+
did: iidResult.did || inputs.did,
|
|
2961
|
+
transactionHash: iidResult.transactionHash,
|
|
2962
|
+
alreadyExisted: iidResult.alreadyExisted || false,
|
|
2963
|
+
matrixUserId: matrixResult.matrixUserId,
|
|
2964
|
+
matrixAccessToken: matrixResult.matrixAccessToken,
|
|
2965
|
+
matrixRoomId: matrixResult.matrixRoomId,
|
|
2966
|
+
matrixDeviceId: matrixResult.matrixDeviceId,
|
|
2967
|
+
matrixMnemonic: matrixResult.matrixMnemonic,
|
|
2968
|
+
matrixPassword: matrixResult.matrixPassword,
|
|
2969
|
+
matrixRecoveryPhrase: matrixResult.matrixRecoveryPhrase,
|
|
2970
|
+
matrixHomeServerUrl: matrixResult.matrixHomeServerUrl
|
|
2971
|
+
}
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
});
|
|
2975
|
+
|
|
2976
|
+
// src/core/lib/actionRegistry/actions/entityCreateOracle.ts
|
|
2977
|
+
registerAction({
|
|
2978
|
+
type: "qi/entity.createOracle",
|
|
2979
|
+
can: "entity/createOracle",
|
|
2980
|
+
sideEffect: true,
|
|
2981
|
+
defaultRequiresConfirmation: false,
|
|
2982
|
+
outputSchema: [
|
|
2983
|
+
{ path: "entityDid", displayName: "Entity DID", type: "string", description: "The oracle entity DID" },
|
|
2984
|
+
{ path: "transactionHash", displayName: "Transaction Hash", type: "string", description: "The entity creation transaction hash" },
|
|
2985
|
+
{ path: "encryptionPublicKeyMultibase", displayName: "Encryption Public Key (multibase)", type: "string", description: "Multibase-encoded P-256 public key registered as a keyAgreement vm on the entity DID" },
|
|
2986
|
+
{ path: "encryptionVerificationMethodId", displayName: "Encryption Verification Method ID", type: "string", description: "DID verification method id of the P-256 keyAgreement key" }
|
|
2987
|
+
],
|
|
2988
|
+
run: async (rawInputs, ctx) => {
|
|
2989
|
+
const form = (() => {
|
|
2990
|
+
const raw = rawInputs.formAnswers;
|
|
2991
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
2992
|
+
try {
|
|
2993
|
+
const parsed = JSON.parse(raw);
|
|
2994
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
2995
|
+
} catch {
|
|
2996
|
+
return {};
|
|
2997
|
+
}
|
|
2998
|
+
})();
|
|
2999
|
+
const inputs = { ...form, ...rawInputs };
|
|
3000
|
+
if (!ctx.services.oracle?.createOracleEntity) {
|
|
3001
|
+
throw new Error("oracle.createOracleEntity handler not available");
|
|
3002
|
+
}
|
|
3003
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required");
|
|
3004
|
+
if (!inputs.address) throw new Error("address is required");
|
|
3005
|
+
if (!inputs.did) throw new Error("did is required");
|
|
3006
|
+
if (!inputs.pubKey) throw new Error("pubKey is required");
|
|
3007
|
+
if (!inputs.pin) throw new Error("pin is required");
|
|
3008
|
+
if (!inputs.matrixAccessToken) throw new Error("matrixAccessToken is required");
|
|
3009
|
+
if (!inputs.matrixRoomId) throw new Error("matrixRoomId is required");
|
|
3010
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
3011
|
+
if (!inputs.apiUrl) throw new Error("apiUrl is required");
|
|
3012
|
+
if (!inputs.price) throw new Error("price is required");
|
|
3013
|
+
const result = await ctx.services.oracle.createOracleEntity({
|
|
3014
|
+
mnemonic: inputs.mnemonic,
|
|
3015
|
+
address: inputs.address,
|
|
3016
|
+
did: inputs.did,
|
|
3017
|
+
pubKey: inputs.pubKey,
|
|
3018
|
+
pin: inputs.pin,
|
|
3019
|
+
matrixAccessToken: inputs.matrixAccessToken,
|
|
3020
|
+
matrixRoomId: inputs.matrixRoomId,
|
|
3021
|
+
oracleName: inputs.oracleName,
|
|
3022
|
+
orgName: inputs.orgName,
|
|
3023
|
+
description: inputs.description,
|
|
3024
|
+
location: inputs.location,
|
|
3025
|
+
logoUrl: inputs.logoUrl,
|
|
3026
|
+
coverImageUrl: inputs.coverImageUrl,
|
|
3027
|
+
apiUrl: inputs.apiUrl,
|
|
3028
|
+
price: inputs.price,
|
|
3029
|
+
llmModel: inputs.llmModel,
|
|
3030
|
+
opening: inputs.opening,
|
|
3031
|
+
communicationStyle: inputs.communicationStyle,
|
|
3032
|
+
capabilities: inputs.capabilities,
|
|
3033
|
+
mcpConfig: inputs.mcpConfig,
|
|
3034
|
+
parentProtocol: inputs.parentProtocol
|
|
3035
|
+
});
|
|
3036
|
+
return { output: result };
|
|
3037
|
+
}
|
|
3038
|
+
});
|
|
3039
|
+
|
|
3040
|
+
// src/core/lib/actionRegistry/actions/sandboxProvision.ts
|
|
3041
|
+
registerAction({
|
|
3042
|
+
type: "qi/sandbox.provision",
|
|
3043
|
+
can: "sandbox/provision",
|
|
3044
|
+
sideEffect: true,
|
|
3045
|
+
defaultRequiresConfirmation: false,
|
|
3046
|
+
outputSchema: [
|
|
3047
|
+
{ path: "sandboxUrl", displayName: "Sandbox URL", type: "string", description: "The provisioned sandbox URL" },
|
|
3048
|
+
{ path: "status", displayName: "Status", type: "string", description: "Provisioning status" }
|
|
3049
|
+
],
|
|
3050
|
+
run: async (inputs, ctx) => {
|
|
3051
|
+
if (!ctx.services.oracle?.provisionSandbox) {
|
|
3052
|
+
throw new Error("oracle.provisionSandbox handler not available");
|
|
3053
|
+
}
|
|
3054
|
+
if (!inputs.entityDid) throw new Error("entityDid is required");
|
|
3055
|
+
if (!inputs.matrixRoomId) throw new Error("matrixRoomId is required");
|
|
3056
|
+
const result = await ctx.services.oracle.provisionSandbox({
|
|
3057
|
+
entityDid: inputs.entityDid,
|
|
3058
|
+
matrixRoomId: inputs.matrixRoomId
|
|
3059
|
+
});
|
|
3060
|
+
return { output: result };
|
|
3061
|
+
}
|
|
3062
|
+
});
|
|
3063
|
+
|
|
3064
|
+
// src/core/lib/actionRegistry/actions/oracleContract.ts
|
|
3065
|
+
registerAction({
|
|
3066
|
+
type: "qi/oracle.contract",
|
|
3067
|
+
can: "oracle/contract",
|
|
3068
|
+
sideEffect: true,
|
|
3069
|
+
defaultRequiresConfirmation: false,
|
|
3070
|
+
outputSchema: [
|
|
3071
|
+
{ path: "userOracleRoomId", displayName: "User\u2194Oracle Room ID", type: "string", description: "Matrix room id of the user\u2194oracle DM room" },
|
|
3072
|
+
{ path: "userOracleRoomAlias", displayName: "User\u2194Oracle Room Alias", type: "string", description: "Matrix alias of the user\u2194oracle DM room" }
|
|
3073
|
+
],
|
|
3074
|
+
run: async (inputs, ctx) => {
|
|
3075
|
+
if (!ctx.services.oracle?.contract) {
|
|
3076
|
+
throw new Error("oracle.contract handler not available");
|
|
3077
|
+
}
|
|
3078
|
+
if (!inputs.oracleEntityDid) throw new Error("oracleEntityDid is required (from entity.createOracle output)");
|
|
3079
|
+
const result = await ctx.services.oracle.contract({
|
|
3080
|
+
oracleEntityDid: inputs.oracleEntityDid
|
|
3081
|
+
});
|
|
3082
|
+
return { output: result };
|
|
3083
|
+
}
|
|
3084
|
+
});
|
|
3085
|
+
|
|
3086
|
+
// src/core/lib/actionRegistry/actions/oracleStoreSecrets.ts
|
|
3087
|
+
var SENSITIVE_PLAINTEXT_KEYS = [
|
|
3088
|
+
"SECP_MNEMONIC",
|
|
3089
|
+
"MATRIX_ORACLE_ADMIN_PASSWORD",
|
|
3090
|
+
"MATRIX_RECOVERY_PHRASE",
|
|
3091
|
+
"MATRIX_VALUE_PIN"
|
|
3092
|
+
];
|
|
3093
|
+
registerAction({
|
|
3094
|
+
type: "qi/oracle.storeSecrets",
|
|
3095
|
+
can: "oracle/storeSecrets",
|
|
3096
|
+
sideEffect: true,
|
|
3097
|
+
defaultRequiresConfirmation: false,
|
|
3098
|
+
outputSchema: [
|
|
3099
|
+
{ path: "storedSecrets", displayName: "Stored Secrets", type: "array", description: "List of secret names stored" },
|
|
3100
|
+
{ path: "roomId", displayName: "Room ID", type: "string", description: "Matrix room where secrets are stored" }
|
|
3101
|
+
],
|
|
3102
|
+
run: async (inputs, ctx) => {
|
|
3103
|
+
if (!ctx.services.oracle?.storeSecrets) {
|
|
3104
|
+
throw new Error("oracle.storeSecrets handler not available");
|
|
3105
|
+
}
|
|
3106
|
+
if (!inputs.matrixRoomId) throw new Error("matrixRoomId is required (from oracle.contract output)");
|
|
3107
|
+
if (!inputs.publicKeyMultibase) throw new Error("publicKeyMultibase is required (from entity.createOracle output)");
|
|
3108
|
+
if (!inputs.verificationMethodId) throw new Error("verificationMethodId is required (from entity.createOracle output)");
|
|
3109
|
+
if (!inputs.matrixHomeServerUrl) throw new Error("matrixHomeServerUrl is required (from matrix.register output)");
|
|
3110
|
+
if (!inputs.matrixUsername) throw new Error("matrixUsername is required (from matrix.register output matrixUserId)");
|
|
3111
|
+
if (!inputs.matrixPassword) throw new Error("matrixPassword is required (from matrix.register output)");
|
|
3112
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required (from wallet.generate output)");
|
|
3113
|
+
if (!inputs.matrixRecoveryPhrase) throw new Error("matrixRecoveryPhrase is required (from matrix.register output)");
|
|
3114
|
+
if (!inputs.pin) throw new Error("pin is required (from form output)");
|
|
3115
|
+
if (!inputs.openRouterApiKeyJwe) {
|
|
3116
|
+
throw new Error("OPEN_ROUTER_API_KEY is required \u2014 enter it in the form before submitting");
|
|
3117
|
+
}
|
|
3118
|
+
const secrets = {
|
|
3119
|
+
SECP_MNEMONIC: inputs.mnemonic,
|
|
3120
|
+
MATRIX_ORACLE_ADMIN_PASSWORD: inputs.matrixPassword,
|
|
3121
|
+
MATRIX_RECOVERY_PHRASE: inputs.matrixRecoveryPhrase,
|
|
3122
|
+
MATRIX_VALUE_PIN: inputs.pin
|
|
3123
|
+
};
|
|
3124
|
+
const preEncryptedSecrets = {
|
|
3125
|
+
OPEN_ROUTER_API_KEY: inputs.openRouterApiKeyJwe
|
|
3126
|
+
};
|
|
3127
|
+
if (inputs.mcpAuthSecrets) {
|
|
3128
|
+
try {
|
|
3129
|
+
const mcpSecrets = typeof inputs.mcpAuthSecrets === "string" ? JSON.parse(inputs.mcpAuthSecrets) : inputs.mcpAuthSecrets;
|
|
3130
|
+
if (mcpSecrets && typeof mcpSecrets === "object") {
|
|
3131
|
+
Object.assign(preEncryptedSecrets, mcpSecrets);
|
|
3132
|
+
}
|
|
3133
|
+
} catch {
|
|
3134
|
+
console.warn("[oracle.storeSecrets] Failed to parse mcpAuthSecrets");
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
for (const k of SENSITIVE_PLAINTEXT_KEYS) {
|
|
3138
|
+
if (!secrets[k]) throw new Error(`${k} is empty after assembly \u2014 refusing to call storeSecrets`);
|
|
3139
|
+
}
|
|
3140
|
+
const result = await ctx.services.oracle.storeSecrets({
|
|
3141
|
+
matrixRoomId: inputs.matrixRoomId,
|
|
3142
|
+
publicKeyMultibase: inputs.publicKeyMultibase,
|
|
3143
|
+
verificationMethodId: inputs.verificationMethodId,
|
|
3144
|
+
matrixHomeServerUrl: inputs.matrixHomeServerUrl,
|
|
3145
|
+
matrixUsername: inputs.matrixUsername,
|
|
3146
|
+
matrixPassword: inputs.matrixPassword,
|
|
3147
|
+
secrets,
|
|
3148
|
+
preEncryptedSecrets
|
|
3149
|
+
});
|
|
3150
|
+
return { output: result };
|
|
3151
|
+
}
|
|
3152
|
+
});
|
|
3153
|
+
|
|
3154
|
+
// src/core/lib/actionRegistry/actions/oracleStoreConfig.ts
|
|
3155
|
+
registerAction({
|
|
3156
|
+
type: "qi/oracle.storeConfig",
|
|
3157
|
+
can: "oracle/storeConfig",
|
|
3158
|
+
sideEffect: true,
|
|
3159
|
+
defaultRequiresConfirmation: false,
|
|
3160
|
+
outputSchema: [
|
|
3161
|
+
{ path: "configStored", displayName: "Config Stored", type: "boolean", description: "Whether the oracle config was stored successfully" },
|
|
3162
|
+
{ path: "roomId", displayName: "Room ID", type: "string", description: "The Matrix room ID where config was stored" }
|
|
3163
|
+
],
|
|
3164
|
+
run: async (inputs, ctx) => {
|
|
3165
|
+
if (!ctx.services.oracle?.storeConfig) {
|
|
3166
|
+
throw new Error("oracle.storeConfig handler not available");
|
|
3167
|
+
}
|
|
3168
|
+
if (!inputs.matrixRoomId) throw new Error("matrixRoomId is required (from oracle.contract output)");
|
|
3169
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
3170
|
+
if (!inputs.entityDid) throw new Error("entityDid is required");
|
|
3171
|
+
const result = await ctx.services.oracle.storeConfig({
|
|
3172
|
+
matrixRoomId: inputs.matrixRoomId,
|
|
3173
|
+
config: {
|
|
3174
|
+
oracleName: inputs.oracleName,
|
|
3175
|
+
orgName: inputs.orgName || "",
|
|
3176
|
+
description: inputs.description || "",
|
|
3177
|
+
location: inputs.location || "",
|
|
3178
|
+
price: inputs.price ?? 0,
|
|
3179
|
+
apiUrl: inputs.apiUrl || "",
|
|
3180
|
+
entityDid: inputs.entityDid,
|
|
3181
|
+
logoUrl: inputs.logoUrl || "",
|
|
3182
|
+
llmModel: inputs.llmModel || "",
|
|
3183
|
+
opening: inputs.opening,
|
|
3184
|
+
communicationStyle: inputs.communicationStyle,
|
|
3185
|
+
capabilities: inputs.capabilities,
|
|
3186
|
+
skills: inputs.skills,
|
|
3187
|
+
mcpServers: inputs.mcpServers,
|
|
3188
|
+
matrixUserId: inputs.matrixUserId || "",
|
|
3189
|
+
matrixAccountRoomId: inputs.matrixAccountRoomId || "",
|
|
3190
|
+
oracleAddress: inputs.oracleAddress || "",
|
|
3191
|
+
oracleDid: inputs.oracleDid || ""
|
|
3192
|
+
}
|
|
3193
|
+
});
|
|
3194
|
+
return { output: result };
|
|
3195
|
+
}
|
|
3196
|
+
});
|
|
3197
|
+
|
|
3198
|
+
// src/core/lib/actionRegistry/actions/oracleStoreSecretsAndConfig.ts
|
|
3199
|
+
var SENSITIVE_PLAINTEXT_KEYS2 = [
|
|
3200
|
+
"SECP_MNEMONIC",
|
|
3201
|
+
"MATRIX_ORACLE_ADMIN_PASSWORD",
|
|
3202
|
+
"MATRIX_RECOVERY_PHRASE",
|
|
3203
|
+
"MATRIX_VALUE_PIN"
|
|
3204
|
+
];
|
|
3205
|
+
registerAction({
|
|
3206
|
+
type: "qi/oracle.storeSecretsAndConfig",
|
|
3207
|
+
can: "oracle/storeSecretsAndConfig",
|
|
3208
|
+
sideEffect: true,
|
|
3209
|
+
defaultRequiresConfirmation: false,
|
|
3210
|
+
outputSchema: [
|
|
3211
|
+
{ path: "storedSecrets", displayName: "Stored Secrets", type: "array", description: "List of secret names stored" },
|
|
3212
|
+
{ path: "roomId", displayName: "Room ID", type: "string", description: "Matrix room where data is stored" },
|
|
3213
|
+
{ path: "configStored", displayName: "Config Stored", type: "boolean", description: "Whether oracle config was stored" }
|
|
3214
|
+
],
|
|
3215
|
+
run: async (inputs, ctx) => {
|
|
3216
|
+
if (!ctx.services.oracle?.storeSecrets) throw new Error("oracle.storeSecrets handler not available");
|
|
3217
|
+
if (!ctx.services.oracle?.storeConfig) throw new Error("oracle.storeConfig handler not available");
|
|
3218
|
+
if (!inputs.matrixRoomId) throw new Error("matrixRoomId is required (from oracle.contract output)");
|
|
3219
|
+
if (!inputs.publicKeyMultibase) throw new Error("publicKeyMultibase is required (from entity.createOracle output)");
|
|
3220
|
+
if (!inputs.verificationMethodId) throw new Error("verificationMethodId is required (from entity.createOracle output)");
|
|
3221
|
+
if (!inputs.matrixHomeServerUrl) throw new Error("matrixHomeServerUrl is required (from matrix.register output)");
|
|
3222
|
+
if (!inputs.matrixUsername) throw new Error("matrixUsername is required (from matrix.register output matrixUserId)");
|
|
3223
|
+
if (!inputs.matrixPassword) throw new Error("matrixPassword is required (from matrix.register output)");
|
|
3224
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required (from wallet.generate output)");
|
|
3225
|
+
if (!inputs.matrixRecoveryPhrase) throw new Error("matrixRecoveryPhrase is required (from matrix.register output)");
|
|
3226
|
+
if (!inputs.pin) throw new Error("pin is required (from form output)");
|
|
3227
|
+
if (!inputs.openRouterApiKeyJwe) {
|
|
3228
|
+
throw new Error("OPEN_ROUTER_API_KEY is required \u2014 enter it in the form before submitting");
|
|
3229
|
+
}
|
|
3230
|
+
const secrets = {
|
|
3231
|
+
SECP_MNEMONIC: inputs.mnemonic,
|
|
3232
|
+
MATRIX_ORACLE_ADMIN_PASSWORD: inputs.matrixPassword,
|
|
3233
|
+
MATRIX_RECOVERY_PHRASE: inputs.matrixRecoveryPhrase,
|
|
3234
|
+
MATRIX_VALUE_PIN: inputs.pin
|
|
3235
|
+
};
|
|
3236
|
+
const preEncryptedSecrets = {
|
|
3237
|
+
OPEN_ROUTER_API_KEY: inputs.openRouterApiKeyJwe
|
|
3238
|
+
};
|
|
3239
|
+
if (inputs.mcpAuthSecrets) {
|
|
3240
|
+
try {
|
|
3241
|
+
const mcpSecrets = typeof inputs.mcpAuthSecrets === "string" ? JSON.parse(inputs.mcpAuthSecrets) : inputs.mcpAuthSecrets;
|
|
3242
|
+
if (mcpSecrets && typeof mcpSecrets === "object") {
|
|
3243
|
+
Object.assign(preEncryptedSecrets, mcpSecrets);
|
|
3244
|
+
}
|
|
3245
|
+
} catch {
|
|
3246
|
+
console.warn("[oracle.storeSecretsAndConfig] Failed to parse mcpAuthSecrets");
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
for (const k of SENSITIVE_PLAINTEXT_KEYS2) {
|
|
3250
|
+
if (!secrets[k]) throw new Error(`${k} is empty after assembly \u2014 refusing to call storeSecrets`);
|
|
3251
|
+
}
|
|
3252
|
+
console.log("[oracle.storeSecretsAndConfig] Phase 1: storing secrets");
|
|
3253
|
+
const secretsResult = await ctx.services.oracle.storeSecrets({
|
|
3254
|
+
matrixRoomId: inputs.matrixRoomId,
|
|
3255
|
+
publicKeyMultibase: inputs.publicKeyMultibase,
|
|
3256
|
+
verificationMethodId: inputs.verificationMethodId,
|
|
3257
|
+
matrixHomeServerUrl: inputs.matrixHomeServerUrl,
|
|
3258
|
+
matrixUsername: inputs.matrixUsername,
|
|
3259
|
+
matrixPassword: inputs.matrixPassword,
|
|
3260
|
+
secrets,
|
|
3261
|
+
preEncryptedSecrets
|
|
3262
|
+
});
|
|
3263
|
+
if (!secretsResult.storedSecrets || secretsResult.storedSecrets.length === 0) {
|
|
3264
|
+
throw new Error("storeSecrets returned success without any storedSecrets");
|
|
3265
|
+
}
|
|
3266
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
3267
|
+
if (!inputs.entityDid) throw new Error("entityDid is required");
|
|
3268
|
+
console.log("[oracle.storeSecretsAndConfig] Phase 2: storing config");
|
|
3269
|
+
const configResult = await ctx.services.oracle.storeConfig({
|
|
3270
|
+
matrixRoomId: inputs.matrixRoomId,
|
|
3271
|
+
config: {
|
|
3272
|
+
oracleName: inputs.oracleName,
|
|
3273
|
+
orgName: inputs.orgName || "",
|
|
3274
|
+
description: inputs.description || "",
|
|
3275
|
+
location: inputs.location || "",
|
|
3276
|
+
price: inputs.price ?? 0,
|
|
3277
|
+
apiUrl: inputs.apiUrl || "",
|
|
3278
|
+
entityDid: inputs.entityDid,
|
|
3279
|
+
logoUrl: inputs.logoUrl || "",
|
|
3280
|
+
llmModel: inputs.llmModel || "",
|
|
3281
|
+
opening: inputs.opening,
|
|
3282
|
+
communicationStyle: inputs.communicationStyle,
|
|
3283
|
+
capabilities: inputs.capabilities,
|
|
3284
|
+
skills: inputs.skills,
|
|
3285
|
+
mcpServers: inputs.mcpServers,
|
|
3286
|
+
matrixUserId: inputs.matrixUserId || "",
|
|
3287
|
+
matrixAccountRoomId: inputs.matrixAccountRoomId || "",
|
|
3288
|
+
oracleAddress: inputs.oracleAddress || "",
|
|
3289
|
+
oracleDid: inputs.oracleDid || ""
|
|
3290
|
+
}
|
|
3291
|
+
});
|
|
3292
|
+
if (!configResult.configStored) {
|
|
3293
|
+
throw new Error("storeConfig returned success without configStored=true");
|
|
3294
|
+
}
|
|
3295
|
+
console.log("[oracle.storeSecretsAndConfig] Both phases complete");
|
|
3296
|
+
return {
|
|
3297
|
+
output: {
|
|
3298
|
+
storedSecrets: secretsResult.storedSecrets,
|
|
3299
|
+
roomId: secretsResult.roomId,
|
|
3300
|
+
configStored: configResult.configStored
|
|
3301
|
+
}
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
});
|
|
3305
|
+
|
|
3306
|
+
// src/core/lib/actionRegistry/actions/oracleConfigureOracle.ts
|
|
3307
|
+
var SENSITIVE_PLAINTEXT_KEYS3 = [
|
|
3308
|
+
"SECP_MNEMONIC",
|
|
3309
|
+
"MATRIX_ORACLE_ADMIN_PASSWORD",
|
|
3310
|
+
"MATRIX_RECOVERY_PHRASE",
|
|
3311
|
+
"MATRIX_VALUE_PIN"
|
|
3312
|
+
];
|
|
3313
|
+
registerAction({
|
|
3314
|
+
type: "qi/oracle.configureOracle",
|
|
3315
|
+
can: "oracle/configureOracle",
|
|
3316
|
+
sideEffect: true,
|
|
3317
|
+
defaultRequiresConfirmation: false,
|
|
3318
|
+
outputSchema: [
|
|
3319
|
+
{ path: "userOracleRoomId", displayName: "User-Oracle Room ID", type: "string", description: "Matrix room id from contract phase" },
|
|
3320
|
+
{ path: "userOracleRoomAlias", displayName: "User-Oracle Room Alias", type: "string", description: "Matrix alias from contract phase" },
|
|
3321
|
+
{ path: "storedSecrets", displayName: "Stored Secrets", type: "array", description: "List of secret names stored" },
|
|
3322
|
+
{ path: "roomId", displayName: "Room ID", type: "string", description: "Matrix room where data is stored" },
|
|
3323
|
+
{ path: "configStored", displayName: "Config Stored", type: "boolean", description: "Whether oracle config was stored" },
|
|
3324
|
+
{ path: "freshAccessToken", displayName: "Fresh Access Token", type: "string", description: "Fresh Matrix access token from mxLogin during secret storage" },
|
|
3325
|
+
{ path: "openRouterApiKeyPlaintext", displayName: "OpenRouter API Key", type: "string", description: "Plaintext OpenRouter API key for deploy" }
|
|
3326
|
+
],
|
|
3327
|
+
run: async (rawInputs, ctx) => {
|
|
3328
|
+
const form = (() => {
|
|
3329
|
+
const raw = rawInputs.formAnswers;
|
|
3330
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
3331
|
+
try {
|
|
3332
|
+
const parsed = JSON.parse(raw);
|
|
3333
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
3334
|
+
} catch {
|
|
3335
|
+
return {};
|
|
3336
|
+
}
|
|
3337
|
+
})();
|
|
3338
|
+
const inputs = { ...form, ...rawInputs };
|
|
3339
|
+
if (!ctx.services.oracle?.contract) throw new Error("oracle.contract handler not available");
|
|
3340
|
+
if (!ctx.services.oracle?.storeSecrets) throw new Error("oracle.storeSecrets handler not available");
|
|
3341
|
+
if (!ctx.services.oracle?.storeConfig) throw new Error("oracle.storeConfig handler not available");
|
|
3342
|
+
if (!inputs.oracleEntityDid) throw new Error("oracleEntityDid is required (from entity.createOracle output)");
|
|
3343
|
+
if (!inputs.publicKeyMultibase) throw new Error("publicKeyMultibase is required (from entity.createOracle output)");
|
|
3344
|
+
if (!inputs.verificationMethodId) throw new Error("verificationMethodId is required (from entity.createOracle output)");
|
|
3345
|
+
if (!inputs.matrixHomeServerUrl) throw new Error("matrixHomeServerUrl is required (from matrix.register output)");
|
|
3346
|
+
if (!inputs.matrixUsername) throw new Error("matrixUsername is required (from matrix.register output matrixUserId)");
|
|
3347
|
+
if (!inputs.matrixPassword) throw new Error("matrixPassword is required (from matrix.register output)");
|
|
3348
|
+
if (!inputs.mnemonic) throw new Error("mnemonic is required (from wallet.generate output)");
|
|
3349
|
+
if (!inputs.matrixRecoveryPhrase) throw new Error("matrixRecoveryPhrase is required (from matrix.register output)");
|
|
3350
|
+
if (!inputs.pin) throw new Error("pin is required (from form output)");
|
|
3351
|
+
if (!inputs.openRouterApiKeyJwe) {
|
|
3352
|
+
throw new Error("OPEN_ROUTER_API_KEY is required \u2014 enter it in the form before submitting");
|
|
3353
|
+
}
|
|
3354
|
+
if (!inputs.oracleName) throw new Error("oracleName is required");
|
|
3355
|
+
if (!inputs.entityDid) throw new Error("entityDid is required");
|
|
3356
|
+
console.log("[oracle.configureOracle] Phase 1: contracting oracle");
|
|
3357
|
+
const contractResult = await ctx.services.oracle.contract({
|
|
3358
|
+
oracleEntityDid: inputs.oracleEntityDid
|
|
3359
|
+
});
|
|
3360
|
+
if (!contractResult.userOracleRoomId) {
|
|
3361
|
+
throw new Error("contract returned success without userOracleRoomId");
|
|
3362
|
+
}
|
|
3363
|
+
const matrixRoomId = contractResult.userOracleRoomId;
|
|
3364
|
+
const secrets = {
|
|
3365
|
+
SECP_MNEMONIC: inputs.mnemonic,
|
|
3366
|
+
MATRIX_ORACLE_ADMIN_PASSWORD: inputs.matrixPassword,
|
|
3367
|
+
MATRIX_RECOVERY_PHRASE: inputs.matrixRecoveryPhrase,
|
|
3368
|
+
MATRIX_VALUE_PIN: inputs.pin
|
|
3369
|
+
};
|
|
3370
|
+
const preEncryptedSecrets = {
|
|
3371
|
+
OPEN_ROUTER_API_KEY: inputs.openRouterApiKeyJwe
|
|
3372
|
+
};
|
|
3373
|
+
if (inputs.mcpAuthSecrets) {
|
|
3374
|
+
try {
|
|
3375
|
+
const mcpSecrets = typeof inputs.mcpAuthSecrets === "string" ? JSON.parse(inputs.mcpAuthSecrets) : inputs.mcpAuthSecrets;
|
|
3376
|
+
if (mcpSecrets && typeof mcpSecrets === "object") {
|
|
3377
|
+
Object.assign(preEncryptedSecrets, mcpSecrets);
|
|
3378
|
+
}
|
|
3379
|
+
} catch {
|
|
3380
|
+
console.warn("[oracle.configureOracle] Failed to parse mcpAuthSecrets");
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
for (const k of SENSITIVE_PLAINTEXT_KEYS3) {
|
|
3384
|
+
if (!secrets[k]) throw new Error(`${k} is empty after assembly \u2014 refusing to call storeSecrets`);
|
|
3385
|
+
}
|
|
3386
|
+
console.log("[oracle.configureOracle] Phase 2: storing secrets");
|
|
3387
|
+
const secretsResult = await ctx.services.oracle.storeSecrets({
|
|
3388
|
+
matrixRoomId,
|
|
3389
|
+
publicKeyMultibase: inputs.publicKeyMultibase,
|
|
3390
|
+
verificationMethodId: inputs.verificationMethodId,
|
|
3391
|
+
matrixHomeServerUrl: inputs.matrixHomeServerUrl,
|
|
3392
|
+
matrixUsername: inputs.matrixUsername,
|
|
3393
|
+
matrixPassword: inputs.matrixPassword,
|
|
3394
|
+
secrets,
|
|
3395
|
+
preEncryptedSecrets
|
|
3396
|
+
});
|
|
3397
|
+
if (!secretsResult.storedSecrets || secretsResult.storedSecrets.length === 0) {
|
|
3398
|
+
throw new Error("storeSecrets returned success without any storedSecrets");
|
|
3399
|
+
}
|
|
3400
|
+
console.log("[oracle.configureOracle] Phase 3: storing config");
|
|
3401
|
+
const configResult = await ctx.services.oracle.storeConfig({
|
|
3402
|
+
matrixRoomId,
|
|
3403
|
+
config: {
|
|
3404
|
+
oracleName: inputs.oracleName,
|
|
3405
|
+
orgName: inputs.orgName || "",
|
|
3406
|
+
description: inputs.description || "",
|
|
3407
|
+
location: inputs.location || "",
|
|
3408
|
+
price: inputs.price ?? 0,
|
|
3409
|
+
apiUrl: inputs.apiUrl || "",
|
|
3410
|
+
entityDid: inputs.entityDid,
|
|
3411
|
+
logoUrl: inputs.logoUrl || "",
|
|
3412
|
+
llmModel: inputs.llmModel || "",
|
|
3413
|
+
opening: inputs.opening,
|
|
3414
|
+
communicationStyle: inputs.communicationStyle,
|
|
3415
|
+
capabilities: inputs.capabilities,
|
|
3416
|
+
skills: inputs.skills,
|
|
3417
|
+
mcpServers: inputs.mcpServers,
|
|
3418
|
+
matrixUserId: inputs.matrixUserId || "",
|
|
3419
|
+
matrixAccountRoomId: inputs.matrixAccountRoomId || "",
|
|
3420
|
+
oracleAddress: inputs.oracleAddress || "",
|
|
3421
|
+
oracleDid: inputs.oracleDid || ""
|
|
3422
|
+
}
|
|
3423
|
+
});
|
|
3424
|
+
if (!configResult.configStored) {
|
|
3425
|
+
throw new Error("storeConfig returned success without configStored=true");
|
|
3426
|
+
}
|
|
3427
|
+
console.log("[oracle.configureOracle] All 3 phases complete");
|
|
3428
|
+
return {
|
|
3429
|
+
output: {
|
|
3430
|
+
userOracleRoomId: contractResult.userOracleRoomId,
|
|
3431
|
+
userOracleRoomAlias: contractResult.userOracleRoomAlias,
|
|
3432
|
+
storedSecrets: secretsResult.storedSecrets,
|
|
3433
|
+
roomId: secretsResult.roomId,
|
|
3434
|
+
configStored: configResult.configStored,
|
|
3435
|
+
freshAccessToken: secretsResult.freshAccessToken || "",
|
|
3436
|
+
openRouterApiKeyPlaintext: inputs.openRouterApiKeyPlaintext || ""
|
|
3437
|
+
}
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3440
|
+
});
|
|
3441
|
+
|
|
3442
|
+
// src/core/lib/actionRegistry/actions/oracleDeploySetup.ts
|
|
3443
|
+
registerAction({
|
|
3444
|
+
type: "qi/oracle.deploySetup",
|
|
3445
|
+
can: "oracle/deploySetup",
|
|
3446
|
+
sideEffect: true,
|
|
3447
|
+
defaultRequiresConfirmation: false,
|
|
3448
|
+
outputSchema: [
|
|
3449
|
+
{ path: "setupComplete", displayName: "Setup Complete", type: "boolean", description: "Whether the oracle setup completed successfully" },
|
|
3450
|
+
{ path: "stdout", displayName: "Build Output", type: "string", description: "Build stdout output" }
|
|
3451
|
+
],
|
|
3452
|
+
run: async (inputs, ctx) => {
|
|
3453
|
+
if (!ctx.services.oracle?.deploySetup) {
|
|
3454
|
+
throw new Error("oracle.deploySetup handler not available");
|
|
3455
|
+
}
|
|
3456
|
+
if (!inputs.name) throw new Error("name is required (project name from form)");
|
|
3457
|
+
const config = typeof inputs.config === "string" ? JSON.parse(inputs.config) : inputs.config;
|
|
3458
|
+
if (!config || typeof config !== "object") throw new Error("config is required (oracle config object)");
|
|
3459
|
+
if (!inputs.roomId) throw new Error("roomId is required (from oracle contract/configure output)");
|
|
3460
|
+
const result = await ctx.services.oracle.deploySetup({ name: inputs.name, config, roomId: inputs.roomId });
|
|
3461
|
+
return { output: result };
|
|
3462
|
+
}
|
|
3463
|
+
});
|
|
3464
|
+
|
|
3465
|
+
// src/core/lib/actionRegistry/actions/oracleDeployStart.ts
|
|
3466
|
+
registerAction({
|
|
3467
|
+
type: "qi/oracle.deployStart",
|
|
3468
|
+
can: "oracle/deployStart",
|
|
3469
|
+
sideEffect: true,
|
|
3470
|
+
defaultRequiresConfirmation: false,
|
|
3471
|
+
outputSchema: [
|
|
3472
|
+
{ path: "processId", displayName: "Process ID", type: "string", description: "Running process identifier" },
|
|
3473
|
+
{ path: "status", displayName: "Status", type: "string", description: "Oracle process status" }
|
|
3474
|
+
],
|
|
3475
|
+
run: async (inputs, ctx) => {
|
|
3476
|
+
if (!ctx.services.oracle?.deployStart) {
|
|
3477
|
+
throw new Error("oracle.deployStart handler not available");
|
|
3478
|
+
}
|
|
3479
|
+
if (!inputs.name) throw new Error("name is required (project name from form)");
|
|
3480
|
+
if (!inputs.entityDid) throw new Error("entityDid is required (from entity.createOracle output)");
|
|
3481
|
+
if (!inputs.roomId) throw new Error("roomId is required (from oracle contract/configure output)");
|
|
3482
|
+
const result = await ctx.services.oracle.deployStart({ name: inputs.name, entityDid: inputs.entityDid, roomId: inputs.roomId });
|
|
3483
|
+
return { output: result };
|
|
3484
|
+
}
|
|
3485
|
+
});
|
|
3486
|
+
|
|
3487
|
+
// src/core/lib/actionRegistry/actions/oracleDeploy.ts
|
|
3488
|
+
registerAction({
|
|
3489
|
+
type: "qi/oracle.deploy",
|
|
3490
|
+
can: "oracle/deploy",
|
|
3491
|
+
sideEffect: true,
|
|
3492
|
+
defaultRequiresConfirmation: false,
|
|
3493
|
+
outputSchema: [
|
|
3494
|
+
{ path: "setupComplete", displayName: "Setup Complete", type: "boolean", description: "Whether the oracle setup completed successfully" },
|
|
3495
|
+
{ path: "processId", displayName: "Process ID", type: "string", description: "Running process identifier" },
|
|
3496
|
+
{ path: "status", displayName: "Status", type: "string", description: "Oracle process status" },
|
|
3497
|
+
{ path: "deploymentUrl", displayName: "Deployment URL", type: "string", description: "The URL where the oracle was deployed" },
|
|
3498
|
+
{ path: "domainUpdateTxHash", displayName: "Domain Update Tx", type: "string", description: "Transaction hash of the on-chain domain update" }
|
|
3499
|
+
],
|
|
3500
|
+
run: async (rawInputs, ctx) => {
|
|
3501
|
+
const form = (() => {
|
|
3502
|
+
const raw = rawInputs.formAnswers;
|
|
3503
|
+
if (typeof raw !== "string" || !raw) return {};
|
|
3504
|
+
try {
|
|
3505
|
+
const parsed = JSON.parse(raw);
|
|
3506
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
3507
|
+
} catch {
|
|
3508
|
+
return {};
|
|
3509
|
+
}
|
|
3510
|
+
})();
|
|
3511
|
+
const inputs = {
|
|
3512
|
+
// Rename: form.projectName → name for deploy handler
|
|
3513
|
+
name: form.projectName,
|
|
3514
|
+
...form,
|
|
3515
|
+
...rawInputs
|
|
3516
|
+
};
|
|
3517
|
+
if (!ctx.services.oracle?.deploySetup) {
|
|
3518
|
+
throw new Error("oracle.deploySetup handler not available");
|
|
3519
|
+
}
|
|
3520
|
+
if (!ctx.services.oracle?.deployStart) {
|
|
3521
|
+
throw new Error("oracle.deployStart handler not available");
|
|
3522
|
+
}
|
|
3523
|
+
if (!inputs.name) throw new Error("name is required (project name from form)");
|
|
3524
|
+
if (!inputs.entityDid) throw new Error("entityDid is required (from entity.createOracle output)");
|
|
3525
|
+
if (!inputs.roomId) throw new Error("roomId is required (from oracle.configureOracle output)");
|
|
3526
|
+
const config = {
|
|
3527
|
+
oracleName: inputs.oracleName,
|
|
3528
|
+
orgName: inputs.orgName,
|
|
3529
|
+
description: inputs.description,
|
|
3530
|
+
location: inputs.location,
|
|
3531
|
+
price: inputs.price,
|
|
3532
|
+
apiUrl: inputs.apiUrl,
|
|
3533
|
+
logoUrl: inputs.logoUrl,
|
|
3534
|
+
llmModel: inputs.llmModel,
|
|
3535
|
+
opening: inputs.opening,
|
|
3536
|
+
communicationStyle: inputs.communicationStyle,
|
|
3537
|
+
capabilities: inputs.capabilities,
|
|
3538
|
+
skills: inputs.skills,
|
|
3539
|
+
mcpServers: inputs.mcpServers,
|
|
3540
|
+
entityDid: inputs.entityDid
|
|
3541
|
+
};
|
|
3542
|
+
const secrets = {
|
|
3543
|
+
mnemonic: inputs.mnemonic,
|
|
3544
|
+
matrixPassword: inputs.matrixPassword,
|
|
3545
|
+
matrixRecoveryPhrase: inputs.matrixRecoveryPhrase,
|
|
3546
|
+
pin: inputs.pin,
|
|
3547
|
+
matrixUsername: inputs.matrixUsername,
|
|
3548
|
+
matrixAccountRoomId: inputs.matrixAccountRoomId,
|
|
3549
|
+
freshAccessToken: inputs.freshAccessToken,
|
|
3550
|
+
openRouterApiKey: inputs.openRouterApiKey
|
|
3551
|
+
};
|
|
3552
|
+
const setupResult = await ctx.services.oracle.deploySetup({ name: inputs.name, config, roomId: inputs.roomId, secrets });
|
|
3553
|
+
if (!setupResult.setupComplete) {
|
|
3554
|
+
throw new Error(`Deploy setup failed: ${setupResult.stderr || "setupComplete was not true"}`);
|
|
3555
|
+
}
|
|
3556
|
+
const startResult = await ctx.services.oracle.deployStart({ name: inputs.name, entityDid: inputs.entityDid, roomId: inputs.roomId, secrets });
|
|
3557
|
+
if (!startResult.processId && startResult.status !== "running") {
|
|
3558
|
+
throw new Error("Deploy start failed: no processId returned and status is not running");
|
|
3559
|
+
}
|
|
3560
|
+
let deploymentUrl;
|
|
3561
|
+
let domainUpdateTxHash;
|
|
3562
|
+
if (startResult.url) {
|
|
3563
|
+
if (!ctx.services.oracle?.updateOracleDomain) {
|
|
3564
|
+
console.warn("[oracle.deploy] updateOracleDomain handler not available, skipping domain update");
|
|
3565
|
+
} else {
|
|
3566
|
+
const domainResult = await ctx.services.oracle.updateOracleDomain({
|
|
3567
|
+
entityDid: inputs.entityDid,
|
|
3568
|
+
newApiUrl: startResult.url
|
|
3569
|
+
});
|
|
3570
|
+
deploymentUrl = startResult.url;
|
|
3571
|
+
domainUpdateTxHash = domainResult.transactionHash;
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
return {
|
|
3575
|
+
output: {
|
|
3576
|
+
setupComplete: setupResult.setupComplete,
|
|
3577
|
+
processId: startResult.processId,
|
|
3578
|
+
status: startResult.status,
|
|
3579
|
+
deploymentUrl,
|
|
3580
|
+
domainUpdateTxHash
|
|
3581
|
+
}
|
|
3582
|
+
};
|
|
3583
|
+
}
|
|
3584
|
+
});
|
|
3585
|
+
|
|
2611
3586
|
// src/core/lib/actionRegistry/actions/bid/bid.diff.ts
|
|
2612
3587
|
registerDiffResolver("bid", {
|
|
2613
3588
|
resolver: async (inputs, _ctx) => {
|
|
@@ -2890,6 +3865,40 @@ registerDiffResolver("evaluateClaim", {
|
|
|
2890
3865
|
}
|
|
2891
3866
|
});
|
|
2892
3867
|
|
|
3868
|
+
// src/core/lib/actionRegistry/actions/walletFund.diff.ts
|
|
3869
|
+
registerDiffResolver("qi/wallet.fund", {
|
|
3870
|
+
resolver: async (inputs, _ctx) => {
|
|
3871
|
+
const address = String(inputs.address || "").trim();
|
|
3872
|
+
const amount = String(inputs.amount || "250000").trim();
|
|
3873
|
+
const network = String(inputs.network || "devnet").trim();
|
|
3874
|
+
const ixoAmount = (Number(amount) / 1e6).toFixed(6);
|
|
3875
|
+
return [
|
|
3876
|
+
{
|
|
3877
|
+
key: "recipient",
|
|
3878
|
+
label: "Recipient",
|
|
3879
|
+
before: "N/A",
|
|
3880
|
+
after: address || "Pending wallet generation",
|
|
3881
|
+
changeType: address ? "replace" : "unchanged"
|
|
3882
|
+
},
|
|
3883
|
+
{
|
|
3884
|
+
key: "amount",
|
|
3885
|
+
label: "Amount",
|
|
3886
|
+
before: "0 IXO",
|
|
3887
|
+
after: `${ixoAmount} IXO (${amount} uixo)`,
|
|
3888
|
+
changeType: "replace",
|
|
3889
|
+
severity: "info"
|
|
3890
|
+
},
|
|
3891
|
+
{
|
|
3892
|
+
key: "network",
|
|
3893
|
+
label: "Network",
|
|
3894
|
+
before: network,
|
|
3895
|
+
after: network,
|
|
3896
|
+
changeType: "unchanged"
|
|
3897
|
+
}
|
|
3898
|
+
];
|
|
3899
|
+
}
|
|
3900
|
+
});
|
|
3901
|
+
|
|
2893
3902
|
// src/core/services/ucanService.ts
|
|
2894
3903
|
import {
|
|
2895
3904
|
createDelegation as ucanCreateDelegation,
|
|
@@ -3920,6 +4929,65 @@ function removePendingInvocation(yDoc, listenerBlockId, pendingInvocationId) {
|
|
|
3920
4929
|
inner.delete(pendingInvocationId);
|
|
3921
4930
|
return true;
|
|
3922
4931
|
}
|
|
4932
|
+
var BARRIER_STATE_MAP_KEY = "barrierState";
|
|
4933
|
+
function getBarrierStateMap(yDoc) {
|
|
4934
|
+
return yDoc.getMap(BARRIER_STATE_MAP_KEY);
|
|
4935
|
+
}
|
|
4936
|
+
function getOrCreateListenerBarrierMap(yDoc, listenerBlockId) {
|
|
4937
|
+
const outer = getBarrierStateMap(yDoc);
|
|
4938
|
+
let inner = outer.get(listenerBlockId);
|
|
4939
|
+
if (!inner) {
|
|
4940
|
+
inner = new Y.Map();
|
|
4941
|
+
outer.set(listenerBlockId, inner);
|
|
4942
|
+
}
|
|
4943
|
+
return inner;
|
|
4944
|
+
}
|
|
4945
|
+
function recordBarrierEvent(yDoc, listenerBlockId, entry) {
|
|
4946
|
+
let written = false;
|
|
4947
|
+
yDoc.transact(() => {
|
|
4948
|
+
const inner = getOrCreateListenerBarrierMap(yDoc, listenerBlockId);
|
|
4949
|
+
const key = `${entry.sourceBlockId}::${entry.eventName}`;
|
|
4950
|
+
const existing = inner.get(key);
|
|
4951
|
+
if (existing && typeof existing === "object" && existing.runId === entry.runId) return;
|
|
4952
|
+
inner.set(key, entry);
|
|
4953
|
+
written = true;
|
|
4954
|
+
});
|
|
4955
|
+
return written;
|
|
4956
|
+
}
|
|
4957
|
+
function readBarrierState(yDoc, listenerBlockId) {
|
|
4958
|
+
const outer = getBarrierStateMap(yDoc);
|
|
4959
|
+
const inner = outer.get(listenerBlockId);
|
|
4960
|
+
if (!inner) return [];
|
|
4961
|
+
const entries = [];
|
|
4962
|
+
inner.forEach((value) => {
|
|
4963
|
+
if (value && typeof value === "object") {
|
|
4964
|
+
entries.push(value);
|
|
4965
|
+
}
|
|
4966
|
+
});
|
|
4967
|
+
return entries;
|
|
4968
|
+
}
|
|
4969
|
+
function clearBarrierState(yDoc, listenerBlockId) {
|
|
4970
|
+
const outer = getBarrierStateMap(yDoc);
|
|
4971
|
+
yDoc.transact(() => {
|
|
4972
|
+
outer.delete(listenerBlockId);
|
|
4973
|
+
});
|
|
4974
|
+
}
|
|
4975
|
+
function computeBarrierInvocationId(entries, listenerBlockId) {
|
|
4976
|
+
const sorted = [...entries].sort((a, b) => a.sourceBlockId.localeCompare(b.sourceBlockId));
|
|
4977
|
+
const input = sorted.map((e) => `${e.sourceBlockId}:${e.runId}:${e.eventName}`).join("|") + `|>${listenerBlockId}`;
|
|
4978
|
+
return `bi-${fnv1a32(input)}`;
|
|
4979
|
+
}
|
|
4980
|
+
function mergeBarrierPayloads(entries) {
|
|
4981
|
+
const merged = {};
|
|
4982
|
+
for (const entry of entries) {
|
|
4983
|
+
if (entry.alias) {
|
|
4984
|
+
merged[entry.alias] = entry.payload;
|
|
4985
|
+
} else {
|
|
4986
|
+
Object.assign(merged, entry.payload);
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
return merged;
|
|
4990
|
+
}
|
|
3923
4991
|
function appendRunRecord(yDoc, blockId, details, userId) {
|
|
3924
4992
|
const auditMap = yDoc.getMap("auditTrail");
|
|
3925
4993
|
yDoc.transact(() => {
|
|
@@ -3992,21 +5060,41 @@ function replayFailedListenerRun(yDoc, failedRecord, listenerBlockId, originalPa
|
|
|
3992
5060
|
}
|
|
3993
5061
|
|
|
3994
5062
|
// src/core/lib/flowEngine/reconcile.ts
|
|
5063
|
+
var _reconcileRunning = false;
|
|
3995
5064
|
function reconcilePendingInvocations(editor) {
|
|
5065
|
+
if (_reconcileRunning) return;
|
|
5066
|
+
_reconcileRunning = true;
|
|
5067
|
+
try {
|
|
5068
|
+
_reconcilePendingInvocationsInner(editor);
|
|
5069
|
+
} finally {
|
|
5070
|
+
_reconcileRunning = false;
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
function _reconcilePendingInvocationsInner(editor) {
|
|
3996
5074
|
const yDoc = editor._yDoc;
|
|
3997
5075
|
if (!yDoc) return;
|
|
3998
5076
|
const blocks = editor.document || [];
|
|
3999
5077
|
if (blocks.length === 0) return;
|
|
4000
5078
|
const listenersBySource = /* @__PURE__ */ new Map();
|
|
5079
|
+
const barrierListenersBySource = /* @__PURE__ */ new Map();
|
|
4001
5080
|
for (const block of blocks) {
|
|
4002
5081
|
const trigger = parseTrigger(block);
|
|
4003
|
-
if (!trigger
|
|
4004
|
-
if (
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
5082
|
+
if (!trigger) continue;
|
|
5083
|
+
if (trigger.type === "block.event") {
|
|
5084
|
+
if (!trigger.sourceBlockId || !trigger.eventName) continue;
|
|
5085
|
+
const key = `${trigger.sourceBlockId}::${trigger.eventName}`;
|
|
5086
|
+
if (!listenersBySource.has(key)) listenersBySource.set(key, []);
|
|
5087
|
+
listenersBySource.get(key).push({ block, trigger });
|
|
5088
|
+
} else if (trigger.type === "block.event.all" && trigger.sources) {
|
|
5089
|
+
for (const source of trigger.sources) {
|
|
5090
|
+
if (!source.sourceBlockId || !source.eventName) continue;
|
|
5091
|
+
const key = `${source.sourceBlockId}::${source.eventName}`;
|
|
5092
|
+
if (!barrierListenersBySource.has(key)) barrierListenersBySource.set(key, []);
|
|
5093
|
+
barrierListenersBySource.get(key).push({ block, trigger, source });
|
|
5094
|
+
}
|
|
5095
|
+
}
|
|
4008
5096
|
}
|
|
4009
|
-
if (listenersBySource.size === 0) return;
|
|
5097
|
+
if (listenersBySource.size === 0 && barrierListenersBySource.size === 0) return;
|
|
4010
5098
|
const runtimeMap = editor._yRuntime;
|
|
4011
5099
|
const getNodeOutput = (nodeId) => {
|
|
4012
5100
|
if (!runtimeMap) return void 0;
|
|
@@ -4025,14 +5113,21 @@ function reconcilePendingInvocations(editor) {
|
|
|
4025
5113
|
break;
|
|
4026
5114
|
}
|
|
4027
5115
|
}
|
|
5116
|
+
for (const key of barrierListenersBySource.keys()) {
|
|
5117
|
+
if (key.startsWith(`${sourceBlockId}::`)) {
|
|
5118
|
+
hasAnyListener = true;
|
|
5119
|
+
break;
|
|
5120
|
+
}
|
|
5121
|
+
}
|
|
4028
5122
|
if (!hasAnyListener) continue;
|
|
4029
5123
|
const records = readRunRecords(yDoc, sourceBlockId);
|
|
4030
5124
|
for (const record of records) {
|
|
4031
|
-
processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNodeOutput);
|
|
5125
|
+
processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNodeOutput, runtimeMap);
|
|
5126
|
+
processBarrierRunRecord(yDoc, sourceBlockId, record, barrierListenersBySource, getNodeOutput, runtimeMap);
|
|
4032
5127
|
}
|
|
4033
5128
|
}
|
|
4034
5129
|
}
|
|
4035
|
-
function processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNodeOutput) {
|
|
5130
|
+
function processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNodeOutput, runtimeMap) {
|
|
4036
5131
|
if (!Array.isArray(record.events)) return;
|
|
4037
5132
|
record.events.forEach((event, eventIndex) => {
|
|
4038
5133
|
if (!event?.name) return;
|
|
@@ -4049,8 +5144,7 @@ function processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNod
|
|
|
4049
5144
|
eventName: event.name,
|
|
4050
5145
|
eventIndex
|
|
4051
5146
|
});
|
|
4052
|
-
const assigneeDid = resolveAssignee(listenerBlock);
|
|
4053
|
-
if (!assigneeDid) continue;
|
|
5147
|
+
const assigneeDid = resolveAssignee(listenerBlock) || "unassigned";
|
|
4054
5148
|
const inputs = parseInputs(listenerBlock);
|
|
4055
5149
|
const refSnapshots = snapshotInputRefs(inputs, getNodeOutput);
|
|
4056
5150
|
const expiresAt = computeExpiry(listenerBlock, record.completedAt);
|
|
@@ -4067,9 +5161,77 @@ function processRunRecord(yDoc, sourceBlockId, record, listenersBySource, getNod
|
|
|
4067
5161
|
expiresAt
|
|
4068
5162
|
};
|
|
4069
5163
|
queuePendingInvocation(yDoc, listenerBlockId, invocation);
|
|
5164
|
+
if (runtimeMap) {
|
|
5165
|
+
const prev = runtimeMap.get(listenerBlockId) || {};
|
|
5166
|
+
runtimeMap.set(listenerBlockId, {
|
|
5167
|
+
...prev,
|
|
5168
|
+
pendingPayload: { ...event.payload, ...refSnapshots }
|
|
5169
|
+
});
|
|
5170
|
+
}
|
|
4070
5171
|
}
|
|
4071
5172
|
});
|
|
4072
5173
|
}
|
|
5174
|
+
function processBarrierRunRecord(yDoc, sourceBlockId, record, barrierListenersBySource, getNodeOutput, runtimeMap) {
|
|
5175
|
+
if (!Array.isArray(record.events)) return;
|
|
5176
|
+
for (const event of record.events) {
|
|
5177
|
+
if (!event?.name) continue;
|
|
5178
|
+
const key = `${sourceBlockId}::${event.name}`;
|
|
5179
|
+
const listeners = barrierListenersBySource.get(key);
|
|
5180
|
+
if (!listeners || listeners.length === 0) continue;
|
|
5181
|
+
for (const { block: listenerBlock, trigger, source } of listeners) {
|
|
5182
|
+
const listenerBlockId = listenerBlock.id;
|
|
5183
|
+
if (!listenerBlockId) continue;
|
|
5184
|
+
const entry = {
|
|
5185
|
+
sourceBlockId,
|
|
5186
|
+
eventName: event.name,
|
|
5187
|
+
alias: source.alias,
|
|
5188
|
+
runId: record.runId,
|
|
5189
|
+
payload: event.payload || {},
|
|
5190
|
+
emittedAt: record.completedAt
|
|
5191
|
+
};
|
|
5192
|
+
recordBarrierEvent(yDoc, listenerBlockId, entry);
|
|
5193
|
+
if (runtimeMap) {
|
|
5194
|
+
const prev = runtimeMap.get(listenerBlockId) || {};
|
|
5195
|
+
const existing = prev.pendingPayload || {};
|
|
5196
|
+
runtimeMap.set(listenerBlockId, {
|
|
5197
|
+
...prev,
|
|
5198
|
+
pendingPayload: { ...existing, ...event.payload || {} }
|
|
5199
|
+
});
|
|
5200
|
+
}
|
|
5201
|
+
const allSources = trigger.sources || [];
|
|
5202
|
+
const currentState = readBarrierState(yDoc, listenerBlockId);
|
|
5203
|
+
const allFired = allSources.length > 0 && allSources.every((s) => currentState.some((e) => e.sourceBlockId === s.sourceBlockId && e.eventName === s.eventName));
|
|
5204
|
+
if (!allFired) continue;
|
|
5205
|
+
const assigneeDid = resolveAssignee(listenerBlock) || "unassigned";
|
|
5206
|
+
const id = computeBarrierInvocationId(currentState, listenerBlockId);
|
|
5207
|
+
const mergedPayload = mergeBarrierPayloads(currentState);
|
|
5208
|
+
const inputs = parseInputs(listenerBlock);
|
|
5209
|
+
const refSnapshots = snapshotInputRefs(inputs, getNodeOutput);
|
|
5210
|
+
const expiresAt = computeExpiry(listenerBlock, record.completedAt);
|
|
5211
|
+
const invocation = {
|
|
5212
|
+
id,
|
|
5213
|
+
triggeringBlockId: sourceBlockId,
|
|
5214
|
+
sourceRunId: record.runId,
|
|
5215
|
+
eventName: `barrier:${allSources.map((s) => s.alias).join("+")}`,
|
|
5216
|
+
eventIndex: 0,
|
|
5217
|
+
payload: mergedPayload,
|
|
5218
|
+
refSnapshots,
|
|
5219
|
+
assigneeDid,
|
|
5220
|
+
emittedAt: record.completedAt,
|
|
5221
|
+
expiresAt
|
|
5222
|
+
};
|
|
5223
|
+
queuePendingInvocation(yDoc, listenerBlockId, invocation);
|
|
5224
|
+
clearBarrierState(yDoc, listenerBlockId);
|
|
5225
|
+
if (runtimeMap) {
|
|
5226
|
+
const prev = runtimeMap.get(listenerBlockId) || {};
|
|
5227
|
+
runtimeMap.set(listenerBlockId, {
|
|
5228
|
+
...prev,
|
|
5229
|
+
pendingPayload: { ...mergedPayload, ...refSnapshots }
|
|
5230
|
+
});
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
}
|
|
5234
|
+
}
|
|
4073
5235
|
function parseTrigger(block) {
|
|
4074
5236
|
const raw = block?.props?.trigger;
|
|
4075
5237
|
if (!raw || typeof raw !== "string") return null;
|
|
@@ -4134,6 +5296,25 @@ function getActionForBlock(block) {
|
|
|
4134
5296
|
return getAction(actionType);
|
|
4135
5297
|
}
|
|
4136
5298
|
|
|
5299
|
+
// src/core/lib/flowEngine/emitEvents.ts
|
|
5300
|
+
function writeRunRecordAndReconcile(editor, blockId, output, events, actorDid) {
|
|
5301
|
+
const yDoc = editor._yDoc;
|
|
5302
|
+
if (!yDoc) return;
|
|
5303
|
+
if (events.length === 0) return;
|
|
5304
|
+
const runId = `run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
5305
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5306
|
+
const details = {
|
|
5307
|
+
runId,
|
|
5308
|
+
output,
|
|
5309
|
+
events,
|
|
5310
|
+
startedAt: now,
|
|
5311
|
+
completedAt: now,
|
|
5312
|
+
actorDid
|
|
5313
|
+
};
|
|
5314
|
+
appendRunRecord(yDoc, blockId, details, actorDid);
|
|
5315
|
+
reconcilePendingInvocations(editor);
|
|
5316
|
+
}
|
|
5317
|
+
|
|
4137
5318
|
// src/core/lib/flowEngine/migration.ts
|
|
4138
5319
|
var MIGRATION_REGISTRY = {};
|
|
4139
5320
|
function registerMigration(definition) {
|
|
@@ -4292,7 +5473,6 @@ var ICON_DEFAULTS = {
|
|
|
4292
5473
|
"matrix/dm": "message-circle",
|
|
4293
5474
|
"proposal/create": "scroll",
|
|
4294
5475
|
"proposal/vote": "vote",
|
|
4295
|
-
"domain/card-build": "file-text",
|
|
4296
5476
|
"domain/card-preview": "id",
|
|
4297
5477
|
"domain/sign": "feather",
|
|
4298
5478
|
"credential/store": "shield",
|
|
@@ -4360,42 +5540,81 @@ function compileBaseUcanFlow(plan, registry) {
|
|
|
4360
5540
|
const triggerEdges = [];
|
|
4361
5541
|
for (const [nodeId, { cap, action }] of actionMap) {
|
|
4362
5542
|
const trigger = cap.trigger;
|
|
4363
|
-
if (!trigger
|
|
4364
|
-
if (
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
5543
|
+
if (!trigger) continue;
|
|
5544
|
+
if (trigger.type === "block.event") {
|
|
5545
|
+
if (action.eligibleForEventTrigger !== true) {
|
|
5546
|
+
throw new Error(
|
|
5547
|
+
`Block "${nodeId}" is configured with a block.event trigger, but its action type "${action.type}" is not marked eligibleForEventTrigger. Set eligibleForEventTrigger: true on the action definition or change the trigger to manual.`
|
|
5548
|
+
);
|
|
5549
|
+
}
|
|
5550
|
+
const sourceId = trigger.sourceBlockId?.trim();
|
|
5551
|
+
const eventName = trigger.eventName?.trim();
|
|
5552
|
+
if (!sourceId || !eventName) {
|
|
5553
|
+
throw new Error(`Block "${nodeId}" has a block.event trigger but is missing sourceBlockId or eventName.`);
|
|
5554
|
+
}
|
|
5555
|
+
const source = actionMap.get(sourceId);
|
|
5556
|
+
if (!source) {
|
|
5557
|
+
throw new Error(`Trigger on block "${nodeId}" references unknown source block "${sourceId}".`);
|
|
5558
|
+
}
|
|
5559
|
+
const declaredEvents = source.action.events || [];
|
|
5560
|
+
if (declaredEvents.length === 0) {
|
|
5561
|
+
throw new Error(`Trigger on block "${nodeId}" references event "${eventName}" but source action "${source.action.type}" declares no events.`);
|
|
5562
|
+
}
|
|
5563
|
+
const found = declaredEvents.find((e) => e.name === eventName);
|
|
5564
|
+
if (!found) {
|
|
5565
|
+
const declared = declaredEvents.map((e) => e.name).join(", ");
|
|
5566
|
+
throw new Error(`Trigger on block "${nodeId}" references unknown event "${eventName}" on action type "${source.action.type}". Declared events: [${declared}]`);
|
|
5567
|
+
}
|
|
5568
|
+
triggerEdges.push({
|
|
5569
|
+
id: `${sourceId}~event:${eventName}~>${nodeId}`,
|
|
5570
|
+
source: sourceId,
|
|
5571
|
+
target: nodeId,
|
|
5572
|
+
kind: "trigger"
|
|
5573
|
+
});
|
|
4368
5574
|
}
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
5575
|
+
if (trigger.type === "block.event.all") {
|
|
5576
|
+
if (action.eligibleForEventTrigger !== true) {
|
|
5577
|
+
throw new Error(`Block "${nodeId}" is configured with a block.event.all trigger, but its action type "${action.type}" is not marked eligibleForEventTrigger.`);
|
|
5578
|
+
}
|
|
5579
|
+
const sources = trigger.sources || [];
|
|
5580
|
+
if (sources.length === 0) {
|
|
5581
|
+
throw new Error(`Block "${nodeId}" has a block.event.all trigger but no sources configured.`);
|
|
5582
|
+
}
|
|
5583
|
+
for (const src of sources) {
|
|
5584
|
+
const srcId = src.sourceBlockId?.trim();
|
|
5585
|
+
const evtName = src.eventName?.trim();
|
|
5586
|
+
if (!srcId || !evtName) {
|
|
5587
|
+
throw new Error(`Block "${nodeId}" has a block.event.all source with missing sourceBlockId or eventName.`);
|
|
5588
|
+
}
|
|
5589
|
+
const sourceEntry = actionMap.get(srcId);
|
|
5590
|
+
if (!sourceEntry) {
|
|
5591
|
+
throw new Error(`Barrier trigger on block "${nodeId}" references unknown source block "${srcId}".`);
|
|
5592
|
+
}
|
|
5593
|
+
const declaredEvents = sourceEntry.action.events || [];
|
|
5594
|
+
const found = declaredEvents.find((e) => e.name === evtName);
|
|
5595
|
+
if (!found) {
|
|
5596
|
+
const declared = declaredEvents.map((e) => e.name).join(", ");
|
|
5597
|
+
throw new Error(`Barrier trigger on block "${nodeId}" references unknown event "${evtName}" on action type "${sourceEntry.action.type}". Declared events: [${declared}]`);
|
|
5598
|
+
}
|
|
5599
|
+
if (!src.alias?.trim()) {
|
|
5600
|
+
throw new Error(`Barrier trigger on block "${nodeId}" has a source (${srcId}/${evtName}) with no alias.`);
|
|
5601
|
+
}
|
|
5602
|
+
triggerEdges.push({
|
|
5603
|
+
id: `${srcId}~event:${evtName}~>${nodeId}`,
|
|
5604
|
+
source: srcId,
|
|
5605
|
+
target: nodeId,
|
|
5606
|
+
kind: "trigger"
|
|
5607
|
+
});
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
if (trigger.type === "block.event" || trigger.type === "block.event.all") {
|
|
5611
|
+
const refs = collectOutputRefs(cap.nb || {});
|
|
5612
|
+
for (const ref of refs) {
|
|
5613
|
+
const parsed = parseOutputRef2(ref);
|
|
5614
|
+
if (!parsed) continue;
|
|
5615
|
+
if (!actionMap.has(parsed.nodeId)) {
|
|
5616
|
+
throw new Error(`Listener "${nodeId}" references output of unknown block "${parsed.nodeId}" via ref "${ref}".`);
|
|
5617
|
+
}
|
|
4399
5618
|
}
|
|
4400
5619
|
}
|
|
4401
5620
|
}
|
|
@@ -5139,6 +6358,7 @@ export {
|
|
|
5139
6358
|
parseLinkedEntities,
|
|
5140
6359
|
buildGovernanceGroupLinkedEntities,
|
|
5141
6360
|
tempDomainCreatorSurvey,
|
|
6361
|
+
resolveEntityTypeFromSchema,
|
|
5142
6362
|
getHomeserver,
|
|
5143
6363
|
didToMatrixUserId,
|
|
5144
6364
|
findOrCreateDMRoom,
|
|
@@ -5170,6 +6390,7 @@ export {
|
|
|
5170
6390
|
replayFailedListenerRun,
|
|
5171
6391
|
reconcilePendingInvocations,
|
|
5172
6392
|
getActionForBlock,
|
|
6393
|
+
writeRunRecordAndReconcile,
|
|
5173
6394
|
compileBaseUcanFlow,
|
|
5174
6395
|
readCompiledFlowFromYDoc,
|
|
5175
6396
|
mergeCompiledFlows,
|
|
@@ -5181,4 +6402,4 @@ export {
|
|
|
5181
6402
|
readFlow,
|
|
5182
6403
|
setupFlowFromBaseUcan
|
|
5183
6404
|
};
|
|
5184
|
-
//# sourceMappingURL=chunk-
|
|
6405
|
+
//# sourceMappingURL=chunk-75MWYZJ2.mjs.map
|