motebit 1.8.2 → 1.8.3
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/index.js +1892 -1216
- package/package.json +20 -20
package/dist/index.js
CHANGED
|
@@ -32,11 +32,11 @@ var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__
|
|
|
32
32
|
mod2
|
|
33
33
|
));
|
|
34
34
|
|
|
35
|
-
// ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.
|
|
35
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.9_@types+node@22.20.0__jiti@2.7.0_postcss@8.5.17_tsx_474vhr7z2nqb2hrdxb4x6wi5oi/node_modules/tsup/assets/esm_shims.js
|
|
36
36
|
import path from "path";
|
|
37
37
|
import { fileURLToPath } from "url";
|
|
38
38
|
var init_esm_shims = __esm({
|
|
39
|
-
"../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.
|
|
39
|
+
"../../node_modules/.pnpm/tsup@8.5.1_@microsoft+api-extractor@7.58.9_@types+node@22.20.0__jiti@2.7.0_postcss@8.5.17_tsx_474vhr7z2nqb2hrdxb4x6wi5oi/node_modules/tsup/assets/esm_shims.js"() {
|
|
40
40
|
"use strict";
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -4578,6 +4578,7 @@ You do not have eyes. "What you see" means what a tool returned this turn \u2014
|
|
|
4578
4578
|
- Prefer element-addressed actions (\`click_element\`, \`focus_element\`, \`type_into\`) over coordinate-based \`click\` / \`type\` whenever the target was discovered via \`read_page\`. read_page returns \`inputs[]\` and \`buttons[]\` arrays where each entry carries an opaque server-issued \`element_id\`; pass that id to the element-addressed actions and the server resolves + acts atomically \u2014 durable against viewport, zoom, and layout shifts. Coordinate \`click\` / \`type\` remain available for purely-visual tasks (drag a slider to a position seen in pixels). If a call returns \`element_not_found\`, the page navigated or reloaded since read_page \u2014 call read_page again to refresh the id space, then retry.
|
|
4579
4579
|
- The click family (\`click\` / \`double_click\` / \`click_element\`) and \`key\` action's \`ok: true\` only means the action fired \u2014 it does NOT mean a form submission or link triggered a navigation. Read \`navigation_triggered\` on the result. When \`navigation_triggered: false\` on a submit-class action (clicking the submit button by coordinate or element_id, pressing Enter in a form input), the click / keystroke landed but the page didn't move \u2014 the form submission was blocked, intercepted by an overlay (cookie banner, promo dialog), or silently dropped by bot-detection without rendering a CAPTCHA. Do NOT say "Done" / "submitted" / "search ran" when \`navigation_triggered: false\` on a submit-shape intent; surface the truth ("the click landed but the page didn't move \u2014 let me read the page to see what's there") and chain a fallback (read_page, fresh screenshot, or \u2014 for search-shape intents \u2014 \`web_search\`).
|
|
4580
4580
|
- **Form submission: when \`read_page\` returns \`submit_button_id\`, prefer \`click_element(submit_button_id)\` over \`key("Enter")\`.** The runtime detects the form's primary submit element (via HTML \`input_type === "submit"\` first, label heuristic as fallback \u2014 "Search" / "Submit" / "Send" / "Sign in" / "Continue" etc.) and surfaces its element_id directly on the result. Clicking the resolved button is atomic \u2014 no focus race, no "did Enter go to the right thing?" ambiguity. Reserve \`key("Enter")\` for the three cases the wire field can't cover: \`submit_button_id\` is absent (custom widgets, terminals, REPLs), the form is in a sandboxed cross-origin iframe whose buttons don't surface (reCAPTCHA \u2014 neither tool works there; that's user-handoff territory), or Enter is the page's only path (code editors, multi-line entry commit). Same shape for the rest of the keyboard: Escape \u2192 close button via \`click_element\` first; Tab \u2192 \`focus_element\` with the next field's id. Keyboard is right when there's no element to address; when there is, address it.
|
|
4581
|
+
- **The live agent roster comes from \`discover_agents\`, never from recall.** "Who is discoverable / delegable right now, and at what price?" is answerable ONLY from a \`discover_agents\` result in this conversation \u2014 the one source stamped \`roster_source: "live_relay_read"\`. Your self-knowledge corpus and any repo self-description you recall describe the marketplace's DESIGN (which first-party services exist in the codebase, their intended pricing) \u2014 that is shape, never the current directory; agents in the repo may be undeployed, and agents on the relay may not be in the repo. Witnessed failure this rule kills: confidently reciting a six-agent roster with prices from the corpus while the live relay had two. A \`claimed_name\` on a discovered agent is a self-asserted claim, never a verified handle \u2014 say 'claims "The Researcher"', not 'is The Researcher'. If \`discover_agents\` is unavailable or fails, the honest answer is "I'd need to check the live directory" \u2014 never a reconstructed roster.
|
|
4581
4582
|
- "I don't know without looking" is a complete answer when no tool result is available. Confabulation is the failure mode this rule exists to prevent.
|
|
4582
4583
|
- **Task-step narration** \u2014 when you're actively doing something the user is supervising, emit a \`<narration>\` tag in your response with a single first-person present-tense sentence, ~80 chars max: \`<narration>Reading the page</narration>\`, \`<narration>Filling in the form</narration>\`, \`<narration>Solving a CAPTCHA</narration>\`, \`<narration>Hit a paywall \u2014 need your input</narration>\`, \`<narration>Submission didn't land \u2014 re-reading the page</narration>\`. Granularity is the supervisor-cares-about chunk between action ("Typing 'm-o-t-e-b-i-t'") and goal ("Looking up the M2 spec"). The runtime parses the tag into the \`task_step_narration\` field on your response; the chrome consumes that field and renders it in the slab's \`motebit \xD7 virtual_browser\` register; the runtime validates against typed-truth before display so \`<narration>Reading apple.com</narration>\` when the actual URL is google.com gets falsified and replaced with a runtime-templated fallback. The \`<narration>\` tag is stripped from the visible text so it doesn't leak into the chat / mote conversation register. Omit the tag when idle, thinking, or no active task-step (the chrome recedes to the empty register). One tag per response; the runtime takes the LAST tag if you emit multiple. Goals \u2014 what the user asked you to accomplish \u2014 go in your visible response text, not here.`;
|
|
4583
4584
|
CONVERSATION_BEHAVIOR = `[How you converse]
|
|
@@ -6534,17 +6535,6 @@ var init_memory_index = __esm({
|
|
|
6534
6535
|
});
|
|
6535
6536
|
|
|
6536
6537
|
// ../../packages/memory-graph/dist/embeddings.js
|
|
6537
|
-
var embeddings_exports = {};
|
|
6538
|
-
__export(embeddings_exports, {
|
|
6539
|
-
EMBEDDING_DIMENSIONS: () => EMBEDDING_DIMENSIONS,
|
|
6540
|
-
embedText: () => embedText,
|
|
6541
|
-
embedTextHash: () => embedTextHash,
|
|
6542
|
-
resetPipeline: () => resetPipeline,
|
|
6543
|
-
setRemoteEmbedUrl: () => setRemoteEmbedUrl
|
|
6544
|
-
});
|
|
6545
|
-
function setRemoteEmbedUrl(url) {
|
|
6546
|
-
remoteEmbedUrl = url;
|
|
6547
|
-
}
|
|
6548
6538
|
async function remoteEmbed(text) {
|
|
6549
6539
|
const res = await fetch(remoteEmbedUrl, {
|
|
6550
6540
|
method: "POST",
|
|
@@ -6572,10 +6562,6 @@ async function getPipeline() {
|
|
|
6572
6562
|
throw e2;
|
|
6573
6563
|
}
|
|
6574
6564
|
}
|
|
6575
|
-
function resetPipeline() {
|
|
6576
|
-
pipelineInstance = null;
|
|
6577
|
-
pipelineFailed = false;
|
|
6578
|
-
}
|
|
6579
6565
|
async function embedText(text) {
|
|
6580
6566
|
if (text === "") {
|
|
6581
6567
|
return new Array(EMBEDDING_DIMENSIONS).fill(0);
|
|
@@ -7320,6 +7306,7 @@ var init_dist3 = __esm({
|
|
|
7320
7306
|
init_promotion();
|
|
7321
7307
|
init_memory_index();
|
|
7322
7308
|
init_embeddings();
|
|
7309
|
+
init_embeddings();
|
|
7323
7310
|
init_consolidation();
|
|
7324
7311
|
init_retrieval();
|
|
7325
7312
|
init_accrual2();
|
|
@@ -7437,13 +7424,15 @@ var init_dist3 = __esm({
|
|
|
7437
7424
|
storage;
|
|
7438
7425
|
eventStore;
|
|
7439
7426
|
motebitId;
|
|
7427
|
+
embed;
|
|
7440
7428
|
scoringConfig;
|
|
7441
7429
|
_retrievalScores = [];
|
|
7442
7430
|
_precisionOverride = null;
|
|
7443
|
-
constructor(storage, eventStore, motebitId, scoringConfig) {
|
|
7431
|
+
constructor(storage, eventStore, motebitId, scoringConfig, embed = embedText) {
|
|
7444
7432
|
this.storage = storage;
|
|
7445
7433
|
this.eventStore = eventStore;
|
|
7446
7434
|
this.motebitId = motebitId;
|
|
7435
|
+
this.embed = embed;
|
|
7447
7436
|
this.scoringConfig = { ...DEFAULT_SCORING_CONFIG, ...scoringConfig };
|
|
7448
7437
|
}
|
|
7449
7438
|
/**
|
|
@@ -7971,8 +7960,7 @@ var init_dist3 = __esm({
|
|
|
7971
7960
|
throw new Error(`No memory node with id ${oldNodeId}`);
|
|
7972
7961
|
if (oldNode.tombstoned)
|
|
7973
7962
|
throw new Error(`Memory ${oldNodeId} is already tombstoned`);
|
|
7974
|
-
const
|
|
7975
|
-
const embedding = await embedText2(newContent);
|
|
7963
|
+
const embedding = await this.embed(newContent);
|
|
7976
7964
|
const now = Date.now();
|
|
7977
7965
|
const newNode = await this.formMemory({
|
|
7978
7966
|
content: newContent,
|
|
@@ -19875,7 +19863,11 @@ function deriveSolanaAddress(publicKey) {
|
|
|
19875
19863
|
}
|
|
19876
19864
|
return base58Encode(publicKey);
|
|
19877
19865
|
}
|
|
19878
|
-
|
|
19866
|
+
function isBlockhashExpiry(err2) {
|
|
19867
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
19868
|
+
return msg.includes("block height exceeded");
|
|
19869
|
+
}
|
|
19870
|
+
var ASSET_NAME_USDC, BROADCAST_MAX_ATTEMPTS, Web3JsRpcAdapter;
|
|
19879
19871
|
var init_web3js_adapter = __esm({
|
|
19880
19872
|
"../../packages/wallet-solana/dist/web3js-adapter.js"() {
|
|
19881
19873
|
"use strict";
|
|
@@ -19883,6 +19875,7 @@ var init_web3js_adapter = __esm({
|
|
|
19883
19875
|
init_dist();
|
|
19884
19876
|
init_constants();
|
|
19885
19877
|
ASSET_NAME_USDC = "USDC";
|
|
19878
|
+
BROADCAST_MAX_ATTEMPTS = 3;
|
|
19886
19879
|
Web3JsRpcAdapter = class _Web3JsRpcAdapter {
|
|
19887
19880
|
connection;
|
|
19888
19881
|
keypair;
|
|
@@ -19961,7 +19954,7 @@ var init_web3js_adapter = __esm({
|
|
|
19961
19954
|
}
|
|
19962
19955
|
const sourceAta = await getAssociatedTokenAddress(this.mint, this.keypair.publicKey);
|
|
19963
19956
|
const destAta = await getAssociatedTokenAddress(this.mint, recipient);
|
|
19964
|
-
const
|
|
19957
|
+
const instructions = [];
|
|
19965
19958
|
let destExists = false;
|
|
19966
19959
|
try {
|
|
19967
19960
|
await getAccount(this.connection, destAta, this.commitment);
|
|
@@ -19971,7 +19964,7 @@ var init_web3js_adapter = __esm({
|
|
|
19971
19964
|
throw err2;
|
|
19972
19965
|
}
|
|
19973
19966
|
if (!destExists) {
|
|
19974
|
-
|
|
19967
|
+
instructions.push(createAssociatedTokenAccountInstruction(
|
|
19975
19968
|
this.keypair.publicKey,
|
|
19976
19969
|
// payer
|
|
19977
19970
|
destAta,
|
|
@@ -19979,22 +19972,49 @@ var init_web3js_adapter = __esm({
|
|
|
19979
19972
|
this.mint
|
|
19980
19973
|
));
|
|
19981
19974
|
}
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
|
|
19975
|
+
instructions.push(createTransferInstruction(sourceAta, destAta, this.keypair.publicKey, args.microAmount));
|
|
19976
|
+
return this.signSendConfirm(instructions);
|
|
19977
|
+
}
|
|
19978
|
+
/**
|
|
19979
|
+
* Build a transaction from `instructions`, sign it over a FRESH recent
|
|
19980
|
+
* blockhash, broadcast, and await confirmation — retrying with a new blockhash
|
|
19981
|
+
* on a `TransactionExpiredBlockheightExceededError` (the permanent-expiry
|
|
19982
|
+
* flake). Each attempt rebuilds the transaction from the instructions so no
|
|
19983
|
+
* stale blockhash/signature state carries over; the expired attempt can never
|
|
19984
|
+
* land (`isBlockhashExpiry`), so the retry cannot double-spend. Any non-expiry
|
|
19985
|
+
* error propagates immediately (conservative — only the known-safe failure is
|
|
19986
|
+
* retried).
|
|
19987
|
+
*/
|
|
19988
|
+
async signSendConfirm(instructions) {
|
|
19989
|
+
let lastErr;
|
|
19990
|
+
for (let attempt = 1; attempt <= BROADCAST_MAX_ATTEMPTS; attempt++) {
|
|
19991
|
+
try {
|
|
19992
|
+
const tx = new Transaction();
|
|
19993
|
+
for (const ix of instructions)
|
|
19994
|
+
tx.add(ix);
|
|
19995
|
+
const latest = await this.connection.getLatestBlockhash(this.commitment);
|
|
19996
|
+
tx.recentBlockhash = latest.blockhash;
|
|
19997
|
+
tx.feePayer = this.keypair.publicKey;
|
|
19998
|
+
tx.sign(this.keypair);
|
|
19999
|
+
const signature = await this.connection.sendRawTransaction(tx.serialize());
|
|
20000
|
+
const confirmation = await this.connection.confirmTransaction({
|
|
20001
|
+
signature,
|
|
20002
|
+
blockhash: latest.blockhash,
|
|
20003
|
+
lastValidBlockHeight: latest.lastValidBlockHeight
|
|
20004
|
+
}, this.commitment);
|
|
20005
|
+
return {
|
|
20006
|
+
signature,
|
|
20007
|
+
slot: confirmation.context.slot,
|
|
20008
|
+
confirmed: confirmation.value.err === null
|
|
20009
|
+
};
|
|
20010
|
+
} catch (err2) {
|
|
20011
|
+
lastErr = err2;
|
|
20012
|
+
if (attempt < BROADCAST_MAX_ATTEMPTS && isBlockhashExpiry(err2))
|
|
20013
|
+
continue;
|
|
20014
|
+
throw err2;
|
|
20015
|
+
}
|
|
20016
|
+
}
|
|
20017
|
+
throw lastErr;
|
|
19998
20018
|
}
|
|
19999
20019
|
/**
|
|
20000
20020
|
* Conservative max transfers per Solana transaction.
|
|
@@ -20031,7 +20051,7 @@ var init_web3js_adapter = __esm({
|
|
|
20031
20051
|
continue;
|
|
20032
20052
|
}
|
|
20033
20053
|
try {
|
|
20034
|
-
const
|
|
20054
|
+
const instructions = [];
|
|
20035
20055
|
const sourceAta = await getAssociatedTokenAddress(this.mint, this.keypair.publicKey);
|
|
20036
20056
|
for (let i3 = start; i3 < end; i3++) {
|
|
20037
20057
|
const item = items[i3];
|
|
@@ -20051,30 +20071,20 @@ var init_web3js_adapter = __esm({
|
|
|
20051
20071
|
throw err2;
|
|
20052
20072
|
}
|
|
20053
20073
|
if (!destExists) {
|
|
20054
|
-
|
|
20074
|
+
instructions.push(createAssociatedTokenAccountInstruction(this.keypair.publicKey, destAta, recipient, this.mint));
|
|
20055
20075
|
}
|
|
20056
|
-
|
|
20076
|
+
instructions.push(createTransferInstruction(sourceAta, destAta, this.keypair.publicKey, item.microAmount));
|
|
20057
20077
|
}
|
|
20058
|
-
const
|
|
20059
|
-
tx.recentBlockhash = latest.blockhash;
|
|
20060
|
-
tx.feePayer = this.keypair.publicKey;
|
|
20061
|
-
tx.sign(this.keypair);
|
|
20062
|
-
const signature = await this.connection.sendRawTransaction(tx.serialize());
|
|
20063
|
-
const confirmation = await this.connection.confirmTransaction({
|
|
20064
|
-
signature,
|
|
20065
|
-
blockhash: latest.blockhash,
|
|
20066
|
-
lastValidBlockHeight: latest.lastValidBlockHeight
|
|
20067
|
-
}, this.commitment);
|
|
20068
|
-
const ok = confirmation.value.err === null;
|
|
20078
|
+
const { signature, slot, confirmed } = await this.signSendConfirm(instructions);
|
|
20069
20079
|
for (let i3 = start; i3 < end; i3++) {
|
|
20070
20080
|
results[i3] = {
|
|
20071
|
-
ok,
|
|
20081
|
+
ok: confirmed,
|
|
20072
20082
|
signature,
|
|
20073
|
-
slot
|
|
20074
|
-
reason:
|
|
20083
|
+
slot,
|
|
20084
|
+
reason: confirmed ? null : "tx failed"
|
|
20075
20085
|
};
|
|
20076
20086
|
}
|
|
20077
|
-
if (!
|
|
20087
|
+
if (!confirmed)
|
|
20078
20088
|
aborted = true;
|
|
20079
20089
|
} catch (err2) {
|
|
20080
20090
|
const reason = err2 instanceof Error ? err2.message : String(err2);
|
|
@@ -20978,7 +20988,7 @@ var init_config2 = __esm({
|
|
|
20978
20988
|
"src/config.ts"() {
|
|
20979
20989
|
"use strict";
|
|
20980
20990
|
init_esm_shims();
|
|
20981
|
-
VERSION = true ? "1.8.
|
|
20991
|
+
VERSION = true ? "1.8.3" : "0.0.0-dev";
|
|
20982
20992
|
CONFIG_DIR = process.env["MOTEBIT_CONFIG_DIR"] ?? path2.join(os.homedir(), ".motebit");
|
|
20983
20993
|
CONFIG_PATH = path2.join(CONFIG_DIR, "config.json");
|
|
20984
20994
|
RELAY_DIR = path2.join(CONFIG_DIR, "relay");
|
|
@@ -27280,6 +27290,153 @@ var init_agent_network = __esm({
|
|
|
27280
27290
|
}
|
|
27281
27291
|
});
|
|
27282
27292
|
|
|
27293
|
+
// ../../packages/semiring/dist/thompson.js
|
|
27294
|
+
function mulberry322(seed) {
|
|
27295
|
+
let a3 = seed >>> 0;
|
|
27296
|
+
return () => {
|
|
27297
|
+
a3 = a3 + 1831565813 | 0;
|
|
27298
|
+
let t3 = Math.imul(a3 ^ a3 >>> 15, 1 | a3);
|
|
27299
|
+
t3 = t3 + Math.imul(t3 ^ t3 >>> 7, 61 | t3) ^ t3;
|
|
27300
|
+
return ((t3 ^ t3 >>> 14) >>> 0) / 4294967296;
|
|
27301
|
+
};
|
|
27302
|
+
}
|
|
27303
|
+
function hashSeed(input) {
|
|
27304
|
+
let h5 = 2166136261 >>> 0;
|
|
27305
|
+
for (let i3 = 0; i3 < input.length; i3++) {
|
|
27306
|
+
h5 ^= input.charCodeAt(i3);
|
|
27307
|
+
h5 = Math.imul(h5, 16777619);
|
|
27308
|
+
}
|
|
27309
|
+
return h5 >>> 0;
|
|
27310
|
+
}
|
|
27311
|
+
function gammaInt(k4, rng) {
|
|
27312
|
+
let sum2 = 0;
|
|
27313
|
+
for (let i3 = 0; i3 < k4; i3++) {
|
|
27314
|
+
const u2 = rng();
|
|
27315
|
+
sum2 -= Math.log(u2 > 0 ? u2 : Number.MIN_VALUE);
|
|
27316
|
+
}
|
|
27317
|
+
return sum2;
|
|
27318
|
+
}
|
|
27319
|
+
function sampleBeta(alpha, beta, rng) {
|
|
27320
|
+
if (!Number.isInteger(alpha) || !Number.isInteger(beta) || alpha < 1 || beta < 1) {
|
|
27321
|
+
throw new RangeError(`sampleBeta requires positive integer shapes; got alpha=${alpha}, beta=${beta}`);
|
|
27322
|
+
}
|
|
27323
|
+
const ga = gammaInt(alpha, rng);
|
|
27324
|
+
const gb = gammaInt(beta, rng);
|
|
27325
|
+
return ga / (ga + gb);
|
|
27326
|
+
}
|
|
27327
|
+
function thompsonDraw(alpha, beta, seed) {
|
|
27328
|
+
return sampleBeta(alpha, beta, mulberry322(hashSeed(seed)));
|
|
27329
|
+
}
|
|
27330
|
+
var init_thompson = __esm({
|
|
27331
|
+
"../../packages/semiring/dist/thompson.js"() {
|
|
27332
|
+
"use strict";
|
|
27333
|
+
init_esm_shims();
|
|
27334
|
+
}
|
|
27335
|
+
});
|
|
27336
|
+
|
|
27337
|
+
// ../../packages/semiring/dist/worker-selection.js
|
|
27338
|
+
function levelPrior(level) {
|
|
27339
|
+
switch (level) {
|
|
27340
|
+
case AgentTrustLevel.Trusted:
|
|
27341
|
+
return { a: 3, b: 1 };
|
|
27342
|
+
case AgentTrustLevel.Verified:
|
|
27343
|
+
return { a: 2, b: 1 };
|
|
27344
|
+
default:
|
|
27345
|
+
return { a: 1, b: 1 };
|
|
27346
|
+
}
|
|
27347
|
+
}
|
|
27348
|
+
function competenceCounts(record, capability) {
|
|
27349
|
+
if (!record)
|
|
27350
|
+
return { successful: 0, failed: 0 };
|
|
27351
|
+
if (capability != null) {
|
|
27352
|
+
const bucket = record.capability_stats?.[capability];
|
|
27353
|
+
return { successful: bucket?.successful_tasks ?? 0, failed: bucket?.failed_tasks ?? 0 };
|
|
27354
|
+
}
|
|
27355
|
+
return { successful: record.successful_tasks ?? 0, failed: record.failed_tasks ?? 0 };
|
|
27356
|
+
}
|
|
27357
|
+
function clampStrength(x3) {
|
|
27358
|
+
return Number.isFinite(x3) ? Math.min(1, Math.max(0, x3)) : 0;
|
|
27359
|
+
}
|
|
27360
|
+
function cappedCounts(successful, failed) {
|
|
27361
|
+
const s0 = Math.max(0, Math.floor(successful));
|
|
27362
|
+
const f0 = Math.max(0, Math.floor(failed));
|
|
27363
|
+
const total = s0 + f0;
|
|
27364
|
+
if (total <= COUNT_CAP)
|
|
27365
|
+
return { s: s0, f: f0 };
|
|
27366
|
+
const s3 = Math.round(s0 * COUNT_CAP / total);
|
|
27367
|
+
return { s: s3, f: COUNT_CAP - s3 };
|
|
27368
|
+
}
|
|
27369
|
+
function exploratoryQuality(c3, explore, capability) {
|
|
27370
|
+
const prior = levelPrior(c3.trustRecord?.trust_level);
|
|
27371
|
+
const counts = competenceCounts(c3.trustRecord, capability);
|
|
27372
|
+
const { s: s3, f: f6 } = cappedCounts(counts.successful, counts.failed);
|
|
27373
|
+
const alpha = prior.a + s3;
|
|
27374
|
+
const beta = prior.b + f6;
|
|
27375
|
+
const mean = alpha / (alpha + beta);
|
|
27376
|
+
const base = clampStrength(explore.strength ?? 1);
|
|
27377
|
+
const strength = c3.bonded ? Math.min(1, base * BOND_EXPLORE_BOOST) : base;
|
|
27378
|
+
if (strength <= 0)
|
|
27379
|
+
return mean;
|
|
27380
|
+
const draw = thompsonDraw(alpha, beta, `${explore.seed}|${c3.motebit_id}`);
|
|
27381
|
+
return mean + strength * (draw - mean);
|
|
27382
|
+
}
|
|
27383
|
+
function reliabilityOf(record, capability) {
|
|
27384
|
+
if (!record)
|
|
27385
|
+
return 0.5;
|
|
27386
|
+
const { successful, failed } = competenceCounts(record, capability);
|
|
27387
|
+
return (1 + successful) / (2 + successful + failed);
|
|
27388
|
+
}
|
|
27389
|
+
function rankWorkers(selfId, candidates, opts) {
|
|
27390
|
+
const weights = opts?.weights ?? DEFAULT_WEIGHTS;
|
|
27391
|
+
const capability = opts?.capability;
|
|
27392
|
+
const explore = opts?.explore != null && clampStrength(opts.explore.strength ?? 1) > 0 ? opts.explore : void 0;
|
|
27393
|
+
const graph = new WeightedDigraph(RouteWeightSemiring);
|
|
27394
|
+
graph.addNode(selfId);
|
|
27395
|
+
for (const c3 of candidates) {
|
|
27396
|
+
if (c3.trustRecord?.trust_level === AgentTrustLevel.Blocked)
|
|
27397
|
+
continue;
|
|
27398
|
+
const trust = explore ? exploratoryQuality(c3, explore, capability) : trustLevelToScore(c3.trustRecord?.trust_level ?? AgentTrustLevel.Unknown);
|
|
27399
|
+
const reliability = explore ? trust : reliabilityOf(c3.trustRecord, capability);
|
|
27400
|
+
graph.setEdge(selfId, c3.motebit_id, {
|
|
27401
|
+
trust,
|
|
27402
|
+
cost: c3.unitCost ?? 0,
|
|
27403
|
+
latency: DEFAULT_LATENCY_MS,
|
|
27404
|
+
reliability,
|
|
27405
|
+
regulatory_risk: 0
|
|
27406
|
+
});
|
|
27407
|
+
}
|
|
27408
|
+
const ranked = rankReachableAgents(graph, selfId, {
|
|
27409
|
+
trust: weights.trust,
|
|
27410
|
+
cost: weights.cost,
|
|
27411
|
+
latency: weights.latency,
|
|
27412
|
+
reliability: weights.reliability,
|
|
27413
|
+
regulatory_risk: 0
|
|
27414
|
+
});
|
|
27415
|
+
return ranked.map((r2) => ({ motebit_id: r2.motebit_id, score: r2.score, route: r2.route })).sort((a3, b3) => b3.score - a3.score || (a3.motebit_id < b3.motebit_id ? -1 : 1));
|
|
27416
|
+
}
|
|
27417
|
+
function selectWorker(selfId, candidates, opts) {
|
|
27418
|
+
return rankWorkers(selfId, candidates, opts)[0] ?? null;
|
|
27419
|
+
}
|
|
27420
|
+
var DEFAULT_LATENCY_MS, COUNT_CAP, BOND_EXPLORE_BOOST, DEFAULT_WEIGHTS;
|
|
27421
|
+
var init_worker_selection = __esm({
|
|
27422
|
+
"../../packages/semiring/dist/worker-selection.js"() {
|
|
27423
|
+
"use strict";
|
|
27424
|
+
init_esm_shims();
|
|
27425
|
+
init_dist();
|
|
27426
|
+
init_agent_network();
|
|
27427
|
+
init_thompson();
|
|
27428
|
+
DEFAULT_LATENCY_MS = 5e3;
|
|
27429
|
+
COUNT_CAP = 100;
|
|
27430
|
+
BOND_EXPLORE_BOOST = 2;
|
|
27431
|
+
DEFAULT_WEIGHTS = {
|
|
27432
|
+
trust: 0.5,
|
|
27433
|
+
reliability: 0.3,
|
|
27434
|
+
cost: 0.2,
|
|
27435
|
+
latency: 0
|
|
27436
|
+
};
|
|
27437
|
+
}
|
|
27438
|
+
});
|
|
27439
|
+
|
|
27283
27440
|
// ../../packages/semiring/dist/disambiguation.js
|
|
27284
27441
|
var init_disambiguation = __esm({
|
|
27285
27442
|
"../../packages/semiring/dist/disambiguation.js"() {
|
|
@@ -27339,6 +27496,8 @@ var init_dist14 = __esm({
|
|
|
27339
27496
|
init_trust_algebra2();
|
|
27340
27497
|
init_provenance();
|
|
27341
27498
|
init_agent_network();
|
|
27499
|
+
init_worker_selection();
|
|
27500
|
+
init_thompson();
|
|
27342
27501
|
init_disambiguation();
|
|
27343
27502
|
init_hardware_attestation();
|
|
27344
27503
|
}
|
|
@@ -42523,269 +42682,822 @@ var init_grant_verifier = __esm({
|
|
|
42523
42682
|
}
|
|
42524
42683
|
});
|
|
42525
42684
|
|
|
42526
|
-
// ../../packages/runtime/dist/
|
|
42527
|
-
function
|
|
42528
|
-
|
|
42529
|
-
|
|
42530
|
-
|
|
42531
|
-
|
|
42532
|
-
|
|
42533
|
-
|
|
42534
|
-
|
|
42535
|
-
|
|
42536
|
-
}
|
|
42537
|
-
const
|
|
42538
|
-
|
|
42539
|
-
|
|
42540
|
-
|
|
42541
|
-
|
|
42542
|
-
|
|
42543
|
-
}
|
|
42544
|
-
|
|
42545
|
-
}
|
|
42546
|
-
|
|
42547
|
-
|
|
42548
|
-
|
|
42549
|
-
|
|
42550
|
-
|
|
42551
|
-
|
|
42552
|
-
|
|
42553
|
-
|
|
42554
|
-
|
|
42555
|
-
|
|
42556
|
-
this.opts = opts;
|
|
42557
|
-
}
|
|
42558
|
-
/** Redact the outbound pack unless the provider is sovereign (on-device). */
|
|
42559
|
-
packFor(pack) {
|
|
42560
|
-
if (this.opts.isSovereign())
|
|
42561
|
-
return pack;
|
|
42562
|
-
const { pack: redacted, redactedCount, labels } = redactPackForCloudEgress(pack, this.opts.redact);
|
|
42563
|
-
if (redactedCount > 0)
|
|
42564
|
-
this.opts.onRedacted?.({ count: redactedCount, labels });
|
|
42565
|
-
return redacted;
|
|
42566
|
-
}
|
|
42567
|
-
get model() {
|
|
42568
|
-
return this.inner.model;
|
|
42569
|
-
}
|
|
42570
|
-
get temperature() {
|
|
42571
|
-
return this.inner.temperature;
|
|
42572
|
-
}
|
|
42573
|
-
get maxTokens() {
|
|
42574
|
-
return this.inner.maxTokens;
|
|
42575
|
-
}
|
|
42576
|
-
setModel(model) {
|
|
42577
|
-
this.inner.setModel(model);
|
|
42578
|
-
}
|
|
42579
|
-
setTemperature(temperature) {
|
|
42580
|
-
this.inner.setTemperature?.(temperature);
|
|
42581
|
-
}
|
|
42582
|
-
setMaxTokens(maxTokens) {
|
|
42583
|
-
this.inner.setMaxTokens?.(maxTokens);
|
|
42584
|
-
}
|
|
42585
|
-
generate(pack) {
|
|
42586
|
-
return this.inner.generate(this.packFor(pack));
|
|
42587
|
-
}
|
|
42588
|
-
generateStream(pack) {
|
|
42589
|
-
return this.inner.generateStream(this.packFor(pack));
|
|
42590
|
-
}
|
|
42591
|
-
estimateConfidence() {
|
|
42592
|
-
return this.inner.estimateConfidence();
|
|
42593
|
-
}
|
|
42594
|
-
extractMemoryCandidates(response) {
|
|
42595
|
-
return this.inner.extractMemoryCandidates(response);
|
|
42596
|
-
}
|
|
42685
|
+
// ../../packages/runtime/dist/relay-delegation.js
|
|
42686
|
+
function classifyRelayError(status, body, retryAfterHeader) {
|
|
42687
|
+
const retryAfterSeconds = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : void 0;
|
|
42688
|
+
let relayCode;
|
|
42689
|
+
let relayMessage;
|
|
42690
|
+
try {
|
|
42691
|
+
const parsed = JSON.parse(body);
|
|
42692
|
+
relayCode = parsed.code;
|
|
42693
|
+
relayMessage = parsed.error;
|
|
42694
|
+
} catch {
|
|
42695
|
+
}
|
|
42696
|
+
const message2 = relayMessage ?? body.slice(0, 512);
|
|
42697
|
+
if (status === 401) {
|
|
42698
|
+
return { code: "auth_expired", message: message2, status };
|
|
42699
|
+
}
|
|
42700
|
+
if (relayCode === "TASK_P2P_PROOF_REQUIRED") {
|
|
42701
|
+
return { code: "payment_proof_required", message: message2, status };
|
|
42702
|
+
}
|
|
42703
|
+
if (status === 402 || relayCode === "INSUFFICIENT_FUNDS") {
|
|
42704
|
+
return { code: "insufficient_balance", message: message2, status };
|
|
42705
|
+
}
|
|
42706
|
+
if (status === 403) {
|
|
42707
|
+
return { code: "unauthorized", message: message2, status };
|
|
42708
|
+
}
|
|
42709
|
+
if (status === 429) {
|
|
42710
|
+
return {
|
|
42711
|
+
code: "rate_limited",
|
|
42712
|
+
message: message2,
|
|
42713
|
+
status,
|
|
42714
|
+
...Number.isFinite(retryAfterSeconds) ? { retryAfterSeconds } : {}
|
|
42597
42715
|
};
|
|
42598
42716
|
}
|
|
42599
|
-
|
|
42600
|
-
|
|
42601
|
-
|
|
42602
|
-
|
|
42603
|
-
|
|
42604
|
-
|
|
42605
|
-
|
|
42606
|
-
|
|
42607
|
-
|
|
42608
|
-
|
|
42609
|
-
|
|
42610
|
-
|
|
42611
|
-
|
|
42612
|
-
|
|
42613
|
-
|
|
42614
|
-
|
|
42615
|
-
|
|
42616
|
-
|
|
42617
|
-
|
|
42618
|
-
|
|
42619
|
-
|
|
42620
|
-
|
|
42621
|
-
|
|
42622
|
-
onChange(fn) {
|
|
42623
|
-
this.changeListeners.add(fn);
|
|
42624
|
-
return () => {
|
|
42625
|
-
this.changeListeners.delete(fn);
|
|
42626
|
-
};
|
|
42627
|
-
}
|
|
42628
|
-
/**
|
|
42629
|
-
* Issue a W3C Verifiable Credential containing this agent's current gradient.
|
|
42630
|
-
* Returns null if no gradient has been computed or no private key is available.
|
|
42631
|
-
*/
|
|
42632
|
-
async issueGradientCredential(privateKey, publicKey) {
|
|
42633
|
-
const snapshot = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
42634
|
-
if (!snapshot)
|
|
42635
|
-
return null;
|
|
42636
|
-
return issueGradientCredential(snapshot, privateKey, publicKey);
|
|
42637
|
-
}
|
|
42638
|
-
/**
|
|
42639
|
-
* Return all verifiable credentials issued by this runtime (gradient + trust).
|
|
42640
|
-
* Credentials accumulate in memory; consumers can read and clear as needed.
|
|
42641
|
-
*/
|
|
42642
|
-
getIssuedCredentials() {
|
|
42643
|
-
return [...this._issuedCredentials];
|
|
42644
|
-
}
|
|
42645
|
-
/**
|
|
42646
|
-
* Clear the in-memory credential cache (e.g. after persisting or presenting them).
|
|
42647
|
-
*/
|
|
42648
|
-
clearIssuedCredentials() {
|
|
42649
|
-
this._issuedCredentials = [];
|
|
42650
|
-
}
|
|
42651
|
-
/** Push a credential to both in-memory cache and persistent store. */
|
|
42652
|
-
persistCredential(vc, subjectMotebitId) {
|
|
42653
|
-
this._issuedCredentials.push(vc);
|
|
42654
|
-
if (this.deps.credentialStore) {
|
|
42655
|
-
try {
|
|
42656
|
-
const credType = vc.type.find((t3) => t3 !== "VerifiableCredential") ?? "VerifiableCredential";
|
|
42657
|
-
this.deps.credentialStore.save({
|
|
42658
|
-
credential_id: crypto.randomUUID(),
|
|
42659
|
-
subject_motebit_id: vc.credentialSubject?.id ?? "",
|
|
42660
|
-
issuer_did: vc.issuer,
|
|
42661
|
-
credential_type: credType,
|
|
42662
|
-
credential_json: JSON.stringify(vc),
|
|
42663
|
-
issued_at: Date.now()
|
|
42664
|
-
});
|
|
42665
|
-
} catch (err2) {
|
|
42666
|
-
this.deps.logger.warn("credential persistence failed", {
|
|
42667
|
-
error: err2 instanceof Error ? err2.message : String(err2)
|
|
42668
|
-
});
|
|
42669
|
-
}
|
|
42670
|
-
}
|
|
42671
|
-
if (this.credentialSubmitter && subjectMotebitId) {
|
|
42672
|
-
this.credentialSubmitter(vc, subjectMotebitId).catch((err2) => {
|
|
42673
|
-
this.deps.logger.warn("credential relay submission failed", {
|
|
42674
|
-
error: err2 instanceof Error ? err2.message : String(err2)
|
|
42675
|
-
});
|
|
42676
|
-
});
|
|
42677
|
-
}
|
|
42678
|
-
for (const listener of this.changeListeners) {
|
|
42679
|
-
try {
|
|
42680
|
-
listener();
|
|
42681
|
-
} catch (err2) {
|
|
42682
|
-
this.deps.logger.warn("credential change listener threw", {
|
|
42683
|
-
error: err2 instanceof Error ? err2.message : String(err2)
|
|
42684
|
-
});
|
|
42685
|
-
}
|
|
42686
|
-
}
|
|
42717
|
+
if (status === 400) {
|
|
42718
|
+
return { code: "malformed_request", message: message2, status };
|
|
42719
|
+
}
|
|
42720
|
+
return { code: "unknown", message: message2, status };
|
|
42721
|
+
}
|
|
42722
|
+
async function submitAndPollDelegation(params) {
|
|
42723
|
+
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
42724
|
+
const startedAt = Date.now();
|
|
42725
|
+
let submitHeader;
|
|
42726
|
+
let queryHeader;
|
|
42727
|
+
try {
|
|
42728
|
+
const [submitToken, queryToken] = await Promise.all([
|
|
42729
|
+
params.authToken("task:submit"),
|
|
42730
|
+
params.authToken("task:query")
|
|
42731
|
+
]);
|
|
42732
|
+
submitHeader = `Bearer ${submitToken}`;
|
|
42733
|
+
queryHeader = `Bearer ${queryToken}`;
|
|
42734
|
+
} catch (err2) {
|
|
42735
|
+
return {
|
|
42736
|
+
ok: false,
|
|
42737
|
+
error: {
|
|
42738
|
+
code: "auth_expired",
|
|
42739
|
+
message: `Auth token mint failed: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
42687
42740
|
}
|
|
42688
42741
|
};
|
|
42689
42742
|
}
|
|
42690
|
-
|
|
42691
|
-
|
|
42692
|
-
|
|
42693
|
-
|
|
42694
|
-
|
|
42695
|
-
|
|
42696
|
-
|
|
42697
|
-
|
|
42698
|
-
try {
|
|
42699
|
-
rows = store.listBySubject(subjectKey);
|
|
42700
|
-
} catch {
|
|
42701
|
-
return;
|
|
42743
|
+
let taskId;
|
|
42744
|
+
try {
|
|
42745
|
+
const body = {
|
|
42746
|
+
prompt: params.prompt,
|
|
42747
|
+
submitted_by: params.motebitId
|
|
42748
|
+
};
|
|
42749
|
+
if (params.requiredCapabilities && params.requiredCapabilities.length > 0) {
|
|
42750
|
+
body.required_capabilities = params.requiredCapabilities;
|
|
42702
42751
|
}
|
|
42703
|
-
|
|
42704
|
-
|
|
42705
|
-
continue;
|
|
42706
|
-
if (seen.has(row.credential_id))
|
|
42707
|
-
continue;
|
|
42708
|
-
seen.add(row.credential_id);
|
|
42709
|
-
candidates.push(row);
|
|
42752
|
+
if (params.routingStrategy) {
|
|
42753
|
+
body.routing_strategy = params.routingStrategy;
|
|
42710
42754
|
}
|
|
42711
|
-
|
|
42712
|
-
|
|
42713
|
-
try {
|
|
42714
|
-
collect(hexPublicKeyToDidKey(record.public_key));
|
|
42715
|
-
} catch {
|
|
42755
|
+
if (params.invocationOrigin) {
|
|
42756
|
+
body.invocation_origin = params.invocationOrigin;
|
|
42716
42757
|
}
|
|
42717
|
-
|
|
42718
|
-
|
|
42719
|
-
if (candidates.length === 0)
|
|
42720
|
-
return null;
|
|
42721
|
-
candidates.sort((a3, b3) => b3.issued_at - a3.issued_at);
|
|
42722
|
-
for (const row of candidates) {
|
|
42723
|
-
let parsed;
|
|
42724
|
-
try {
|
|
42725
|
-
parsed = JSON.parse(row.credential_json);
|
|
42726
|
-
} catch {
|
|
42727
|
-
continue;
|
|
42758
|
+
if (params.grantId != null) {
|
|
42759
|
+
body.grant_id = params.grantId;
|
|
42728
42760
|
}
|
|
42729
|
-
const
|
|
42730
|
-
|
|
42761
|
+
const resp = await fetch(`${params.syncUrl}/agent/${params.motebitId}/task`, {
|
|
42762
|
+
method: "POST",
|
|
42763
|
+
headers: {
|
|
42764
|
+
"Content-Type": "application/json",
|
|
42765
|
+
Authorization: submitHeader,
|
|
42766
|
+
"Idempotency-Key": crypto.randomUUID()
|
|
42767
|
+
},
|
|
42768
|
+
body: JSON.stringify(body),
|
|
42769
|
+
signal: params.signal
|
|
42770
|
+
});
|
|
42771
|
+
if (!resp.ok) {
|
|
42772
|
+
const text = await resp.text().catch(() => "");
|
|
42731
42773
|
return {
|
|
42732
|
-
|
|
42733
|
-
|
|
42734
|
-
|
|
42774
|
+
ok: false,
|
|
42775
|
+
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
42776
|
+
};
|
|
42777
|
+
}
|
|
42778
|
+
const data = await resp.json();
|
|
42779
|
+
taskId = data.task_id;
|
|
42780
|
+
} catch (err2) {
|
|
42781
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
42782
|
+
return {
|
|
42783
|
+
ok: false,
|
|
42784
|
+
error: { code: "timeout", message: "Aborted before submission completed" }
|
|
42735
42785
|
};
|
|
42736
42786
|
}
|
|
42787
|
+
return {
|
|
42788
|
+
ok: false,
|
|
42789
|
+
error: {
|
|
42790
|
+
code: "network_unreachable",
|
|
42791
|
+
message: err2 instanceof Error ? err2.message : String(err2)
|
|
42792
|
+
}
|
|
42793
|
+
};
|
|
42737
42794
|
}
|
|
42738
|
-
|
|
42795
|
+
const result = await pollForReceipt({
|
|
42796
|
+
syncUrl: params.syncUrl,
|
|
42797
|
+
motebitId: params.motebitId,
|
|
42798
|
+
taskId,
|
|
42799
|
+
queryHeader,
|
|
42800
|
+
timeoutMs,
|
|
42801
|
+
startedAt,
|
|
42802
|
+
logger: params.logger,
|
|
42803
|
+
...params.signal ? { signal: params.signal } : {}
|
|
42804
|
+
});
|
|
42805
|
+
return result.ok ? { ...result, settlement: { mode: "relay" } } : result;
|
|
42739
42806
|
}
|
|
42740
|
-
|
|
42741
|
-
|
|
42742
|
-
|
|
42743
|
-
|
|
42744
|
-
|
|
42745
|
-
|
|
42746
|
-
|
|
42747
|
-
|
|
42748
|
-
|
|
42749
|
-
|
|
42750
|
-
|
|
42751
|
-
|
|
42752
|
-
|
|
42753
|
-
|
|
42754
|
-
|
|
42755
|
-
|
|
42756
|
-
|
|
42757
|
-
|
|
42807
|
+
async function pollForReceipt(args) {
|
|
42808
|
+
const maxPolls = Math.ceil(args.timeoutMs / POLL_INTERVAL_MS);
|
|
42809
|
+
for (let i3 = 0; i3 < maxPolls; i3++) {
|
|
42810
|
+
if (args.signal?.aborted) {
|
|
42811
|
+
return { ok: false, error: { code: "timeout", message: "Aborted mid-poll" } };
|
|
42812
|
+
}
|
|
42813
|
+
await new Promise((resolve14, reject) => {
|
|
42814
|
+
const t3 = setTimeout(resolve14, POLL_INTERVAL_MS);
|
|
42815
|
+
args.signal?.addEventListener("abort", () => {
|
|
42816
|
+
clearTimeout(t3);
|
|
42817
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
42818
|
+
}, { once: true });
|
|
42819
|
+
}).catch(() => {
|
|
42820
|
+
});
|
|
42821
|
+
try {
|
|
42822
|
+
const resp = await fetch(`${args.syncUrl}/agent/${args.motebitId}/task/${args.taskId}`, {
|
|
42823
|
+
headers: { Authorization: args.queryHeader },
|
|
42824
|
+
signal: args.signal
|
|
42825
|
+
});
|
|
42826
|
+
if (!resp.ok) {
|
|
42827
|
+
args.logger.warn("delegation poll failed", {
|
|
42828
|
+
taskId: args.taskId,
|
|
42829
|
+
status: resp.status,
|
|
42830
|
+
body: await resp.text().catch(() => "")
|
|
42831
|
+
});
|
|
42832
|
+
continue;
|
|
42833
|
+
}
|
|
42834
|
+
const data = await resp.json();
|
|
42835
|
+
if (data.receipt != null) {
|
|
42836
|
+
return { ok: true, receipt: data.receipt, taskId: args.taskId };
|
|
42837
|
+
}
|
|
42838
|
+
if (data.task.status === "failed") {
|
|
42839
|
+
return {
|
|
42840
|
+
ok: false,
|
|
42841
|
+
error: { code: "agent_failed", message: "Agent reported failure without a receipt" }
|
|
42842
|
+
};
|
|
42843
|
+
}
|
|
42844
|
+
} catch (err2) {
|
|
42845
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
42846
|
+
return { ok: false, error: { code: "timeout", message: "Aborted mid-poll" } };
|
|
42847
|
+
}
|
|
42848
|
+
}
|
|
42758
42849
|
}
|
|
42759
|
-
|
|
42760
|
-
return null;
|
|
42850
|
+
const elapsedMs = Date.now() - args.startedAt;
|
|
42761
42851
|
return {
|
|
42762
|
-
|
|
42763
|
-
|
|
42764
|
-
sample_count: stats.sample_count
|
|
42852
|
+
ok: false,
|
|
42853
|
+
error: { code: "timeout", message: `No receipt within ${Math.round(elapsedMs / 1e3)}s` }
|
|
42765
42854
|
};
|
|
42766
42855
|
}
|
|
42767
|
-
|
|
42768
|
-
|
|
42769
|
-
|
|
42770
|
-
|
|
42856
|
+
async function submitP2pDelegation(params) {
|
|
42857
|
+
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
42858
|
+
const startedAt = Date.now();
|
|
42859
|
+
let submitHeader;
|
|
42860
|
+
let queryHeader;
|
|
42861
|
+
try {
|
|
42862
|
+
const [submitToken, queryToken] = await Promise.all([
|
|
42863
|
+
params.authToken("task:submit"),
|
|
42864
|
+
params.authToken("task:query")
|
|
42865
|
+
]);
|
|
42866
|
+
submitHeader = `Bearer ${submitToken}`;
|
|
42867
|
+
queryHeader = `Bearer ${queryToken}`;
|
|
42868
|
+
} catch (err2) {
|
|
42869
|
+
return {
|
|
42870
|
+
ok: false,
|
|
42871
|
+
error: {
|
|
42872
|
+
code: "auth_expired",
|
|
42873
|
+
message: `Auth token mint failed: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
42874
|
+
}
|
|
42875
|
+
};
|
|
42771
42876
|
}
|
|
42772
|
-
|
|
42773
|
-
|
|
42774
|
-
|
|
42775
|
-
|
|
42776
|
-
|
|
42777
|
-
|
|
42778
|
-
|
|
42779
|
-
|
|
42780
|
-
|
|
42781
|
-
|
|
42782
|
-
|
|
42783
|
-
|
|
42784
|
-
|
|
42785
|
-
|
|
42786
|
-
|
|
42787
|
-
|
|
42788
|
-
|
|
42877
|
+
let taskId;
|
|
42878
|
+
try {
|
|
42879
|
+
const body = {
|
|
42880
|
+
prompt: params.prompt,
|
|
42881
|
+
submitted_by: params.motebitId,
|
|
42882
|
+
target_agent: params.targetWorkerId,
|
|
42883
|
+
settlement_mode: "p2p",
|
|
42884
|
+
// The relay's task-submission handler reads the proof under `payment_proof`
|
|
42885
|
+
// (services/relay/src/tasks.ts) — NOT `p2p_payment_proof` (that's only the
|
|
42886
|
+
// relay's internal TaskQueue field name). Sending the wrong key made the
|
|
42887
|
+
// relay see no proof and reject every paid cross-agent delegation with 402
|
|
42888
|
+
// TASK_P2P_PROOF_REQUIRED. The federation-e2e client↔relay integration test
|
|
42889
|
+
// locks this wire key (the seam that mocked-fetch unit tests can't catch).
|
|
42890
|
+
payment_proof: params.paymentProof
|
|
42891
|
+
};
|
|
42892
|
+
if (params.requiredCapabilities && params.requiredCapabilities.length > 0) {
|
|
42893
|
+
body.required_capabilities = params.requiredCapabilities;
|
|
42894
|
+
}
|
|
42895
|
+
if (params.acknowledgeNoHistoryRisk === true) {
|
|
42896
|
+
body.delegator_acknowledges_no_history_risk = true;
|
|
42897
|
+
}
|
|
42898
|
+
if (params.invocationOrigin) {
|
|
42899
|
+
body.invocation_origin = params.invocationOrigin;
|
|
42900
|
+
}
|
|
42901
|
+
if (params.grantId != null) {
|
|
42902
|
+
body.grant_id = params.grantId;
|
|
42903
|
+
}
|
|
42904
|
+
const resp = await fetch(`${params.syncUrl}/agent/${params.motebitId}/task`, {
|
|
42905
|
+
method: "POST",
|
|
42906
|
+
headers: {
|
|
42907
|
+
"Content-Type": "application/json",
|
|
42908
|
+
Authorization: submitHeader,
|
|
42909
|
+
// Stable across retries of the SAME logical delegation so a re-submit
|
|
42910
|
+
// of the already-paid proof dedupes byte-identically rather than
|
|
42911
|
+
// racing a second task. Keyed on the onchain tx_hash, which uniquely
|
|
42912
|
+
// identifies this payment.
|
|
42913
|
+
"Idempotency-Key": params.paymentProof.tx_hash
|
|
42914
|
+
},
|
|
42915
|
+
body: JSON.stringify(body),
|
|
42916
|
+
signal: params.signal
|
|
42917
|
+
});
|
|
42918
|
+
if (!resp.ok) {
|
|
42919
|
+
const text = await resp.text().catch(() => "");
|
|
42920
|
+
return {
|
|
42921
|
+
ok: false,
|
|
42922
|
+
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
42923
|
+
};
|
|
42924
|
+
}
|
|
42925
|
+
const data = await resp.json();
|
|
42926
|
+
taskId = data.task_id;
|
|
42927
|
+
} catch (err2) {
|
|
42928
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
42929
|
+
return {
|
|
42930
|
+
ok: false,
|
|
42931
|
+
error: { code: "timeout", message: "Aborted before submission completed" }
|
|
42932
|
+
};
|
|
42933
|
+
}
|
|
42934
|
+
return {
|
|
42935
|
+
ok: false,
|
|
42936
|
+
error: {
|
|
42937
|
+
code: "network_unreachable",
|
|
42938
|
+
message: err2 instanceof Error ? err2.message : String(err2)
|
|
42939
|
+
}
|
|
42940
|
+
};
|
|
42941
|
+
}
|
|
42942
|
+
const result = await pollForReceipt({
|
|
42943
|
+
syncUrl: params.syncUrl,
|
|
42944
|
+
motebitId: params.motebitId,
|
|
42945
|
+
taskId,
|
|
42946
|
+
queryHeader,
|
|
42947
|
+
timeoutMs,
|
|
42948
|
+
startedAt,
|
|
42949
|
+
logger: params.logger,
|
|
42950
|
+
...params.signal ? { signal: params.signal } : {}
|
|
42951
|
+
});
|
|
42952
|
+
if (result.ok) {
|
|
42953
|
+
const proof = params.paymentProof;
|
|
42954
|
+
return {
|
|
42955
|
+
...result,
|
|
42956
|
+
settlement: {
|
|
42957
|
+
mode: "p2p",
|
|
42958
|
+
txHash: proof.tx_hash,
|
|
42959
|
+
paidMicro: proof.amount_micro,
|
|
42960
|
+
feeMicro: proof.fee_amount_micro + (proof.b_fee_amount_micro ?? 0)
|
|
42961
|
+
}
|
|
42962
|
+
};
|
|
42963
|
+
}
|
|
42964
|
+
return result;
|
|
42965
|
+
}
|
|
42966
|
+
function hexToBytes7(hex) {
|
|
42967
|
+
const clean2 = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
42968
|
+
if (clean2.length === 0 || clean2.length % 2 !== 0 || /[^0-9a-fA-F]/.test(clean2)) {
|
|
42969
|
+
throw new Error(`invalid hex: ${hex.slice(0, 16)}\u2026`);
|
|
42970
|
+
}
|
|
42971
|
+
const out = new Uint8Array(clean2.length / 2);
|
|
42972
|
+
for (let i3 = 0; i3 < out.length; i3++) {
|
|
42973
|
+
out[i3] = Number.parseInt(clean2.slice(i3 * 2, i3 * 2 + 2), 16);
|
|
42974
|
+
}
|
|
42975
|
+
return out;
|
|
42976
|
+
}
|
|
42977
|
+
async function resolveP2pPaymentRequest(params) {
|
|
42978
|
+
const { syncUrl, capability, motebitId } = params;
|
|
42979
|
+
let treasuryAddress;
|
|
42980
|
+
try {
|
|
42981
|
+
treasuryAddress = base58Encode(hexToBytes7(params.relayPublicKeyHex));
|
|
42982
|
+
} catch (err2) {
|
|
42983
|
+
return fail("malformed_request", `Invalid pinned relay public key: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
42984
|
+
}
|
|
42985
|
+
let worker;
|
|
42986
|
+
try {
|
|
42987
|
+
const resp = await fetch(`${syncUrl}/api/v1/agents/discover?capability=${encodeURIComponent(capability)}`, { signal: params.signal });
|
|
42988
|
+
if (!resp.ok) {
|
|
42989
|
+
const text = await resp.text().catch(() => "");
|
|
42990
|
+
return {
|
|
42991
|
+
ok: false,
|
|
42992
|
+
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
42993
|
+
};
|
|
42994
|
+
}
|
|
42995
|
+
const data = await resp.json();
|
|
42996
|
+
const admissible = (data.agents ?? []).filter((a3) => {
|
|
42997
|
+
if (a3.motebit_id === motebitId || a3.settlement_address == null)
|
|
42998
|
+
return false;
|
|
42999
|
+
if (params.targetWorkerId != null && a3.motebit_id !== params.targetWorkerId)
|
|
43000
|
+
return false;
|
|
43001
|
+
const modes = Array.isArray(a3.settlement_modes) ? a3.settlement_modes : String(a3.settlement_modes ?? "").split(",");
|
|
43002
|
+
return modes.includes("p2p");
|
|
43003
|
+
});
|
|
43004
|
+
let candidate = admissible[0];
|
|
43005
|
+
if (params.targetWorkerId == null && params.selectWorker != null && admissible.length > 1) {
|
|
43006
|
+
const priceFor3 = (a3) => (a3.pricing ?? []).find((p5) => p5.capability === capability)?.unit_cost ?? (a3.pricing ?? [])[0]?.unit_cost ?? void 0;
|
|
43007
|
+
const chosenId = await params.selectWorker(admissible.map((a3) => {
|
|
43008
|
+
const unitCost = priceFor3(a3);
|
|
43009
|
+
return { motebit_id: a3.motebit_id, ...unitCost != null ? { unitCost } : {} };
|
|
43010
|
+
}));
|
|
43011
|
+
if (chosenId != null) {
|
|
43012
|
+
const chosen = admissible.find((a3) => a3.motebit_id === chosenId);
|
|
43013
|
+
if (chosen != null)
|
|
43014
|
+
candidate = chosen;
|
|
43015
|
+
}
|
|
43016
|
+
}
|
|
43017
|
+
if (candidate?.settlement_address == null) {
|
|
43018
|
+
return fail("no_routing", params.targetWorkerId != null ? `Pinned worker "${params.targetWorkerId}" is not P2P-eligible for "${capability}".` : `No P2P-capable worker advertises "${capability}".`);
|
|
43019
|
+
}
|
|
43020
|
+
worker = {
|
|
43021
|
+
motebit_id: candidate.motebit_id,
|
|
43022
|
+
settlement_address: candidate.settlement_address,
|
|
43023
|
+
...candidate.source_relay_public_key != null ? { sourceRelayPublicKey: candidate.source_relay_public_key } : {},
|
|
43024
|
+
pricing: candidate.pricing ?? null
|
|
43025
|
+
};
|
|
43026
|
+
} catch (err2) {
|
|
43027
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
43028
|
+
return fail("timeout", "Aborted during discovery");
|
|
43029
|
+
}
|
|
43030
|
+
return fail("network_unreachable", err2 instanceof Error ? err2.message : String(err2));
|
|
43031
|
+
}
|
|
43032
|
+
let paymentRequest;
|
|
43033
|
+
if (worker.sourceRelayPublicKey != null) {
|
|
43034
|
+
let executorTreasuryAddress;
|
|
43035
|
+
try {
|
|
43036
|
+
executorTreasuryAddress = base58Encode(hexToBytes7(worker.sourceRelayPublicKey));
|
|
43037
|
+
} catch (err2) {
|
|
43038
|
+
return fail("malformed_request", `Invalid peer relay public key in discovery: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
43039
|
+
}
|
|
43040
|
+
const priced = (worker.pricing ?? []).find((p5) => p5.capability === capability) ?? (worker.pricing ?? [])[0];
|
|
43041
|
+
if (priced?.unit_cost == null || priced.unit_cost <= 0) {
|
|
43042
|
+
return fail("worker_not_payable", `Remote worker has no positive price for "${capability}".`);
|
|
43043
|
+
}
|
|
43044
|
+
const budgetMicro = toMicro(priced.unit_cost);
|
|
43045
|
+
const split2 = computeFederatedFeeSplit(budgetMicro, PLATFORM_FEE_RATE);
|
|
43046
|
+
paymentRequest = {
|
|
43047
|
+
workerAddress: worker.settlement_address,
|
|
43048
|
+
amountMicro: split2.workerNetMicro,
|
|
43049
|
+
treasuryAddress,
|
|
43050
|
+
feeAmountMicro: split2.originFeeMicro,
|
|
43051
|
+
executorTreasuryAddress,
|
|
43052
|
+
executorFeeAmountMicro: split2.executorFeeMicro
|
|
43053
|
+
};
|
|
43054
|
+
} else {
|
|
43055
|
+
let preflightAllowed = false;
|
|
43056
|
+
try {
|
|
43057
|
+
const eligToken = await params.authToken("market:listing");
|
|
43058
|
+
const ackQuery = params.acknowledgeNoHistoryRisk === true ? "?acknowledge_no_history_risk=true" : "";
|
|
43059
|
+
const resp = await fetch(`${syncUrl}/api/v1/agents/${worker.motebit_id}/p2p-eligibility${ackQuery}`, { headers: { Authorization: `Bearer ${eligToken}` }, signal: params.signal });
|
|
43060
|
+
if (resp.ok) {
|
|
43061
|
+
const data = await resp.json();
|
|
43062
|
+
if (data.allowed !== true) {
|
|
43063
|
+
return fail("p2p_ineligible", data.reason ?? "Not P2P-eligible for this worker");
|
|
43064
|
+
}
|
|
43065
|
+
preflightAllowed = true;
|
|
43066
|
+
}
|
|
43067
|
+
} catch (err2) {
|
|
43068
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
43069
|
+
return fail("timeout", "Aborted during eligibility pre-flight");
|
|
43070
|
+
}
|
|
43071
|
+
}
|
|
43072
|
+
if (!preflightAllowed) {
|
|
43073
|
+
return fail("p2p_ineligible", "P2P eligibility could not be confirmed (pre-flight unavailable) \u2014 refusing to broadcast an unconfirmed payment.");
|
|
43074
|
+
}
|
|
43075
|
+
let unitCost;
|
|
43076
|
+
try {
|
|
43077
|
+
const listingToken = await params.authToken("market:listing");
|
|
43078
|
+
const resp = await fetch(`${syncUrl}/api/v1/agents/${worker.motebit_id}/listing`, {
|
|
43079
|
+
headers: { Authorization: `Bearer ${listingToken}` },
|
|
43080
|
+
signal: params.signal
|
|
43081
|
+
});
|
|
43082
|
+
if (resp.status === 404) {
|
|
43083
|
+
return fail("worker_not_payable", "Worker has no service listing.");
|
|
43084
|
+
}
|
|
43085
|
+
if (!resp.ok) {
|
|
43086
|
+
const text = await resp.text().catch(() => "");
|
|
43087
|
+
return {
|
|
43088
|
+
ok: false,
|
|
43089
|
+
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
43090
|
+
};
|
|
43091
|
+
}
|
|
43092
|
+
const data = await resp.json();
|
|
43093
|
+
const entry = (data.pricing ?? []).find((p5) => p5.capability === capability) ?? (data.pricing ?? [])[0];
|
|
43094
|
+
if (entry?.unit_cost == null || entry.unit_cost <= 0) {
|
|
43095
|
+
return fail("worker_not_payable", `Worker has no positive price for "${capability}".`);
|
|
43096
|
+
}
|
|
43097
|
+
unitCost = entry.unit_cost;
|
|
43098
|
+
} catch (err2) {
|
|
43099
|
+
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
43100
|
+
return fail("timeout", "Aborted during pricing");
|
|
43101
|
+
}
|
|
43102
|
+
return fail("network_unreachable", err2 instanceof Error ? err2.message : String(err2));
|
|
43103
|
+
}
|
|
43104
|
+
const amountMicro = toMicro(unitCost);
|
|
43105
|
+
paymentRequest = {
|
|
43106
|
+
workerAddress: worker.settlement_address,
|
|
43107
|
+
amountMicro,
|
|
43108
|
+
treasuryAddress,
|
|
43109
|
+
feeAmountMicro: computeP2pFeeMicro(amountMicro, PLATFORM_FEE_RATE)
|
|
43110
|
+
};
|
|
43111
|
+
}
|
|
43112
|
+
return {
|
|
43113
|
+
ok: true,
|
|
43114
|
+
paymentRequest,
|
|
43115
|
+
workerMotebitId: worker.motebit_id,
|
|
43116
|
+
workerAddress: worker.settlement_address
|
|
43117
|
+
};
|
|
43118
|
+
}
|
|
43119
|
+
async function resolveAndSubmitP2pDelegation(params) {
|
|
43120
|
+
if (params.buildP2pPayment == null) {
|
|
43121
|
+
return fail("no_sovereign_rail", "Paid direct delegation needs a sovereign wallet rail that can build an atomic payment.");
|
|
43122
|
+
}
|
|
43123
|
+
const resolved = await resolveP2pPaymentRequest({
|
|
43124
|
+
motebitId: params.motebitId,
|
|
43125
|
+
syncUrl: params.syncUrl,
|
|
43126
|
+
authToken: params.authToken,
|
|
43127
|
+
capability: params.capability,
|
|
43128
|
+
relayPublicKeyHex: params.relayPublicKeyHex,
|
|
43129
|
+
...params.targetWorkerId != null ? { targetWorkerId: params.targetWorkerId } : {},
|
|
43130
|
+
...params.selectWorker != null ? { selectWorker: params.selectWorker } : {},
|
|
43131
|
+
...params.acknowledgeNoHistoryRisk === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
43132
|
+
...params.signal ? { signal: params.signal } : {}
|
|
43133
|
+
});
|
|
43134
|
+
if (!resolved.ok)
|
|
43135
|
+
return { ok: false, error: resolved.error };
|
|
43136
|
+
let proof;
|
|
43137
|
+
try {
|
|
43138
|
+
proof = await params.buildP2pPayment(resolved.paymentRequest);
|
|
43139
|
+
} catch (err2) {
|
|
43140
|
+
if (err2 instanceof Error && err2.name === "MoneyMeterDeniedError") {
|
|
43141
|
+
const denial = err2.denial;
|
|
43142
|
+
return {
|
|
43143
|
+
ok: false,
|
|
43144
|
+
error: {
|
|
43145
|
+
code: "money_meter_denied",
|
|
43146
|
+
message: err2.message,
|
|
43147
|
+
...denial != null ? { denial } : {}
|
|
43148
|
+
}
|
|
43149
|
+
};
|
|
43150
|
+
}
|
|
43151
|
+
if (err2 instanceof Error && err2.name === "InsufficientUsdcBalanceError") {
|
|
43152
|
+
return fail("insufficient_balance", err2.message);
|
|
43153
|
+
}
|
|
43154
|
+
return fail("payment_broadcast_failed", `P2P payment failed to broadcast: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
43155
|
+
}
|
|
43156
|
+
return submitP2pDelegation({
|
|
43157
|
+
motebitId: params.motebitId,
|
|
43158
|
+
syncUrl: params.syncUrl,
|
|
43159
|
+
authToken: params.authToken,
|
|
43160
|
+
prompt: params.prompt,
|
|
43161
|
+
targetWorkerId: resolved.workerMotebitId,
|
|
43162
|
+
// The relay needs the capability to locate + price a federated worker on its
|
|
43163
|
+
// operator; pinned via the same capability used for discovery.
|
|
43164
|
+
requiredCapabilities: [params.capability],
|
|
43165
|
+
...params.acknowledgeNoHistoryRisk === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
43166
|
+
paymentProof: proof,
|
|
43167
|
+
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
43168
|
+
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
43169
|
+
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
43170
|
+
logger: params.logger,
|
|
43171
|
+
...params.signal ? { signal: params.signal } : {}
|
|
43172
|
+
});
|
|
43173
|
+
}
|
|
43174
|
+
async function selectAndRunDelegation(params) {
|
|
43175
|
+
const capability = params.requiredCapabilities?.[0];
|
|
43176
|
+
if (params.targetWorkerId != null) {
|
|
43177
|
+
if (capability == null) {
|
|
43178
|
+
return fail("malformed_request", "A pinned hire requires a capability to discover the worker by.");
|
|
43179
|
+
}
|
|
43180
|
+
if (params.buildP2pPayment == null || params.relayPublicKey == null) {
|
|
43181
|
+
return fail("no_sovereign_rail", "Hiring a specific agent settles peer-to-peer and needs a configured sovereign wallet rail.");
|
|
43182
|
+
}
|
|
43183
|
+
}
|
|
43184
|
+
if (params.buildP2pPayment != null && params.relayPublicKey != null && capability != null) {
|
|
43185
|
+
const p2p = await resolveAndSubmitP2pDelegation({
|
|
43186
|
+
motebitId: params.motebitId,
|
|
43187
|
+
syncUrl: params.syncUrl,
|
|
43188
|
+
authToken: params.authToken,
|
|
43189
|
+
prompt: params.prompt,
|
|
43190
|
+
capability,
|
|
43191
|
+
...params.targetWorkerId != null ? { targetWorkerId: params.targetWorkerId } : {},
|
|
43192
|
+
relayPublicKeyHex: params.relayPublicKey,
|
|
43193
|
+
buildP2pPayment: params.buildP2pPayment,
|
|
43194
|
+
...params.acknowledgeNoHistoryRisk === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
43195
|
+
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
43196
|
+
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
43197
|
+
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
43198
|
+
logger: params.logger,
|
|
43199
|
+
...params.signal ? { signal: params.signal } : {}
|
|
43200
|
+
});
|
|
43201
|
+
if (p2p.ok)
|
|
43202
|
+
return p2p;
|
|
43203
|
+
if (params.targetWorkerId != null)
|
|
43204
|
+
return p2p;
|
|
43205
|
+
if (p2p.error.code !== "no_routing" && p2p.error.code !== "worker_not_payable" && p2p.error.code !== "p2p_ineligible") {
|
|
43206
|
+
return p2p;
|
|
43207
|
+
}
|
|
43208
|
+
}
|
|
43209
|
+
return submitAndPollDelegation({
|
|
43210
|
+
motebitId: params.motebitId,
|
|
43211
|
+
syncUrl: params.syncUrl,
|
|
43212
|
+
authToken: params.authToken,
|
|
43213
|
+
prompt: params.prompt,
|
|
43214
|
+
...params.requiredCapabilities ? { requiredCapabilities: params.requiredCapabilities } : {},
|
|
43215
|
+
...params.routingStrategy ? { routingStrategy: params.routingStrategy } : {},
|
|
43216
|
+
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
43217
|
+
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
43218
|
+
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
43219
|
+
logger: params.logger,
|
|
43220
|
+
...params.signal ? { signal: params.signal } : {}
|
|
43221
|
+
});
|
|
43222
|
+
}
|
|
43223
|
+
var DEFAULT_TIMEOUT_MS, POLL_INTERVAL_MS, fail;
|
|
43224
|
+
var init_relay_delegation = __esm({
|
|
43225
|
+
"../../packages/runtime/dist/relay-delegation.js"() {
|
|
43226
|
+
"use strict";
|
|
43227
|
+
init_esm_shims();
|
|
43228
|
+
init_dist();
|
|
43229
|
+
DEFAULT_TIMEOUT_MS = 12e4;
|
|
43230
|
+
POLL_INTERVAL_MS = 2e3;
|
|
43231
|
+
fail = (code2, message2, status) => ({
|
|
43232
|
+
ok: false,
|
|
43233
|
+
error: status != null ? { code: code2, message: message2, status } : { code: code2, message: message2 }
|
|
43234
|
+
});
|
|
43235
|
+
}
|
|
43236
|
+
});
|
|
43237
|
+
|
|
43238
|
+
// ../../packages/runtime/dist/secret-redacting-provider.js
|
|
43239
|
+
function redactPackForCloudEgress(pack, redact) {
|
|
43240
|
+
let redactedCount = 0;
|
|
43241
|
+
const labels = /* @__PURE__ */ new Set();
|
|
43242
|
+
const apply = (text) => {
|
|
43243
|
+
const r2 = redact(text);
|
|
43244
|
+
redactedCount += r2.redactionCount;
|
|
43245
|
+
for (const l6 of r2.labels)
|
|
43246
|
+
labels.add(l6);
|
|
43247
|
+
return r2.text;
|
|
43248
|
+
};
|
|
43249
|
+
const newPack = {
|
|
43250
|
+
...pack,
|
|
43251
|
+
user_message: apply(pack.user_message),
|
|
43252
|
+
...pack.conversation_history !== void 0 ? {
|
|
43253
|
+
conversation_history: pack.conversation_history.map((m3) => m3.role === "user" ? { ...m3, content: apply(m3.content) } : m3)
|
|
43254
|
+
} : {}
|
|
43255
|
+
};
|
|
43256
|
+
return { pack: newPack, redactedCount, labels: [...labels] };
|
|
43257
|
+
}
|
|
43258
|
+
var SecretRedactingProvider;
|
|
43259
|
+
var init_secret_redacting_provider = __esm({
|
|
43260
|
+
"../../packages/runtime/dist/secret-redacting-provider.js"() {
|
|
43261
|
+
"use strict";
|
|
43262
|
+
init_esm_shims();
|
|
43263
|
+
SecretRedactingProvider = class {
|
|
43264
|
+
inner;
|
|
43265
|
+
opts;
|
|
43266
|
+
constructor(inner, opts) {
|
|
43267
|
+
this.inner = inner;
|
|
43268
|
+
this.opts = opts;
|
|
43269
|
+
}
|
|
43270
|
+
/** Redact the outbound pack unless the provider is sovereign (on-device). */
|
|
43271
|
+
packFor(pack) {
|
|
43272
|
+
if (this.opts.isSovereign())
|
|
43273
|
+
return pack;
|
|
43274
|
+
const { pack: redacted, redactedCount, labels } = redactPackForCloudEgress(pack, this.opts.redact);
|
|
43275
|
+
if (redactedCount > 0)
|
|
43276
|
+
this.opts.onRedacted?.({ count: redactedCount, labels });
|
|
43277
|
+
return redacted;
|
|
43278
|
+
}
|
|
43279
|
+
get model() {
|
|
43280
|
+
return this.inner.model;
|
|
43281
|
+
}
|
|
43282
|
+
get temperature() {
|
|
43283
|
+
return this.inner.temperature;
|
|
43284
|
+
}
|
|
43285
|
+
get maxTokens() {
|
|
43286
|
+
return this.inner.maxTokens;
|
|
43287
|
+
}
|
|
43288
|
+
setModel(model) {
|
|
43289
|
+
this.inner.setModel(model);
|
|
43290
|
+
}
|
|
43291
|
+
setTemperature(temperature) {
|
|
43292
|
+
this.inner.setTemperature?.(temperature);
|
|
43293
|
+
}
|
|
43294
|
+
setMaxTokens(maxTokens) {
|
|
43295
|
+
this.inner.setMaxTokens?.(maxTokens);
|
|
43296
|
+
}
|
|
43297
|
+
generate(pack) {
|
|
43298
|
+
return this.inner.generate(this.packFor(pack));
|
|
43299
|
+
}
|
|
43300
|
+
generateStream(pack) {
|
|
43301
|
+
return this.inner.generateStream(this.packFor(pack));
|
|
43302
|
+
}
|
|
43303
|
+
estimateConfidence() {
|
|
43304
|
+
return this.inner.estimateConfidence();
|
|
43305
|
+
}
|
|
43306
|
+
extractMemoryCandidates(response) {
|
|
43307
|
+
return this.inner.extractMemoryCandidates(response);
|
|
43308
|
+
}
|
|
43309
|
+
};
|
|
43310
|
+
}
|
|
43311
|
+
});
|
|
43312
|
+
|
|
43313
|
+
// ../../packages/runtime/dist/credential-manager.js
|
|
43314
|
+
var CredentialManager;
|
|
43315
|
+
var init_credential_manager = __esm({
|
|
43316
|
+
"../../packages/runtime/dist/credential-manager.js"() {
|
|
43317
|
+
"use strict";
|
|
43318
|
+
init_esm_shims();
|
|
43319
|
+
init_dist6();
|
|
43320
|
+
CredentialManager = class {
|
|
43321
|
+
deps;
|
|
43322
|
+
_issuedCredentials = [];
|
|
43323
|
+
changeListeners = /* @__PURE__ */ new Set();
|
|
43324
|
+
/** Callback to submit credentials to relay for indexing. Set externally (e.g. by enableInteractiveDelegation). */
|
|
43325
|
+
credentialSubmitter = null;
|
|
43326
|
+
constructor(deps) {
|
|
43327
|
+
this.deps = deps;
|
|
43328
|
+
}
|
|
43329
|
+
/**
|
|
43330
|
+
* Subscribe to credential-set changes (fires after each `persistCredential`).
|
|
43331
|
+
* Returns an unsubscribe function. Used by surfaces that render credentials
|
|
43332
|
+
* as scene objects (satellites) so they don't have to poll.
|
|
43333
|
+
*/
|
|
43334
|
+
onChange(fn) {
|
|
43335
|
+
this.changeListeners.add(fn);
|
|
43336
|
+
return () => {
|
|
43337
|
+
this.changeListeners.delete(fn);
|
|
43338
|
+
};
|
|
43339
|
+
}
|
|
43340
|
+
/**
|
|
43341
|
+
* Issue a W3C Verifiable Credential containing this agent's current gradient.
|
|
43342
|
+
* Returns null if no gradient has been computed or no private key is available.
|
|
43343
|
+
*/
|
|
43344
|
+
async issueGradientCredential(privateKey, publicKey) {
|
|
43345
|
+
const snapshot = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
43346
|
+
if (!snapshot)
|
|
43347
|
+
return null;
|
|
43348
|
+
return issueGradientCredential(snapshot, privateKey, publicKey);
|
|
43349
|
+
}
|
|
43350
|
+
/**
|
|
43351
|
+
* Return all verifiable credentials issued by this runtime (gradient + trust).
|
|
43352
|
+
* Credentials accumulate in memory; consumers can read and clear as needed.
|
|
43353
|
+
*/
|
|
43354
|
+
getIssuedCredentials() {
|
|
43355
|
+
return [...this._issuedCredentials];
|
|
43356
|
+
}
|
|
43357
|
+
/**
|
|
43358
|
+
* Clear the in-memory credential cache (e.g. after persisting or presenting them).
|
|
43359
|
+
*/
|
|
43360
|
+
clearIssuedCredentials() {
|
|
43361
|
+
this._issuedCredentials = [];
|
|
43362
|
+
}
|
|
43363
|
+
/** Push a credential to both in-memory cache and persistent store. */
|
|
43364
|
+
persistCredential(vc, subjectMotebitId) {
|
|
43365
|
+
this._issuedCredentials.push(vc);
|
|
43366
|
+
if (this.deps.credentialStore) {
|
|
43367
|
+
try {
|
|
43368
|
+
const credType = vc.type.find((t3) => t3 !== "VerifiableCredential") ?? "VerifiableCredential";
|
|
43369
|
+
this.deps.credentialStore.save({
|
|
43370
|
+
credential_id: crypto.randomUUID(),
|
|
43371
|
+
subject_motebit_id: vc.credentialSubject?.id ?? "",
|
|
43372
|
+
issuer_did: vc.issuer,
|
|
43373
|
+
credential_type: credType,
|
|
43374
|
+
credential_json: JSON.stringify(vc),
|
|
43375
|
+
issued_at: Date.now()
|
|
43376
|
+
});
|
|
43377
|
+
} catch (err2) {
|
|
43378
|
+
this.deps.logger.warn("credential persistence failed", {
|
|
43379
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
43380
|
+
});
|
|
43381
|
+
}
|
|
43382
|
+
}
|
|
43383
|
+
if (this.credentialSubmitter && subjectMotebitId) {
|
|
43384
|
+
this.credentialSubmitter(vc, subjectMotebitId).catch((err2) => {
|
|
43385
|
+
this.deps.logger.warn("credential relay submission failed", {
|
|
43386
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
43387
|
+
});
|
|
43388
|
+
});
|
|
43389
|
+
}
|
|
43390
|
+
for (const listener of this.changeListeners) {
|
|
43391
|
+
try {
|
|
43392
|
+
listener();
|
|
43393
|
+
} catch (err2) {
|
|
43394
|
+
this.deps.logger.warn("credential change listener threw", {
|
|
43395
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
43396
|
+
});
|
|
43397
|
+
}
|
|
43398
|
+
}
|
|
43399
|
+
}
|
|
43400
|
+
};
|
|
43401
|
+
}
|
|
43402
|
+
});
|
|
43403
|
+
|
|
43404
|
+
// ../../packages/runtime/dist/hardware-attestation-projection.js
|
|
43405
|
+
function readLatestHardwareAttestationClaim(store, record) {
|
|
43406
|
+
const candidates = [];
|
|
43407
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43408
|
+
const collect = (subjectKey) => {
|
|
43409
|
+
let rows;
|
|
43410
|
+
try {
|
|
43411
|
+
rows = store.listBySubject(subjectKey);
|
|
43412
|
+
} catch {
|
|
43413
|
+
return;
|
|
43414
|
+
}
|
|
43415
|
+
for (const row of rows) {
|
|
43416
|
+
if (row.credential_type !== TRUST_VC_TYPE)
|
|
43417
|
+
continue;
|
|
43418
|
+
if (seen.has(row.credential_id))
|
|
43419
|
+
continue;
|
|
43420
|
+
seen.add(row.credential_id);
|
|
43421
|
+
candidates.push(row);
|
|
43422
|
+
}
|
|
43423
|
+
};
|
|
43424
|
+
if (record.public_key != null && record.public_key !== "") {
|
|
43425
|
+
try {
|
|
43426
|
+
collect(hexPublicKeyToDidKey(record.public_key));
|
|
43427
|
+
} catch {
|
|
43428
|
+
}
|
|
43429
|
+
}
|
|
43430
|
+
collect(`did:motebit:${record.remote_motebit_id}`);
|
|
43431
|
+
if (candidates.length === 0)
|
|
43432
|
+
return null;
|
|
43433
|
+
candidates.sort((a3, b3) => b3.issued_at - a3.issued_at);
|
|
43434
|
+
for (const row of candidates) {
|
|
43435
|
+
let parsed;
|
|
43436
|
+
try {
|
|
43437
|
+
parsed = JSON.parse(row.credential_json);
|
|
43438
|
+
} catch {
|
|
43439
|
+
continue;
|
|
43440
|
+
}
|
|
43441
|
+
const claim = parsed.credentialSubject?.hardware_attestation;
|
|
43442
|
+
if (claim != null) {
|
|
43443
|
+
return {
|
|
43444
|
+
platform: claim.platform,
|
|
43445
|
+
key_exported: claim.key_exported,
|
|
43446
|
+
score: scoreAttestation(claim)
|
|
43447
|
+
};
|
|
43448
|
+
}
|
|
43449
|
+
}
|
|
43450
|
+
return null;
|
|
43451
|
+
}
|
|
43452
|
+
var TRUST_VC_TYPE;
|
|
43453
|
+
var init_hardware_attestation_projection = __esm({
|
|
43454
|
+
"../../packages/runtime/dist/hardware-attestation-projection.js"() {
|
|
43455
|
+
"use strict";
|
|
43456
|
+
init_esm_shims();
|
|
43457
|
+
init_dist6();
|
|
43458
|
+
init_dist14();
|
|
43459
|
+
TRUST_VC_TYPE = "AgentTrustCredential";
|
|
43460
|
+
}
|
|
43461
|
+
});
|
|
43462
|
+
|
|
43463
|
+
// ../../packages/runtime/dist/latency-stats-projection.js
|
|
43464
|
+
async function readLatencyStats(store, motebitId, record) {
|
|
43465
|
+
let stats;
|
|
43466
|
+
try {
|
|
43467
|
+
stats = await store.getStats(motebitId, record.remote_motebit_id);
|
|
43468
|
+
} catch {
|
|
43469
|
+
return null;
|
|
43470
|
+
}
|
|
43471
|
+
if (stats.sample_count === 0)
|
|
43472
|
+
return null;
|
|
43473
|
+
return {
|
|
43474
|
+
avg_ms: stats.avg_ms,
|
|
43475
|
+
p95_ms: stats.p95_ms,
|
|
43476
|
+
sample_count: stats.sample_count
|
|
43477
|
+
};
|
|
43478
|
+
}
|
|
43479
|
+
var init_latency_stats_projection = __esm({
|
|
43480
|
+
"../../packages/runtime/dist/latency-stats-projection.js"() {
|
|
43481
|
+
"use strict";
|
|
43482
|
+
init_esm_shims();
|
|
43483
|
+
}
|
|
43484
|
+
});
|
|
43485
|
+
|
|
43486
|
+
// ../../packages/runtime/dist/plan-execution.js
|
|
43487
|
+
var PlanExecutionManager;
|
|
43488
|
+
var init_plan_execution = __esm({
|
|
43489
|
+
"../../packages/runtime/dist/plan-execution.js"() {
|
|
43490
|
+
"use strict";
|
|
43491
|
+
init_esm_shims();
|
|
43492
|
+
init_dist2();
|
|
43493
|
+
init_dist6();
|
|
43494
|
+
init_execution_ledger();
|
|
43495
|
+
PlanExecutionManager = class {
|
|
43496
|
+
deps;
|
|
43497
|
+
_lastExecutionManifest = null;
|
|
43498
|
+
_stepStates = /* @__PURE__ */ new Map();
|
|
43499
|
+
/**
|
|
43500
|
+
* Per-step delegation `task_id`, remembered on `step_delegated` so the
|
|
42789
43501
|
* subsequent terminal event can include it in its payload (spec §3.7).
|
|
42790
43502
|
* Receivers join the delegation chain payload-directly instead of
|
|
42791
43503
|
* reconstructing it by scanning sibling events.
|
|
@@ -43342,7 +44054,28 @@ var init_operator = __esm({
|
|
|
43342
44054
|
});
|
|
43343
44055
|
|
|
43344
44056
|
// ../../packages/runtime/dist/agent-trust.js
|
|
43345
|
-
|
|
44057
|
+
function resolveTaskCapability(explicit, receipt) {
|
|
44058
|
+
if (explicit != null && explicit !== "" && explicit !== "*")
|
|
44059
|
+
return explicit;
|
|
44060
|
+
const scope = receipt.delegated_scope;
|
|
44061
|
+
if (scope == null || scope === "" || scope === "*")
|
|
44062
|
+
return void 0;
|
|
44063
|
+
const parts = scope.split(",").map((s3) => s3.trim()).filter(Boolean);
|
|
44064
|
+
return parts.length === 1 ? parts[0] : void 0;
|
|
44065
|
+
}
|
|
44066
|
+
function bumpCapabilityStats(existing, capability, effectiveSuccess, effectiveFailure) {
|
|
44067
|
+
if (capability == null)
|
|
44068
|
+
return existing;
|
|
44069
|
+
const prev = existing?.[capability] ?? { successful_tasks: 0, failed_tasks: 0 };
|
|
44070
|
+
return {
|
|
44071
|
+
...existing ?? {},
|
|
44072
|
+
[capability]: {
|
|
44073
|
+
successful_tasks: prev.successful_tasks + (effectiveSuccess ? 1 : 0),
|
|
44074
|
+
failed_tasks: prev.failed_tasks + (effectiveFailure ? 1 : 0)
|
|
44075
|
+
}
|
|
44076
|
+
};
|
|
44077
|
+
}
|
|
44078
|
+
async function bumpTrustFromReceipt(deps, receipt, verified, capability) {
|
|
43346
44079
|
const { motebitId, agentTrustStore, events, agentGraph, signingKeys, onCredentialIssued, getRemoteHardwareAttestations, hardwareAttestationVerifiers } = deps;
|
|
43347
44080
|
if (agentTrustStore == null)
|
|
43348
44081
|
return;
|
|
@@ -43364,10 +44097,12 @@ async function bumpTrustFromReceipt(deps, receipt, verified) {
|
|
|
43364
44097
|
}
|
|
43365
44098
|
const effectiveSuccess = taskSucceeded && resultQuality >= 0.2;
|
|
43366
44099
|
const effectiveFailure = taskFailed || taskSucceeded && resultQuality < 0.2;
|
|
44100
|
+
const taskCapability = resolveTaskCapability(capability, receipt);
|
|
43367
44101
|
if (existing != null) {
|
|
43368
44102
|
const alpha = 0.3;
|
|
43369
44103
|
const prevQuality = existing.avg_quality ?? 1;
|
|
43370
44104
|
const newQuality = alpha * resultQuality + (1 - alpha) * prevQuality;
|
|
44105
|
+
const nextCapabilityStats = bumpCapabilityStats(existing.capability_stats, taskCapability, effectiveSuccess, effectiveFailure);
|
|
43371
44106
|
const updated = {
|
|
43372
44107
|
...existing,
|
|
43373
44108
|
last_seen_at: now,
|
|
@@ -43375,7 +44110,8 @@ async function bumpTrustFromReceipt(deps, receipt, verified) {
|
|
|
43375
44110
|
successful_tasks: (existing.successful_tasks ?? 0) + (effectiveSuccess ? 1 : 0),
|
|
43376
44111
|
failed_tasks: (existing.failed_tasks ?? 0) + (effectiveFailure ? 1 : 0),
|
|
43377
44112
|
avg_quality: newQuality,
|
|
43378
|
-
quality_sample_count: (existing.quality_sample_count ?? 0) + 1
|
|
44113
|
+
quality_sample_count: (existing.quality_sample_count ?? 0) + 1,
|
|
44114
|
+
...nextCapabilityStats != null ? { capability_stats: nextCapabilityStats } : {}
|
|
43379
44115
|
};
|
|
43380
44116
|
const newLevel = evaluateTrustTransition(updated);
|
|
43381
44117
|
if (newLevel != null) {
|
|
@@ -43483,6 +44219,7 @@ async function bumpTrustFromReceipt(deps, receipt, verified) {
|
|
|
43483
44219
|
}
|
|
43484
44220
|
}
|
|
43485
44221
|
} else {
|
|
44222
|
+
const firstCapabilityStats = bumpCapabilityStats(void 0, taskCapability, effectiveSuccess, effectiveFailure);
|
|
43486
44223
|
const record = {
|
|
43487
44224
|
motebit_id: motebitId,
|
|
43488
44225
|
remote_motebit_id: remoteMotebitId,
|
|
@@ -43493,7 +44230,8 @@ async function bumpTrustFromReceipt(deps, receipt, verified) {
|
|
|
43493
44230
|
successful_tasks: effectiveSuccess ? 1 : 0,
|
|
43494
44231
|
failed_tasks: effectiveFailure ? 1 : 0,
|
|
43495
44232
|
avg_quality: resultQuality,
|
|
43496
|
-
quality_sample_count: 1
|
|
44233
|
+
quality_sample_count: 1,
|
|
44234
|
+
...firstCapabilityStats != null ? { capability_stats: firstCapabilityStats } : {}
|
|
43497
44235
|
};
|
|
43498
44236
|
await agentTrustStore.setAgentTrust(record);
|
|
43499
44237
|
agentGraph.invalidate();
|
|
@@ -52745,910 +53483,402 @@ ${snippet}`;
|
|
|
52745
53483
|
// --- Layer-3 conversation search ---
|
|
52746
53484
|
/**
|
|
52747
53485
|
* BM25 search over every persisted message for this motebit. Used by
|
|
52748
|
-
* the `search_conversations` tool — the Layer-3 transcript retrieval
|
|
52749
|
-
* that complements Layer-1 (memory index) and Layer-2
|
|
52750
|
-
* (`recall_memories` embedding search). Returns ranked hits with
|
|
52751
|
-
* conversation id, timestamp, and a short snippet around the first
|
|
52752
|
-
* matching token.
|
|
52753
|
-
*
|
|
52754
|
-
* Uses only the sync ConversationStoreAdapter surface, so callers
|
|
52755
|
-
* with IDB-backed stores MUST preload message caches (e.g.
|
|
52756
|
-
* `preloadAllMessages` on web) before invoking. The default for
|
|
52757
|
-
* CLI/desktop/mobile with SQLite is sync all the way down and needs
|
|
52758
|
-
* no preload.
|
|
52759
|
-
*/
|
|
52760
|
-
searchHistory(query, limit = 5) {
|
|
52761
|
-
const { store } = this.deps;
|
|
52762
|
-
if (store == null)
|
|
52763
|
-
return [];
|
|
52764
|
-
const convos = store.listConversations(this.deps.motebitId);
|
|
52765
|
-
const messages = [];
|
|
52766
|
-
for (const c3 of convos) {
|
|
52767
|
-
const msgs = store.loadMessages(c3.conversationId);
|
|
52768
|
-
for (const m3 of msgs) {
|
|
52769
|
-
if (m3.role !== "user" && m3.role !== "assistant")
|
|
52770
|
-
continue;
|
|
52771
|
-
messages.push({
|
|
52772
|
-
conversationId: c3.conversationId,
|
|
52773
|
-
role: m3.role,
|
|
52774
|
-
content: m3.content,
|
|
52775
|
-
createdAt: m3.createdAt
|
|
52776
|
-
});
|
|
52777
|
-
}
|
|
52778
|
-
}
|
|
52779
|
-
return searchConversationMessages(messages, query, { limit });
|
|
52780
|
-
}
|
|
52781
|
-
/**
|
|
52782
|
-
* Heuristic-title every stored conversation whose title is currently
|
|
52783
|
-
* null or empty. Idempotent: conversations with existing titles are
|
|
52784
|
-
* skipped. Uses only the synchronous store API, so the caller is
|
|
52785
|
-
* responsible for preloading message caches if the adapter is
|
|
52786
|
-
* IDB-backed (web/mobile). Returns the count of conversations
|
|
52787
|
-
* titled.
|
|
52788
|
-
*
|
|
52789
|
-
* Shipped to close out the prior autoTitle regression: conversations
|
|
52790
|
-
* created before the AI-path hang was fixed carry `title: null`
|
|
52791
|
-
* forever. This pass gives them a legible heuristic title on next
|
|
52792
|
-
* app start without round-tripping the AI.
|
|
52793
|
-
*/
|
|
52794
|
-
backfillMissingTitles() {
|
|
52795
|
-
const { store } = this.deps;
|
|
52796
|
-
if (store == null)
|
|
52797
|
-
return 0;
|
|
52798
|
-
const convos = store.listConversations(this.deps.motebitId);
|
|
52799
|
-
let fixed = 0;
|
|
52800
|
-
for (const c3 of convos) {
|
|
52801
|
-
if (c3.title != null && c3.title !== "")
|
|
52802
|
-
continue;
|
|
52803
|
-
const messages = store.loadMessages(c3.conversationId);
|
|
52804
|
-
const history = [];
|
|
52805
|
-
for (const m3 of messages) {
|
|
52806
|
-
if (m3.role === "user" || m3.role === "assistant") {
|
|
52807
|
-
history.push({ role: m3.role, content: m3.content });
|
|
52808
|
-
}
|
|
52809
|
-
}
|
|
52810
|
-
const title = deriveHeuristicTitle(history);
|
|
52811
|
-
if (title != null) {
|
|
52812
|
-
store.updateTitle(c3.conversationId, title);
|
|
52813
|
-
fixed += 1;
|
|
52814
|
-
}
|
|
52815
|
-
}
|
|
52816
|
-
return fixed;
|
|
52817
|
-
}
|
|
52818
|
-
// --- Task isolation ---
|
|
52819
|
-
/** Save conversation state for isolated task execution. */
|
|
52820
|
-
saveContext() {
|
|
52821
|
-
return { history: [...this.history], id: this.currentId };
|
|
52822
|
-
}
|
|
52823
|
-
/** Restore conversation state after isolated task execution. */
|
|
52824
|
-
restoreContext(ctx) {
|
|
52825
|
-
this.history = ctx.history;
|
|
52826
|
-
this.currentId = ctx.id;
|
|
52827
|
-
}
|
|
52828
|
-
/** Clear conversation for isolated execution (task context). */
|
|
52829
|
-
clearForTask() {
|
|
52830
|
-
this.history = [];
|
|
52831
|
-
this.currentId = null;
|
|
52832
|
-
}
|
|
52833
|
-
// --- Agentic loop support ---
|
|
52834
|
-
/**
|
|
52835
|
-
* Inject intermediate messages into the live history (e.g. tool call/result
|
|
52836
|
-
* pairs during the agentic loop). These are part of the context window for
|
|
52837
|
-
* continuation turns but are not individually persisted as conversation
|
|
52838
|
-
* messages — only the final user/assistant exchange is persisted via
|
|
52839
|
-
* pushExchange().
|
|
52840
|
-
*/
|
|
52841
|
-
injectIntermediateMessages(...messages) {
|
|
52842
|
-
this.history.push(...messages);
|
|
52843
|
-
}
|
|
52844
|
-
/** Return the raw live history reference for continuation turns. */
|
|
52845
|
-
get liveHistory() {
|
|
52846
|
-
return this.history;
|
|
52847
|
-
}
|
|
52848
|
-
// --- Internal helpers ---
|
|
52849
|
-
/** Get stored summary for the current conversation. */
|
|
52850
|
-
getStoredSummary() {
|
|
52851
|
-
const { store } = this.deps;
|
|
52852
|
-
if (this.currentId == null || this.currentId === "" || store == null)
|
|
52853
|
-
return null;
|
|
52854
|
-
return store.getActiveConversation(this.deps.motebitId)?.summary ?? null;
|
|
52855
|
-
}
|
|
52856
|
-
async runSummarization() {
|
|
52857
|
-
const provider = this.deps.getProvider();
|
|
52858
|
-
const { store } = this.deps;
|
|
52859
|
-
if (provider == null || store == null || this.currentId == null || this.currentId === "")
|
|
52860
|
-
return;
|
|
52861
|
-
try {
|
|
52862
|
-
const existingSummary = this.getStoredSummary();
|
|
52863
|
-
const clearedProvider = projectProviderClearance(this.deps.assertSensitivityPermitsAiCall("summarizeConversation"));
|
|
52864
|
-
const summary = await summarizeConversation(this.history, existingSummary, clearedProvider, this.deps.getTaskRouter() ?? void 0);
|
|
52865
|
-
if (summary && this.currentId) {
|
|
52866
|
-
store.updateSummary(this.currentId, summary);
|
|
52867
|
-
}
|
|
52868
|
-
} catch {
|
|
52869
|
-
}
|
|
52870
|
-
}
|
|
52871
|
-
};
|
|
52872
|
-
}
|
|
52873
|
-
});
|
|
52874
|
-
|
|
52875
|
-
// ../../packages/runtime/dist/gradient-manager.js
|
|
52876
|
-
var GradientManager;
|
|
52877
|
-
var init_gradient_manager = __esm({
|
|
52878
|
-
"../../packages/runtime/dist/gradient-manager.js"() {
|
|
52879
|
-
"use strict";
|
|
52880
|
-
init_esm_shims();
|
|
52881
|
-
init_dist2();
|
|
52882
|
-
init_gradient();
|
|
52883
|
-
GradientManager = class {
|
|
52884
|
-
deps;
|
|
52885
|
-
_behavioralStats = {
|
|
52886
|
-
turnCount: 0,
|
|
52887
|
-
totalIterations: 0,
|
|
52888
|
-
toolCallsSucceeded: 0,
|
|
52889
|
-
toolCallsBlocked: 0,
|
|
52890
|
-
toolCallsFailed: 0
|
|
52891
|
-
};
|
|
52892
|
-
_precision;
|
|
52893
|
-
_curiosityTargets = [];
|
|
52894
|
-
_lastReflection = null;
|
|
52895
|
-
constructor(deps) {
|
|
52896
|
-
this.deps = deps;
|
|
52897
|
-
this._precision = NEUTRAL_PRECISION;
|
|
52898
|
-
}
|
|
52899
|
-
// --- Bootstrap ---
|
|
52900
|
-
/** Apply accumulated intelligence baseline on startup. */
|
|
52901
|
-
applyStartupBaseline() {
|
|
52902
|
-
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
52903
|
-
if (latest) {
|
|
52904
|
-
this._precision = computePrecision(latest);
|
|
52905
|
-
this.deps.state.pushUpdate(computeStateBaseline(latest, this._precision));
|
|
52906
|
-
}
|
|
52907
|
-
}
|
|
52908
|
-
// --- Accessors ---
|
|
52909
|
-
/** Get the latest gradient snapshot, or null if none computed yet. */
|
|
52910
|
-
getGradient() {
|
|
52911
|
-
return this.deps.gradientStore.latest(this.deps.motebitId);
|
|
52912
|
-
}
|
|
52913
|
-
/** Get current active inference precision weights. */
|
|
52914
|
-
getPrecision() {
|
|
52915
|
-
return this._precision;
|
|
52916
|
-
}
|
|
52917
|
-
/** Get gradient history (most recent first). */
|
|
52918
|
-
getGradientHistory(limit) {
|
|
52919
|
-
return this.deps.gradientStore.list(this.deps.motebitId, limit);
|
|
52920
|
-
}
|
|
52921
|
-
/** Get gradient-informed market config for delegation routing. */
|
|
52922
|
-
getMarketConfig() {
|
|
52923
|
-
const snapshot = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
52924
|
-
if (!snapshot)
|
|
52925
|
-
return void 0;
|
|
52926
|
-
return gradientToMarketConfig(snapshot);
|
|
52927
|
-
}
|
|
52928
|
-
/** Self-model: the agent narrates its own trajectory from gradient history. */
|
|
52929
|
-
getGradientSummary(limit = 20) {
|
|
52930
|
-
const history = this.deps.gradientStore.list(this.deps.motebitId, limit);
|
|
52931
|
-
return summarizeGradientHistory(history);
|
|
52932
|
-
}
|
|
52933
|
-
/** Return accumulated behavioral stats and reset the accumulator. */
|
|
52934
|
-
getAndResetBehavioralStats() {
|
|
52935
|
-
const stats = { ...this._behavioralStats };
|
|
52936
|
-
this._behavioralStats = {
|
|
52937
|
-
turnCount: 0,
|
|
52938
|
-
totalIterations: 0,
|
|
52939
|
-
toolCallsSucceeded: 0,
|
|
52940
|
-
toolCallsBlocked: 0,
|
|
52941
|
-
toolCallsFailed: 0
|
|
52942
|
-
};
|
|
52943
|
-
return stats;
|
|
52944
|
-
}
|
|
52945
|
-
/** Return the cached reflection from the last session (or null if none). */
|
|
52946
|
-
getLastReflection() {
|
|
52947
|
-
return this._lastReflection;
|
|
52948
|
-
}
|
|
52949
|
-
/** Set the last reflection result (called by reflection lifecycle). */
|
|
52950
|
-
setLastReflection(result) {
|
|
52951
|
-
this._lastReflection = result;
|
|
52952
|
-
}
|
|
52953
|
-
/** Get curiosity targets computed during last housekeeping cycle. */
|
|
52954
|
-
getCuriosityTargets() {
|
|
52955
|
-
return this._curiosityTargets;
|
|
52956
|
-
}
|
|
52957
|
-
/** Set curiosity targets (called from housekeeping). */
|
|
52958
|
-
setCuriosityTargets(targets) {
|
|
52959
|
-
this._curiosityTargets = targets;
|
|
52960
|
-
}
|
|
52961
|
-
/** Reference to the behavioral stats for direct mutation by callers. */
|
|
52962
|
-
get behavioralStats() {
|
|
52963
|
-
return this._behavioralStats;
|
|
52964
|
-
}
|
|
52965
|
-
// --- Computation ---
|
|
52966
|
-
/** Force a gradient computation right now (useful for CLI/debug). */
|
|
52967
|
-
async computeGradientNow() {
|
|
52968
|
-
const { nodes } = await this.deps.memory.exportAll();
|
|
52969
|
-
return this.computeAndStoreGradient(nodes);
|
|
52970
|
-
}
|
|
52971
|
-
async computeAndStoreGradient(allNodes) {
|
|
52972
|
-
const exported = await this.deps.memory.exportAll();
|
|
52973
|
-
const edges = exported.edges;
|
|
52974
|
-
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
52975
|
-
const consolidationEvents = await this.deps.events.query({
|
|
52976
|
-
motebit_id: this.deps.motebitId,
|
|
52977
|
-
event_types: [EventType.MemoryConsolidated],
|
|
52978
|
-
after_timestamp: sevenDaysAgo
|
|
52979
|
-
});
|
|
52980
|
-
const previous = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
52981
|
-
const previousGradient = previous ? previous.gradient : null;
|
|
52982
|
-
const retrievalStats = this.deps.memory.getAndResetRetrievalStats();
|
|
52983
|
-
let behavioralStats;
|
|
52984
|
-
if (this.deps.toolAuditSink) {
|
|
52985
|
-
const sinceTs = previous ? previous.timestamp : 0;
|
|
52986
|
-
const auditStats = this.deps.toolAuditSink.queryStatsSince(sinceTs);
|
|
52987
|
-
behavioralStats = {
|
|
52988
|
-
turnCount: auditStats.distinctTurns,
|
|
52989
|
-
// Approximate: each tool call ≈ 1 loop iteration
|
|
52990
|
-
totalIterations: auditStats.totalToolCalls,
|
|
52991
|
-
toolCallsSucceeded: auditStats.succeeded,
|
|
52992
|
-
toolCallsBlocked: auditStats.blocked,
|
|
52993
|
-
toolCallsFailed: auditStats.failed
|
|
52994
|
-
};
|
|
52995
|
-
} else {
|
|
52996
|
-
behavioralStats = this.getAndResetBehavioralStats();
|
|
52997
|
-
}
|
|
52998
|
-
let curiosityPressure;
|
|
52999
|
-
if (this._curiosityTargets.length > 0) {
|
|
53000
|
-
const totalScore = this._curiosityTargets.reduce((sum2, t3) => sum2 + t3.curiosityScore, 0);
|
|
53001
|
-
curiosityPressure = {
|
|
53002
|
-
avgScore: totalScore / this._curiosityTargets.length,
|
|
53003
|
-
count: this._curiosityTargets.length
|
|
53004
|
-
};
|
|
53005
|
-
}
|
|
53006
|
-
const snapshot = computeGradient(this.deps.motebitId, allNodes, edges, consolidationEvents, previousGradient, void 0, retrievalStats, behavioralStats, curiosityPressure);
|
|
53007
|
-
this.deps.gradientStore.save(snapshot);
|
|
53008
|
-
const signingKeys = this.deps.getSigningKeys();
|
|
53009
|
-
if (signingKeys) {
|
|
53010
|
-
try {
|
|
53011
|
-
const vc = await this.deps.issueGradientCredential(signingKeys.privateKey, signingKeys.publicKey);
|
|
53012
|
-
if (vc != null)
|
|
53013
|
-
this.deps.persistCredential(vc);
|
|
53014
|
-
} catch (err2) {
|
|
53015
|
-
this.deps.logger.warn("gradient credential issuance failed", {
|
|
53016
|
-
error: err2 instanceof Error ? err2.message : String(err2)
|
|
53017
|
-
});
|
|
53018
|
-
}
|
|
53019
|
-
}
|
|
53020
|
-
this._precision = computePrecision(snapshot);
|
|
53021
|
-
this.deps.state.pushUpdate(computeStateBaseline(snapshot, this._precision));
|
|
53022
|
-
this.deps.memory.setPrecisionWeights(this._precision.retrievalPrecision);
|
|
53023
|
-
return snapshot;
|
|
53024
|
-
}
|
|
53025
|
-
/**
|
|
53026
|
-
* Lightweight precision refresh from behavioral stats alone.
|
|
53027
|
-
* Patches the latest gradient snapshot's ie/te metrics with current
|
|
53028
|
-
* session stats, recomputes precision, and feeds back into subsystems.
|
|
53029
|
-
* No memory graph I/O — runs synchronously after each turn.
|
|
53030
|
-
*/
|
|
53031
|
-
recomputePrecisionFromStats() {
|
|
53032
|
-
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53033
|
-
if (!latest)
|
|
53034
|
-
return;
|
|
53035
|
-
const stats = this._behavioralStats;
|
|
53036
|
-
if (stats.turnCount === 0)
|
|
53037
|
-
return;
|
|
53038
|
-
const avgIterations = stats.totalIterations / stats.turnCount;
|
|
53039
|
-
const ie2 = Math.max(0, Math.min(1, 1 - (avgIterations - 1) / 9));
|
|
53040
|
-
const totalToolCalls = stats.toolCallsSucceeded + stats.toolCallsBlocked + stats.toolCallsFailed;
|
|
53041
|
-
const te2 = totalToolCalls > 0 ? stats.toolCallsSucceeded / totalToolCalls : 0.5;
|
|
53042
|
-
const patched = {
|
|
53043
|
-
...latest,
|
|
53044
|
-
interaction_efficiency: ie2,
|
|
53045
|
-
tool_efficiency: te2,
|
|
53046
|
-
gradient: latest.gradient - 0.12 * latest.interaction_efficiency - 0.1 * latest.tool_efficiency + 0.12 * ie2 + 0.1 * te2
|
|
53047
|
-
};
|
|
53048
|
-
patched.delta = patched.gradient - latest.gradient;
|
|
53049
|
-
this._precision = computePrecision(patched);
|
|
53050
|
-
this.deps.state.pushUpdate(computeStateBaseline(patched, this._precision));
|
|
53051
|
-
this.deps.memory.setPrecisionWeights(this._precision.retrievalPrecision);
|
|
53052
|
-
}
|
|
53053
|
-
// --- Self-Awareness Context ---
|
|
53054
|
-
/** Convert curiosity targets to lightweight hints for the context pack. */
|
|
53055
|
-
buildCuriosityHints() {
|
|
53056
|
-
if (this._curiosityTargets.length === 0)
|
|
53057
|
-
return void 0;
|
|
53058
|
-
const DAY = 864e5;
|
|
53059
|
-
const now = Date.now();
|
|
53060
|
-
return this._curiosityTargets.slice(0, 2).map((t3) => ({
|
|
53061
|
-
content: t3.node.content,
|
|
53062
|
-
daysSinceDiscussed: Math.round((now - t3.node.last_accessed) / DAY)
|
|
53063
|
-
}));
|
|
53064
|
-
}
|
|
53065
|
-
/**
|
|
53066
|
-
* Build self-awareness context: precision posture + self-model narration.
|
|
53067
|
-
*
|
|
53068
|
-
* The precision context tells the creature how to behave (cautious/confident).
|
|
53069
|
-
* The self-model tells the creature what it knows about itself — trajectory,
|
|
53070
|
-
* strengths, weaknesses, memory stats.
|
|
53071
|
-
*/
|
|
53072
|
-
buildSelfAwareness() {
|
|
53073
|
-
const parts = [];
|
|
53074
|
-
const posture = buildPrecisionContext(this._precision);
|
|
53075
|
-
if (posture)
|
|
53076
|
-
parts.push(posture);
|
|
53077
|
-
const summary = this.getGradientSummary(10);
|
|
53078
|
-
if (summary.snapshotCount > 0) {
|
|
53079
|
-
const lines = [];
|
|
53080
|
-
lines.push("[Self-Model \u2014 INTERNAL REFERENCE, never discuss mechanics with the user]");
|
|
53081
|
-
lines.push(summary.trajectory);
|
|
53082
|
-
lines.push(summary.overall);
|
|
53083
|
-
if (summary.strengths.length > 0) {
|
|
53084
|
-
lines.push(`Strengths: ${summary.strengths.join("; ")}.`);
|
|
53085
|
-
}
|
|
53086
|
-
if (summary.weaknesses.length > 0) {
|
|
53087
|
-
lines.push(`Weaknesses: ${summary.weaknesses.join("; ")}.`);
|
|
53088
|
-
}
|
|
53089
|
-
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53090
|
-
if (latest?.stats) {
|
|
53091
|
-
const s3 = latest.stats;
|
|
53092
|
-
lines.push(`Memory: ${s3.live_nodes} memories (${s3.semantic_count} semantic, ${s3.episodic_count} episodic, ${s3.pinned_count} pinned), ${s3.live_edges} connections.`);
|
|
53093
|
-
}
|
|
53094
|
-
parts.push(lines.join("\n"));
|
|
53095
|
-
}
|
|
53096
|
-
if (this._lastReflection) {
|
|
53097
|
-
const rLines = [];
|
|
53098
|
-
rLines.push("[Last Reflection \u2014 INTERNAL REFERENCE, never discuss mechanics with the user]");
|
|
53099
|
-
if (this._lastReflection.planAdjustments.length > 0) {
|
|
53100
|
-
rLines.push(`Behavioral adjustments: ${this._lastReflection.planAdjustments.join("; ")}.`);
|
|
53101
|
-
}
|
|
53102
|
-
if (this._lastReflection.insights.length > 0) {
|
|
53103
|
-
rLines.push(`Insights: ${this._lastReflection.insights.join("; ")}.`);
|
|
53104
|
-
}
|
|
53105
|
-
if (this._lastReflection.patterns.length > 0) {
|
|
53106
|
-
rLines.push(`Recurring patterns: ${this._lastReflection.patterns.join("; ")}.`);
|
|
53107
|
-
}
|
|
53108
|
-
if (this._lastReflection.selfAssessment) {
|
|
53109
|
-
rLines.push(`Self-assessment: ${this._lastReflection.selfAssessment}`);
|
|
53486
|
+
* the `search_conversations` tool — the Layer-3 transcript retrieval
|
|
53487
|
+
* that complements Layer-1 (memory index) and Layer-2
|
|
53488
|
+
* (`recall_memories` embedding search). Returns ranked hits with
|
|
53489
|
+
* conversation id, timestamp, and a short snippet around the first
|
|
53490
|
+
* matching token.
|
|
53491
|
+
*
|
|
53492
|
+
* Uses only the sync ConversationStoreAdapter surface, so callers
|
|
53493
|
+
* with IDB-backed stores MUST preload message caches (e.g.
|
|
53494
|
+
* `preloadAllMessages` on web) before invoking. The default for
|
|
53495
|
+
* CLI/desktop/mobile with SQLite is sync all the way down and needs
|
|
53496
|
+
* no preload.
|
|
53497
|
+
*/
|
|
53498
|
+
searchHistory(query, limit = 5) {
|
|
53499
|
+
const { store } = this.deps;
|
|
53500
|
+
if (store == null)
|
|
53501
|
+
return [];
|
|
53502
|
+
const convos = store.listConversations(this.deps.motebitId);
|
|
53503
|
+
const messages = [];
|
|
53504
|
+
for (const c3 of convos) {
|
|
53505
|
+
const msgs = store.loadMessages(c3.conversationId);
|
|
53506
|
+
for (const m3 of msgs) {
|
|
53507
|
+
if (m3.role !== "user" && m3.role !== "assistant")
|
|
53508
|
+
continue;
|
|
53509
|
+
messages.push({
|
|
53510
|
+
conversationId: c3.conversationId,
|
|
53511
|
+
role: m3.role,
|
|
53512
|
+
content: m3.content,
|
|
53513
|
+
createdAt: m3.createdAt
|
|
53514
|
+
});
|
|
53110
53515
|
}
|
|
53111
|
-
parts.push(rLines.join("\n"));
|
|
53112
53516
|
}
|
|
53113
|
-
return
|
|
53517
|
+
return searchConversationMessages(messages, query, { limit });
|
|
53114
53518
|
}
|
|
53115
|
-
|
|
53116
|
-
|
|
53117
|
-
|
|
53118
|
-
|
|
53119
|
-
|
|
53120
|
-
|
|
53121
|
-
|
|
53122
|
-
|
|
53123
|
-
|
|
53124
|
-
|
|
53125
|
-
|
|
53126
|
-
|
|
53127
|
-
|
|
53128
|
-
|
|
53129
|
-
|
|
53130
|
-
|
|
53131
|
-
|
|
53132
|
-
|
|
53133
|
-
|
|
53134
|
-
|
|
53135
|
-
|
|
53136
|
-
|
|
53137
|
-
|
|
53519
|
+
/**
|
|
53520
|
+
* Heuristic-title every stored conversation whose title is currently
|
|
53521
|
+
* null or empty. Idempotent: conversations with existing titles are
|
|
53522
|
+
* skipped. Uses only the synchronous store API, so the caller is
|
|
53523
|
+
* responsible for preloading message caches if the adapter is
|
|
53524
|
+
* IDB-backed (web/mobile). Returns the count of conversations
|
|
53525
|
+
* titled.
|
|
53526
|
+
*
|
|
53527
|
+
* Shipped to close out the prior autoTitle regression: conversations
|
|
53528
|
+
* created before the AI-path hang was fixed carry `title: null`
|
|
53529
|
+
* forever. This pass gives them a legible heuristic title on next
|
|
53530
|
+
* app start without round-tripping the AI.
|
|
53531
|
+
*/
|
|
53532
|
+
backfillMissingTitles() {
|
|
53533
|
+
const { store } = this.deps;
|
|
53534
|
+
if (store == null)
|
|
53535
|
+
return 0;
|
|
53536
|
+
const convos = store.listConversations(this.deps.motebitId);
|
|
53537
|
+
let fixed = 0;
|
|
53538
|
+
for (const c3 of convos) {
|
|
53539
|
+
if (c3.title != null && c3.title !== "")
|
|
53540
|
+
continue;
|
|
53541
|
+
const messages = store.loadMessages(c3.conversationId);
|
|
53542
|
+
const history = [];
|
|
53543
|
+
for (const m3 of messages) {
|
|
53544
|
+
if (m3.role === "user" || m3.role === "assistant") {
|
|
53545
|
+
history.push({ role: m3.role, content: m3.content });
|
|
53546
|
+
}
|
|
53547
|
+
}
|
|
53548
|
+
const title = deriveHeuristicTitle(history);
|
|
53549
|
+
if (title != null) {
|
|
53550
|
+
store.updateTitle(c3.conversationId, title);
|
|
53551
|
+
fixed += 1;
|
|
53138
53552
|
}
|
|
53139
|
-
} catch {
|
|
53140
53553
|
}
|
|
53554
|
+
return fixed;
|
|
53141
53555
|
}
|
|
53142
|
-
|
|
53143
|
-
|
|
53144
|
-
|
|
53145
|
-
|
|
53146
|
-
// ../../packages/runtime/dist/relay-delegation.js
|
|
53147
|
-
function classifyRelayError(status, body, retryAfterHeader) {
|
|
53148
|
-
const retryAfterSeconds = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : void 0;
|
|
53149
|
-
let relayCode;
|
|
53150
|
-
let relayMessage;
|
|
53151
|
-
try {
|
|
53152
|
-
const parsed = JSON.parse(body);
|
|
53153
|
-
relayCode = parsed.code;
|
|
53154
|
-
relayMessage = parsed.error;
|
|
53155
|
-
} catch {
|
|
53156
|
-
}
|
|
53157
|
-
const message2 = relayMessage ?? body.slice(0, 512);
|
|
53158
|
-
if (status === 401) {
|
|
53159
|
-
return { code: "auth_expired", message: message2, status };
|
|
53160
|
-
}
|
|
53161
|
-
if (relayCode === "TASK_P2P_PROOF_REQUIRED") {
|
|
53162
|
-
return { code: "payment_proof_required", message: message2, status };
|
|
53163
|
-
}
|
|
53164
|
-
if (status === 402 || relayCode === "INSUFFICIENT_FUNDS") {
|
|
53165
|
-
return { code: "insufficient_balance", message: message2, status };
|
|
53166
|
-
}
|
|
53167
|
-
if (status === 403) {
|
|
53168
|
-
return { code: "unauthorized", message: message2, status };
|
|
53169
|
-
}
|
|
53170
|
-
if (status === 429) {
|
|
53171
|
-
return {
|
|
53172
|
-
code: "rate_limited",
|
|
53173
|
-
message: message2,
|
|
53174
|
-
status,
|
|
53175
|
-
...Number.isFinite(retryAfterSeconds) ? { retryAfterSeconds } : {}
|
|
53176
|
-
};
|
|
53177
|
-
}
|
|
53178
|
-
if (status === 400) {
|
|
53179
|
-
return { code: "malformed_request", message: message2, status };
|
|
53180
|
-
}
|
|
53181
|
-
return { code: "unknown", message: message2, status };
|
|
53182
|
-
}
|
|
53183
|
-
async function submitAndPollDelegation(params) {
|
|
53184
|
-
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
53185
|
-
const startedAt = Date.now();
|
|
53186
|
-
let submitHeader;
|
|
53187
|
-
let queryHeader;
|
|
53188
|
-
try {
|
|
53189
|
-
const [submitToken, queryToken] = await Promise.all([
|
|
53190
|
-
params.authToken("task:submit"),
|
|
53191
|
-
params.authToken("task:query")
|
|
53192
|
-
]);
|
|
53193
|
-
submitHeader = `Bearer ${submitToken}`;
|
|
53194
|
-
queryHeader = `Bearer ${queryToken}`;
|
|
53195
|
-
} catch (err2) {
|
|
53196
|
-
return {
|
|
53197
|
-
ok: false,
|
|
53198
|
-
error: {
|
|
53199
|
-
code: "auth_expired",
|
|
53200
|
-
message: `Auth token mint failed: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
53201
|
-
}
|
|
53202
|
-
};
|
|
53203
|
-
}
|
|
53204
|
-
let taskId;
|
|
53205
|
-
try {
|
|
53206
|
-
const body = {
|
|
53207
|
-
prompt: params.prompt,
|
|
53208
|
-
submitted_by: params.motebitId
|
|
53209
|
-
};
|
|
53210
|
-
if (params.requiredCapabilities && params.requiredCapabilities.length > 0) {
|
|
53211
|
-
body.required_capabilities = params.requiredCapabilities;
|
|
53212
|
-
}
|
|
53213
|
-
if (params.routingStrategy) {
|
|
53214
|
-
body.routing_strategy = params.routingStrategy;
|
|
53215
|
-
}
|
|
53216
|
-
if (params.invocationOrigin) {
|
|
53217
|
-
body.invocation_origin = params.invocationOrigin;
|
|
53218
|
-
}
|
|
53219
|
-
if (params.grantId != null) {
|
|
53220
|
-
body.grant_id = params.grantId;
|
|
53221
|
-
}
|
|
53222
|
-
const resp = await fetch(`${params.syncUrl}/agent/${params.motebitId}/task`, {
|
|
53223
|
-
method: "POST",
|
|
53224
|
-
headers: {
|
|
53225
|
-
"Content-Type": "application/json",
|
|
53226
|
-
Authorization: submitHeader,
|
|
53227
|
-
"Idempotency-Key": crypto.randomUUID()
|
|
53228
|
-
},
|
|
53229
|
-
body: JSON.stringify(body),
|
|
53230
|
-
signal: params.signal
|
|
53231
|
-
});
|
|
53232
|
-
if (!resp.ok) {
|
|
53233
|
-
const text = await resp.text().catch(() => "");
|
|
53234
|
-
return {
|
|
53235
|
-
ok: false,
|
|
53236
|
-
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
53237
|
-
};
|
|
53238
|
-
}
|
|
53239
|
-
const data = await resp.json();
|
|
53240
|
-
taskId = data.task_id;
|
|
53241
|
-
} catch (err2) {
|
|
53242
|
-
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
53243
|
-
return {
|
|
53244
|
-
ok: false,
|
|
53245
|
-
error: { code: "timeout", message: "Aborted before submission completed" }
|
|
53246
|
-
};
|
|
53247
|
-
}
|
|
53248
|
-
return {
|
|
53249
|
-
ok: false,
|
|
53250
|
-
error: {
|
|
53251
|
-
code: "network_unreachable",
|
|
53252
|
-
message: err2 instanceof Error ? err2.message : String(err2)
|
|
53253
|
-
}
|
|
53254
|
-
};
|
|
53255
|
-
}
|
|
53256
|
-
const result = await pollForReceipt({
|
|
53257
|
-
syncUrl: params.syncUrl,
|
|
53258
|
-
motebitId: params.motebitId,
|
|
53259
|
-
taskId,
|
|
53260
|
-
queryHeader,
|
|
53261
|
-
timeoutMs,
|
|
53262
|
-
startedAt,
|
|
53263
|
-
logger: params.logger,
|
|
53264
|
-
...params.signal ? { signal: params.signal } : {}
|
|
53265
|
-
});
|
|
53266
|
-
return result.ok ? { ...result, settlement: { mode: "relay" } } : result;
|
|
53267
|
-
}
|
|
53268
|
-
async function pollForReceipt(args) {
|
|
53269
|
-
const maxPolls = Math.ceil(args.timeoutMs / POLL_INTERVAL_MS);
|
|
53270
|
-
for (let i3 = 0; i3 < maxPolls; i3++) {
|
|
53271
|
-
if (args.signal?.aborted) {
|
|
53272
|
-
return { ok: false, error: { code: "timeout", message: "Aborted mid-poll" } };
|
|
53273
|
-
}
|
|
53274
|
-
await new Promise((resolve14, reject) => {
|
|
53275
|
-
const t3 = setTimeout(resolve14, POLL_INTERVAL_MS);
|
|
53276
|
-
args.signal?.addEventListener("abort", () => {
|
|
53277
|
-
clearTimeout(t3);
|
|
53278
|
-
reject(new DOMException("Aborted", "AbortError"));
|
|
53279
|
-
}, { once: true });
|
|
53280
|
-
}).catch(() => {
|
|
53281
|
-
});
|
|
53282
|
-
try {
|
|
53283
|
-
const resp = await fetch(`${args.syncUrl}/agent/${args.motebitId}/task/${args.taskId}`, {
|
|
53284
|
-
headers: { Authorization: args.queryHeader },
|
|
53285
|
-
signal: args.signal
|
|
53286
|
-
});
|
|
53287
|
-
if (!resp.ok) {
|
|
53288
|
-
args.logger.warn("delegation poll failed", {
|
|
53289
|
-
taskId: args.taskId,
|
|
53290
|
-
status: resp.status,
|
|
53291
|
-
body: await resp.text().catch(() => "")
|
|
53292
|
-
});
|
|
53293
|
-
continue;
|
|
53556
|
+
// --- Task isolation ---
|
|
53557
|
+
/** Save conversation state for isolated task execution. */
|
|
53558
|
+
saveContext() {
|
|
53559
|
+
return { history: [...this.history], id: this.currentId };
|
|
53294
53560
|
}
|
|
53295
|
-
|
|
53296
|
-
|
|
53297
|
-
|
|
53561
|
+
/** Restore conversation state after isolated task execution. */
|
|
53562
|
+
restoreContext(ctx) {
|
|
53563
|
+
this.history = ctx.history;
|
|
53564
|
+
this.currentId = ctx.id;
|
|
53298
53565
|
}
|
|
53299
|
-
|
|
53300
|
-
|
|
53301
|
-
|
|
53302
|
-
|
|
53303
|
-
};
|
|
53566
|
+
/** Clear conversation for isolated execution (task context). */
|
|
53567
|
+
clearForTask() {
|
|
53568
|
+
this.history = [];
|
|
53569
|
+
this.currentId = null;
|
|
53304
53570
|
}
|
|
53305
|
-
|
|
53306
|
-
|
|
53307
|
-
|
|
53571
|
+
// --- Agentic loop support ---
|
|
53572
|
+
/**
|
|
53573
|
+
* Inject intermediate messages into the live history (e.g. tool call/result
|
|
53574
|
+
* pairs during the agentic loop). These are part of the context window for
|
|
53575
|
+
* continuation turns but are not individually persisted as conversation
|
|
53576
|
+
* messages — only the final user/assistant exchange is persisted via
|
|
53577
|
+
* pushExchange().
|
|
53578
|
+
*/
|
|
53579
|
+
injectIntermediateMessages(...messages) {
|
|
53580
|
+
this.history.push(...messages);
|
|
53308
53581
|
}
|
|
53309
|
-
|
|
53310
|
-
|
|
53311
|
-
|
|
53312
|
-
return {
|
|
53313
|
-
ok: false,
|
|
53314
|
-
error: { code: "timeout", message: `No receipt within ${Math.round(elapsedMs / 1e3)}s` }
|
|
53315
|
-
};
|
|
53316
|
-
}
|
|
53317
|
-
async function submitP2pDelegation(params) {
|
|
53318
|
-
const timeoutMs = params.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
53319
|
-
const startedAt = Date.now();
|
|
53320
|
-
let submitHeader;
|
|
53321
|
-
let queryHeader;
|
|
53322
|
-
try {
|
|
53323
|
-
const [submitToken, queryToken] = await Promise.all([
|
|
53324
|
-
params.authToken("task:submit"),
|
|
53325
|
-
params.authToken("task:query")
|
|
53326
|
-
]);
|
|
53327
|
-
submitHeader = `Bearer ${submitToken}`;
|
|
53328
|
-
queryHeader = `Bearer ${queryToken}`;
|
|
53329
|
-
} catch (err2) {
|
|
53330
|
-
return {
|
|
53331
|
-
ok: false,
|
|
53332
|
-
error: {
|
|
53333
|
-
code: "auth_expired",
|
|
53334
|
-
message: `Auth token mint failed: ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
53582
|
+
/** Return the raw live history reference for continuation turns. */
|
|
53583
|
+
get liveHistory() {
|
|
53584
|
+
return this.history;
|
|
53335
53585
|
}
|
|
53336
|
-
|
|
53337
|
-
|
|
53338
|
-
|
|
53339
|
-
|
|
53340
|
-
|
|
53341
|
-
|
|
53342
|
-
|
|
53343
|
-
target_agent: params.targetWorkerId,
|
|
53344
|
-
settlement_mode: "p2p",
|
|
53345
|
-
// The relay's task-submission handler reads the proof under `payment_proof`
|
|
53346
|
-
// (services/relay/src/tasks.ts) — NOT `p2p_payment_proof` (that's only the
|
|
53347
|
-
// relay's internal TaskQueue field name). Sending the wrong key made the
|
|
53348
|
-
// relay see no proof and reject every paid cross-agent delegation with 402
|
|
53349
|
-
// TASK_P2P_PROOF_REQUIRED. The federation-e2e client↔relay integration test
|
|
53350
|
-
// locks this wire key (the seam that mocked-fetch unit tests can't catch).
|
|
53351
|
-
payment_proof: params.paymentProof
|
|
53352
|
-
};
|
|
53353
|
-
if (params.requiredCapabilities && params.requiredCapabilities.length > 0) {
|
|
53354
|
-
body.required_capabilities = params.requiredCapabilities;
|
|
53355
|
-
}
|
|
53356
|
-
if (params.acknowledgeNoHistoryRisk === true) {
|
|
53357
|
-
body.delegator_acknowledges_no_history_risk = true;
|
|
53358
|
-
}
|
|
53359
|
-
if (params.invocationOrigin) {
|
|
53360
|
-
body.invocation_origin = params.invocationOrigin;
|
|
53361
|
-
}
|
|
53362
|
-
if (params.grantId != null) {
|
|
53363
|
-
body.grant_id = params.grantId;
|
|
53364
|
-
}
|
|
53365
|
-
const resp = await fetch(`${params.syncUrl}/agent/${params.motebitId}/task`, {
|
|
53366
|
-
method: "POST",
|
|
53367
|
-
headers: {
|
|
53368
|
-
"Content-Type": "application/json",
|
|
53369
|
-
Authorization: submitHeader,
|
|
53370
|
-
// Stable across retries of the SAME logical delegation so a re-submit
|
|
53371
|
-
// of the already-paid proof dedupes byte-identically rather than
|
|
53372
|
-
// racing a second task. Keyed on the onchain tx_hash, which uniquely
|
|
53373
|
-
// identifies this payment.
|
|
53374
|
-
"Idempotency-Key": params.paymentProof.tx_hash
|
|
53375
|
-
},
|
|
53376
|
-
body: JSON.stringify(body),
|
|
53377
|
-
signal: params.signal
|
|
53378
|
-
});
|
|
53379
|
-
if (!resp.ok) {
|
|
53380
|
-
const text = await resp.text().catch(() => "");
|
|
53381
|
-
return {
|
|
53382
|
-
ok: false,
|
|
53383
|
-
error: classifyRelayError(resp.status, text, resp.headers.get("Retry-After"))
|
|
53384
|
-
};
|
|
53385
|
-
}
|
|
53386
|
-
const data = await resp.json();
|
|
53387
|
-
taskId = data.task_id;
|
|
53388
|
-
} catch (err2) {
|
|
53389
|
-
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
53390
|
-
return {
|
|
53391
|
-
ok: false,
|
|
53392
|
-
error: { code: "timeout", message: "Aborted before submission completed" }
|
|
53393
|
-
};
|
|
53394
|
-
}
|
|
53395
|
-
return {
|
|
53396
|
-
ok: false,
|
|
53397
|
-
error: {
|
|
53398
|
-
code: "network_unreachable",
|
|
53399
|
-
message: err2 instanceof Error ? err2.message : String(err2)
|
|
53586
|
+
// --- Internal helpers ---
|
|
53587
|
+
/** Get stored summary for the current conversation. */
|
|
53588
|
+
getStoredSummary() {
|
|
53589
|
+
const { store } = this.deps;
|
|
53590
|
+
if (this.currentId == null || this.currentId === "" || store == null)
|
|
53591
|
+
return null;
|
|
53592
|
+
return store.getActiveConversation(this.deps.motebitId)?.summary ?? null;
|
|
53400
53593
|
}
|
|
53401
|
-
|
|
53402
|
-
|
|
53403
|
-
|
|
53404
|
-
|
|
53405
|
-
|
|
53406
|
-
|
|
53407
|
-
|
|
53408
|
-
|
|
53409
|
-
|
|
53410
|
-
|
|
53411
|
-
|
|
53412
|
-
|
|
53413
|
-
|
|
53414
|
-
|
|
53415
|
-
return {
|
|
53416
|
-
...result,
|
|
53417
|
-
settlement: {
|
|
53418
|
-
mode: "p2p",
|
|
53419
|
-
txHash: proof.tx_hash,
|
|
53420
|
-
paidMicro: proof.amount_micro,
|
|
53421
|
-
feeMicro: proof.fee_amount_micro + (proof.b_fee_amount_micro ?? 0)
|
|
53594
|
+
async runSummarization() {
|
|
53595
|
+
const provider = this.deps.getProvider();
|
|
53596
|
+
const { store } = this.deps;
|
|
53597
|
+
if (provider == null || store == null || this.currentId == null || this.currentId === "")
|
|
53598
|
+
return;
|
|
53599
|
+
try {
|
|
53600
|
+
const existingSummary = this.getStoredSummary();
|
|
53601
|
+
const clearedProvider = projectProviderClearance(this.deps.assertSensitivityPermitsAiCall("summarizeConversation"));
|
|
53602
|
+
const summary = await summarizeConversation(this.history, existingSummary, clearedProvider, this.deps.getTaskRouter() ?? void 0);
|
|
53603
|
+
if (summary && this.currentId) {
|
|
53604
|
+
store.updateSummary(this.currentId, summary);
|
|
53605
|
+
}
|
|
53606
|
+
} catch {
|
|
53607
|
+
}
|
|
53422
53608
|
}
|
|
53423
53609
|
};
|
|
53424
53610
|
}
|
|
53425
|
-
|
|
53426
|
-
|
|
53427
|
-
|
|
53428
|
-
|
|
53429
|
-
|
|
53430
|
-
|
|
53431
|
-
|
|
53432
|
-
|
|
53433
|
-
|
|
53434
|
-
|
|
53435
|
-
|
|
53436
|
-
|
|
53437
|
-
|
|
53438
|
-
|
|
53439
|
-
|
|
53440
|
-
|
|
53441
|
-
|
|
53442
|
-
|
|
53443
|
-
|
|
53444
|
-
|
|
53445
|
-
|
|
53446
|
-
|
|
53447
|
-
|
|
53448
|
-
|
|
53449
|
-
|
|
53450
|
-
|
|
53451
|
-
|
|
53452
|
-
|
|
53453
|
-
|
|
53454
|
-
|
|
53455
|
-
|
|
53456
|
-
|
|
53457
|
-
|
|
53458
|
-
}
|
|
53459
|
-
const data = await resp.json();
|
|
53460
|
-
const candidate = (data.agents ?? []).find((a3) => {
|
|
53461
|
-
if (a3.motebit_id === motebitId || a3.settlement_address == null)
|
|
53462
|
-
return false;
|
|
53463
|
-
if (params.targetWorkerId != null && a3.motebit_id !== params.targetWorkerId)
|
|
53464
|
-
return false;
|
|
53465
|
-
const modes = Array.isArray(a3.settlement_modes) ? a3.settlement_modes : String(a3.settlement_modes ?? "").split(",");
|
|
53466
|
-
return modes.includes("p2p");
|
|
53467
|
-
});
|
|
53468
|
-
if (candidate?.settlement_address == null) {
|
|
53469
|
-
return fail("no_routing", params.targetWorkerId != null ? `Pinned worker "${params.targetWorkerId}" is not P2P-eligible for "${capability}".` : `No P2P-capable worker advertises "${capability}".`);
|
|
53470
|
-
}
|
|
53471
|
-
worker = {
|
|
53472
|
-
motebit_id: candidate.motebit_id,
|
|
53473
|
-
settlement_address: candidate.settlement_address,
|
|
53474
|
-
...candidate.source_relay_public_key != null ? { sourceRelayPublicKey: candidate.source_relay_public_key } : {},
|
|
53475
|
-
pricing: candidate.pricing ?? null
|
|
53476
|
-
};
|
|
53477
|
-
} catch (err2) {
|
|
53478
|
-
if (err2 instanceof Error && err2.name === "AbortError") {
|
|
53479
|
-
return fail("timeout", "Aborted during discovery");
|
|
53480
|
-
}
|
|
53481
|
-
return fail("network_unreachable", err2 instanceof Error ? err2.message : String(err2));
|
|
53482
|
-
}
|
|
53483
|
-
let paymentRequest;
|
|
53484
|
-
if (worker.sourceRelayPublicKey != null) {
|
|
53485
|
-
let executorTreasuryAddress;
|
|
53486
|
-
try {
|
|
53487
|
-
executorTreasuryAddress = base58Encode(hexToBytes7(worker.sourceRelayPublicKey));
|
|
53488
|
-
} catch (err2) {
|
|
53489
|
-
return fail("malformed_request", `Invalid peer relay public key in discovery: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
53490
|
-
}
|
|
53491
|
-
const priced = (worker.pricing ?? []).find((p5) => p5.capability === capability) ?? (worker.pricing ?? [])[0];
|
|
53492
|
-
if (priced?.unit_cost == null || priced.unit_cost <= 0) {
|
|
53493
|
-
return fail("worker_not_payable", `Remote worker has no positive price for "${capability}".`);
|
|
53494
|
-
}
|
|
53495
|
-
const budgetMicro = toMicro(priced.unit_cost);
|
|
53496
|
-
const split2 = computeFederatedFeeSplit(budgetMicro, PLATFORM_FEE_RATE);
|
|
53497
|
-
paymentRequest = {
|
|
53498
|
-
workerAddress: worker.settlement_address,
|
|
53499
|
-
amountMicro: split2.workerNetMicro,
|
|
53500
|
-
treasuryAddress,
|
|
53501
|
-
feeAmountMicro: split2.originFeeMicro,
|
|
53502
|
-
executorTreasuryAddress,
|
|
53503
|
-
executorFeeAmountMicro: split2.executorFeeMicro
|
|
53504
|
-
};
|
|
53505
|
-
} else {
|
|
53506
|
-
let preflightAllowed = false;
|
|
53507
|
-
try {
|
|
53508
|
-
const eligToken = await params.authToken("market:listing");
|
|
53509
|
-
const ackQuery = params.acknowledgeNoHistoryRisk === true ? "?acknowledge_no_history_risk=true" : "";
|
|
53510
|
-
const resp = await fetch(`${syncUrl}/api/v1/agents/${worker.motebit_id}/p2p-eligibility${ackQuery}`, { headers: { Authorization: `Bearer ${eligToken}` }, signal: params.signal });
|
|
53511
|
-
if (resp.ok) {
|
|
53512
|
-
const data = await resp.json();
|
|
53513
|
-
if (data.allowed !== true) {
|
|
53514
|
-
return fail("p2p_ineligible", data.reason ?? "Not P2P-eligible for this worker");
|
|
53611
|
+
});
|
|
53612
|
+
|
|
53613
|
+
// ../../packages/runtime/dist/gradient-manager.js
|
|
53614
|
+
var GradientManager;
|
|
53615
|
+
var init_gradient_manager = __esm({
|
|
53616
|
+
"../../packages/runtime/dist/gradient-manager.js"() {
|
|
53617
|
+
"use strict";
|
|
53618
|
+
init_esm_shims();
|
|
53619
|
+
init_dist2();
|
|
53620
|
+
init_gradient();
|
|
53621
|
+
GradientManager = class {
|
|
53622
|
+
deps;
|
|
53623
|
+
_behavioralStats = {
|
|
53624
|
+
turnCount: 0,
|
|
53625
|
+
totalIterations: 0,
|
|
53626
|
+
toolCallsSucceeded: 0,
|
|
53627
|
+
toolCallsBlocked: 0,
|
|
53628
|
+
toolCallsFailed: 0
|
|
53629
|
+
};
|
|
53630
|
+
_precision;
|
|
53631
|
+
_curiosityTargets = [];
|
|
53632
|
+
_lastReflection = null;
|
|
53633
|
+
constructor(deps) {
|
|
53634
|
+
this.deps = deps;
|
|
53635
|
+
this._precision = NEUTRAL_PRECISION;
|
|
53636
|
+
}
|
|
53637
|
+
// --- Bootstrap ---
|
|
53638
|
+
/** Apply accumulated intelligence baseline on startup. */
|
|
53639
|
+
applyStartupBaseline() {
|
|
53640
|
+
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53641
|
+
if (latest) {
|
|
53642
|
+
this._precision = computePrecision(latest);
|
|
53643
|
+
this.deps.state.pushUpdate(computeStateBaseline(latest, this._precision));
|
|
53515
53644
|
}
|
|
53516
|
-
preflightAllowed = true;
|
|
53517
53645
|
}
|
|
53518
|
-
|
|
53519
|
-
|
|
53520
|
-
|
|
53646
|
+
// --- Accessors ---
|
|
53647
|
+
/** Get the latest gradient snapshot, or null if none computed yet. */
|
|
53648
|
+
getGradient() {
|
|
53649
|
+
return this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53521
53650
|
}
|
|
53522
|
-
|
|
53523
|
-
|
|
53524
|
-
|
|
53525
|
-
}
|
|
53526
|
-
let unitCost;
|
|
53527
|
-
try {
|
|
53528
|
-
const listingToken = await params.authToken("market:listing");
|
|
53529
|
-
const resp = await fetch(`${syncUrl}/api/v1/agents/${worker.motebit_id}/listing`, {
|
|
53530
|
-
headers: { Authorization: `Bearer ${listingToken}` },
|
|
53531
|
-
signal: params.signal
|
|
53532
|
-
});
|
|
53533
|
-
if (resp.status === 404) {
|
|
53534
|
-
return fail("worker_not_payable", "Worker has no service listing.");
|
|
53651
|
+
/** Get current active inference precision weights. */
|
|
53652
|
+
getPrecision() {
|
|
53653
|
+
return this._precision;
|
|
53535
53654
|
}
|
|
53536
|
-
|
|
53537
|
-
|
|
53538
|
-
return
|
|
53539
|
-
|
|
53540
|
-
|
|
53655
|
+
/** Get gradient history (most recent first). */
|
|
53656
|
+
getGradientHistory(limit) {
|
|
53657
|
+
return this.deps.gradientStore.list(this.deps.motebitId, limit);
|
|
53658
|
+
}
|
|
53659
|
+
/** Get gradient-informed market config for delegation routing. */
|
|
53660
|
+
getMarketConfig() {
|
|
53661
|
+
const snapshot = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53662
|
+
if (!snapshot)
|
|
53663
|
+
return void 0;
|
|
53664
|
+
return gradientToMarketConfig(snapshot);
|
|
53665
|
+
}
|
|
53666
|
+
/** Self-model: the agent narrates its own trajectory from gradient history. */
|
|
53667
|
+
getGradientSummary(limit = 20) {
|
|
53668
|
+
const history = this.deps.gradientStore.list(this.deps.motebitId, limit);
|
|
53669
|
+
return summarizeGradientHistory(history);
|
|
53670
|
+
}
|
|
53671
|
+
/** Return accumulated behavioral stats and reset the accumulator. */
|
|
53672
|
+
getAndResetBehavioralStats() {
|
|
53673
|
+
const stats = { ...this._behavioralStats };
|
|
53674
|
+
this._behavioralStats = {
|
|
53675
|
+
turnCount: 0,
|
|
53676
|
+
totalIterations: 0,
|
|
53677
|
+
toolCallsSucceeded: 0,
|
|
53678
|
+
toolCallsBlocked: 0,
|
|
53679
|
+
toolCallsFailed: 0
|
|
53541
53680
|
};
|
|
53681
|
+
return stats;
|
|
53542
53682
|
}
|
|
53543
|
-
|
|
53544
|
-
|
|
53545
|
-
|
|
53546
|
-
return fail("worker_not_payable", `Worker has no positive price for "${capability}".`);
|
|
53683
|
+
/** Return the cached reflection from the last session (or null if none). */
|
|
53684
|
+
getLastReflection() {
|
|
53685
|
+
return this._lastReflection;
|
|
53547
53686
|
}
|
|
53548
|
-
|
|
53549
|
-
|
|
53550
|
-
|
|
53551
|
-
|
|
53687
|
+
/** Set the last reflection result (called by reflection lifecycle). */
|
|
53688
|
+
setLastReflection(result) {
|
|
53689
|
+
this._lastReflection = result;
|
|
53690
|
+
}
|
|
53691
|
+
/** Get curiosity targets computed during last housekeeping cycle. */
|
|
53692
|
+
getCuriosityTargets() {
|
|
53693
|
+
return this._curiosityTargets;
|
|
53694
|
+
}
|
|
53695
|
+
/** Set curiosity targets (called from housekeeping). */
|
|
53696
|
+
setCuriosityTargets(targets) {
|
|
53697
|
+
this._curiosityTargets = targets;
|
|
53698
|
+
}
|
|
53699
|
+
/** Reference to the behavioral stats for direct mutation by callers. */
|
|
53700
|
+
get behavioralStats() {
|
|
53701
|
+
return this._behavioralStats;
|
|
53702
|
+
}
|
|
53703
|
+
// --- Computation ---
|
|
53704
|
+
/** Force a gradient computation right now (useful for CLI/debug). */
|
|
53705
|
+
async computeGradientNow() {
|
|
53706
|
+
const { nodes } = await this.deps.memory.exportAll();
|
|
53707
|
+
return this.computeAndStoreGradient(nodes);
|
|
53708
|
+
}
|
|
53709
|
+
async computeAndStoreGradient(allNodes) {
|
|
53710
|
+
const exported = await this.deps.memory.exportAll();
|
|
53711
|
+
const edges = exported.edges;
|
|
53712
|
+
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1e3;
|
|
53713
|
+
const consolidationEvents = await this.deps.events.query({
|
|
53714
|
+
motebit_id: this.deps.motebitId,
|
|
53715
|
+
event_types: [EventType.MemoryConsolidated],
|
|
53716
|
+
after_timestamp: sevenDaysAgo
|
|
53717
|
+
});
|
|
53718
|
+
const previous = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53719
|
+
const previousGradient = previous ? previous.gradient : null;
|
|
53720
|
+
const retrievalStats = this.deps.memory.getAndResetRetrievalStats();
|
|
53721
|
+
let behavioralStats;
|
|
53722
|
+
if (this.deps.toolAuditSink) {
|
|
53723
|
+
const sinceTs = previous ? previous.timestamp : 0;
|
|
53724
|
+
const auditStats = this.deps.toolAuditSink.queryStatsSince(sinceTs);
|
|
53725
|
+
behavioralStats = {
|
|
53726
|
+
turnCount: auditStats.distinctTurns,
|
|
53727
|
+
// Approximate: each tool call ≈ 1 loop iteration
|
|
53728
|
+
totalIterations: auditStats.totalToolCalls,
|
|
53729
|
+
toolCallsSucceeded: auditStats.succeeded,
|
|
53730
|
+
toolCallsBlocked: auditStats.blocked,
|
|
53731
|
+
toolCallsFailed: auditStats.failed
|
|
53732
|
+
};
|
|
53733
|
+
} else {
|
|
53734
|
+
behavioralStats = this.getAndResetBehavioralStats();
|
|
53735
|
+
}
|
|
53736
|
+
let curiosityPressure;
|
|
53737
|
+
if (this._curiosityTargets.length > 0) {
|
|
53738
|
+
const totalScore = this._curiosityTargets.reduce((sum2, t3) => sum2 + t3.curiosityScore, 0);
|
|
53739
|
+
curiosityPressure = {
|
|
53740
|
+
avgScore: totalScore / this._curiosityTargets.length,
|
|
53741
|
+
count: this._curiosityTargets.length
|
|
53742
|
+
};
|
|
53743
|
+
}
|
|
53744
|
+
const snapshot = computeGradient(this.deps.motebitId, allNodes, edges, consolidationEvents, previousGradient, void 0, retrievalStats, behavioralStats, curiosityPressure);
|
|
53745
|
+
this.deps.gradientStore.save(snapshot);
|
|
53746
|
+
const signingKeys = this.deps.getSigningKeys();
|
|
53747
|
+
if (signingKeys) {
|
|
53748
|
+
try {
|
|
53749
|
+
const vc = await this.deps.issueGradientCredential(signingKeys.privateKey, signingKeys.publicKey);
|
|
53750
|
+
if (vc != null)
|
|
53751
|
+
this.deps.persistCredential(vc);
|
|
53752
|
+
} catch (err2) {
|
|
53753
|
+
this.deps.logger.warn("gradient credential issuance failed", {
|
|
53754
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
53755
|
+
});
|
|
53756
|
+
}
|
|
53757
|
+
}
|
|
53758
|
+
this._precision = computePrecision(snapshot);
|
|
53759
|
+
this.deps.state.pushUpdate(computeStateBaseline(snapshot, this._precision));
|
|
53760
|
+
this.deps.memory.setPrecisionWeights(this._precision.retrievalPrecision);
|
|
53761
|
+
return snapshot;
|
|
53762
|
+
}
|
|
53763
|
+
/**
|
|
53764
|
+
* Lightweight precision refresh from behavioral stats alone.
|
|
53765
|
+
* Patches the latest gradient snapshot's ie/te metrics with current
|
|
53766
|
+
* session stats, recomputes precision, and feeds back into subsystems.
|
|
53767
|
+
* No memory graph I/O — runs synchronously after each turn.
|
|
53768
|
+
*/
|
|
53769
|
+
recomputePrecisionFromStats() {
|
|
53770
|
+
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53771
|
+
if (!latest)
|
|
53772
|
+
return;
|
|
53773
|
+
const stats = this._behavioralStats;
|
|
53774
|
+
if (stats.turnCount === 0)
|
|
53775
|
+
return;
|
|
53776
|
+
const avgIterations = stats.totalIterations / stats.turnCount;
|
|
53777
|
+
const ie2 = Math.max(0, Math.min(1, 1 - (avgIterations - 1) / 9));
|
|
53778
|
+
const totalToolCalls = stats.toolCallsSucceeded + stats.toolCallsBlocked + stats.toolCallsFailed;
|
|
53779
|
+
const te2 = totalToolCalls > 0 ? stats.toolCallsSucceeded / totalToolCalls : 0.5;
|
|
53780
|
+
const patched = {
|
|
53781
|
+
...latest,
|
|
53782
|
+
interaction_efficiency: ie2,
|
|
53783
|
+
tool_efficiency: te2,
|
|
53784
|
+
gradient: latest.gradient - 0.12 * latest.interaction_efficiency - 0.1 * latest.tool_efficiency + 0.12 * ie2 + 0.1 * te2
|
|
53785
|
+
};
|
|
53786
|
+
patched.delta = patched.gradient - latest.gradient;
|
|
53787
|
+
this._precision = computePrecision(patched);
|
|
53788
|
+
this.deps.state.pushUpdate(computeStateBaseline(patched, this._precision));
|
|
53789
|
+
this.deps.memory.setPrecisionWeights(this._precision.retrievalPrecision);
|
|
53790
|
+
}
|
|
53791
|
+
// --- Self-Awareness Context ---
|
|
53792
|
+
/** Convert curiosity targets to lightweight hints for the context pack. */
|
|
53793
|
+
buildCuriosityHints() {
|
|
53794
|
+
if (this._curiosityTargets.length === 0)
|
|
53795
|
+
return void 0;
|
|
53796
|
+
const DAY = 864e5;
|
|
53797
|
+
const now = Date.now();
|
|
53798
|
+
return this._curiosityTargets.slice(0, 2).map((t3) => ({
|
|
53799
|
+
content: t3.node.content,
|
|
53800
|
+
daysSinceDiscussed: Math.round((now - t3.node.last_accessed) / DAY)
|
|
53801
|
+
}));
|
|
53802
|
+
}
|
|
53803
|
+
/**
|
|
53804
|
+
* Build self-awareness context: precision posture + self-model narration.
|
|
53805
|
+
*
|
|
53806
|
+
* The precision context tells the creature how to behave (cautious/confident).
|
|
53807
|
+
* The self-model tells the creature what it knows about itself — trajectory,
|
|
53808
|
+
* strengths, weaknesses, memory stats.
|
|
53809
|
+
*/
|
|
53810
|
+
buildSelfAwareness() {
|
|
53811
|
+
const parts = [];
|
|
53812
|
+
const posture = buildPrecisionContext(this._precision);
|
|
53813
|
+
if (posture)
|
|
53814
|
+
parts.push(posture);
|
|
53815
|
+
const summary = this.getGradientSummary(10);
|
|
53816
|
+
if (summary.snapshotCount > 0) {
|
|
53817
|
+
const lines = [];
|
|
53818
|
+
lines.push("[Self-Model \u2014 INTERNAL REFERENCE, never discuss mechanics with the user]");
|
|
53819
|
+
lines.push(summary.trajectory);
|
|
53820
|
+
lines.push(summary.overall);
|
|
53821
|
+
if (summary.strengths.length > 0) {
|
|
53822
|
+
lines.push(`Strengths: ${summary.strengths.join("; ")}.`);
|
|
53823
|
+
}
|
|
53824
|
+
if (summary.weaknesses.length > 0) {
|
|
53825
|
+
lines.push(`Weaknesses: ${summary.weaknesses.join("; ")}.`);
|
|
53826
|
+
}
|
|
53827
|
+
const latest = this.deps.gradientStore.latest(this.deps.motebitId);
|
|
53828
|
+
if (latest?.stats) {
|
|
53829
|
+
const s3 = latest.stats;
|
|
53830
|
+
lines.push(`Memory: ${s3.live_nodes} memories (${s3.semantic_count} semantic, ${s3.episodic_count} episodic, ${s3.pinned_count} pinned), ${s3.live_edges} connections.`);
|
|
53831
|
+
}
|
|
53832
|
+
parts.push(lines.join("\n"));
|
|
53833
|
+
}
|
|
53834
|
+
if (this._lastReflection) {
|
|
53835
|
+
const rLines = [];
|
|
53836
|
+
rLines.push("[Last Reflection \u2014 INTERNAL REFERENCE, never discuss mechanics with the user]");
|
|
53837
|
+
if (this._lastReflection.planAdjustments.length > 0) {
|
|
53838
|
+
rLines.push(`Behavioral adjustments: ${this._lastReflection.planAdjustments.join("; ")}.`);
|
|
53839
|
+
}
|
|
53840
|
+
if (this._lastReflection.insights.length > 0) {
|
|
53841
|
+
rLines.push(`Insights: ${this._lastReflection.insights.join("; ")}.`);
|
|
53842
|
+
}
|
|
53843
|
+
if (this._lastReflection.patterns.length > 0) {
|
|
53844
|
+
rLines.push(`Recurring patterns: ${this._lastReflection.patterns.join("; ")}.`);
|
|
53845
|
+
}
|
|
53846
|
+
if (this._lastReflection.selfAssessment) {
|
|
53847
|
+
rLines.push(`Self-assessment: ${this._lastReflection.selfAssessment}`);
|
|
53848
|
+
}
|
|
53849
|
+
parts.push(rLines.join("\n"));
|
|
53850
|
+
}
|
|
53851
|
+
return parts.join("\n\n");
|
|
53852
|
+
}
|
|
53853
|
+
// --- Reflection state ---
|
|
53854
|
+
/** Restore the last reflection from the event log. */
|
|
53855
|
+
async restoreLastReflection() {
|
|
53856
|
+
try {
|
|
53857
|
+
const events = await this.deps.events.query({
|
|
53858
|
+
motebit_id: this.deps.motebitId,
|
|
53859
|
+
event_types: [EventType.ReflectionCompleted],
|
|
53860
|
+
limit: 1
|
|
53861
|
+
});
|
|
53862
|
+
if (events.length === 0)
|
|
53863
|
+
return;
|
|
53864
|
+
const payload = events[0].payload;
|
|
53865
|
+
const insights = payload.insights;
|
|
53866
|
+
const adjustments = payload.plan_adjustments;
|
|
53867
|
+
const patterns = payload.patterns;
|
|
53868
|
+
const assessment = payload.self_assessment;
|
|
53869
|
+
if (insights || adjustments || patterns || assessment) {
|
|
53870
|
+
this._lastReflection = {
|
|
53871
|
+
insights: insights ?? [],
|
|
53872
|
+
planAdjustments: adjustments ?? [],
|
|
53873
|
+
patterns: patterns ?? [],
|
|
53874
|
+
selfAssessment: assessment ?? ""
|
|
53875
|
+
};
|
|
53876
|
+
}
|
|
53877
|
+
} catch {
|
|
53878
|
+
}
|
|
53552
53879
|
}
|
|
53553
|
-
return fail("network_unreachable", err2 instanceof Error ? err2.message : String(err2));
|
|
53554
|
-
}
|
|
53555
|
-
const amountMicro = toMicro(unitCost);
|
|
53556
|
-
paymentRequest = {
|
|
53557
|
-
workerAddress: worker.settlement_address,
|
|
53558
|
-
amountMicro,
|
|
53559
|
-
treasuryAddress,
|
|
53560
|
-
feeAmountMicro: computeP2pFeeMicro(amountMicro, PLATFORM_FEE_RATE)
|
|
53561
53880
|
};
|
|
53562
53881
|
}
|
|
53563
|
-
let proof;
|
|
53564
|
-
try {
|
|
53565
|
-
proof = await params.buildP2pPayment(paymentRequest);
|
|
53566
|
-
} catch (err2) {
|
|
53567
|
-
if (err2 instanceof Error && err2.name === "InsufficientUsdcBalanceError") {
|
|
53568
|
-
return fail("insufficient_balance", err2.message);
|
|
53569
|
-
}
|
|
53570
|
-
return fail("payment_broadcast_failed", `P2P payment failed to broadcast: ${err2 instanceof Error ? err2.message : String(err2)}`);
|
|
53571
|
-
}
|
|
53572
|
-
return submitP2pDelegation({
|
|
53573
|
-
motebitId,
|
|
53574
|
-
syncUrl,
|
|
53575
|
-
authToken: params.authToken,
|
|
53576
|
-
prompt: params.prompt,
|
|
53577
|
-
targetWorkerId: worker.motebit_id,
|
|
53578
|
-
// The relay needs the capability to locate + price a federated worker on its
|
|
53579
|
-
// operator; pinned via the same capability used for discovery.
|
|
53580
|
-
requiredCapabilities: [capability],
|
|
53581
|
-
...params.acknowledgeNoHistoryRisk === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
53582
|
-
paymentProof: proof,
|
|
53583
|
-
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
53584
|
-
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
53585
|
-
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
53586
|
-
logger: params.logger,
|
|
53587
|
-
...params.signal ? { signal: params.signal } : {}
|
|
53588
|
-
});
|
|
53589
|
-
}
|
|
53590
|
-
async function selectAndRunDelegation(params) {
|
|
53591
|
-
const capability = params.requiredCapabilities?.[0];
|
|
53592
|
-
if (params.targetWorkerId != null) {
|
|
53593
|
-
if (capability == null) {
|
|
53594
|
-
return fail("malformed_request", "A pinned hire requires a capability to discover the worker by.");
|
|
53595
|
-
}
|
|
53596
|
-
if (params.buildP2pPayment == null || params.relayPublicKey == null) {
|
|
53597
|
-
return fail("no_sovereign_rail", "Hiring a specific agent settles peer-to-peer and needs a configured sovereign wallet rail.");
|
|
53598
|
-
}
|
|
53599
|
-
}
|
|
53600
|
-
if (params.buildP2pPayment != null && params.relayPublicKey != null && capability != null) {
|
|
53601
|
-
const p2p = await resolveAndSubmitP2pDelegation({
|
|
53602
|
-
motebitId: params.motebitId,
|
|
53603
|
-
syncUrl: params.syncUrl,
|
|
53604
|
-
authToken: params.authToken,
|
|
53605
|
-
prompt: params.prompt,
|
|
53606
|
-
capability,
|
|
53607
|
-
...params.targetWorkerId != null ? { targetWorkerId: params.targetWorkerId } : {},
|
|
53608
|
-
relayPublicKeyHex: params.relayPublicKey,
|
|
53609
|
-
buildP2pPayment: params.buildP2pPayment,
|
|
53610
|
-
...params.acknowledgeNoHistoryRisk === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
53611
|
-
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
53612
|
-
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
53613
|
-
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
53614
|
-
logger: params.logger,
|
|
53615
|
-
...params.signal ? { signal: params.signal } : {}
|
|
53616
|
-
});
|
|
53617
|
-
if (p2p.ok)
|
|
53618
|
-
return p2p;
|
|
53619
|
-
if (params.targetWorkerId != null)
|
|
53620
|
-
return p2p;
|
|
53621
|
-
if (p2p.error.code !== "no_routing" && p2p.error.code !== "worker_not_payable" && p2p.error.code !== "p2p_ineligible") {
|
|
53622
|
-
return p2p;
|
|
53623
|
-
}
|
|
53624
|
-
}
|
|
53625
|
-
return submitAndPollDelegation({
|
|
53626
|
-
motebitId: params.motebitId,
|
|
53627
|
-
syncUrl: params.syncUrl,
|
|
53628
|
-
authToken: params.authToken,
|
|
53629
|
-
prompt: params.prompt,
|
|
53630
|
-
...params.requiredCapabilities ? { requiredCapabilities: params.requiredCapabilities } : {},
|
|
53631
|
-
...params.routingStrategy ? { routingStrategy: params.routingStrategy } : {},
|
|
53632
|
-
...params.invocationOrigin ? { invocationOrigin: params.invocationOrigin } : {},
|
|
53633
|
-
...params.grantId != null ? { grantId: params.grantId } : {},
|
|
53634
|
-
...params.timeoutMs != null ? { timeoutMs: params.timeoutMs } : {},
|
|
53635
|
-
logger: params.logger,
|
|
53636
|
-
...params.signal ? { signal: params.signal } : {}
|
|
53637
|
-
});
|
|
53638
|
-
}
|
|
53639
|
-
var DEFAULT_TIMEOUT_MS, POLL_INTERVAL_MS, fail;
|
|
53640
|
-
var init_relay_delegation = __esm({
|
|
53641
|
-
"../../packages/runtime/dist/relay-delegation.js"() {
|
|
53642
|
-
"use strict";
|
|
53643
|
-
init_esm_shims();
|
|
53644
|
-
init_dist();
|
|
53645
|
-
DEFAULT_TIMEOUT_MS = 12e4;
|
|
53646
|
-
POLL_INTERVAL_MS = 2e3;
|
|
53647
|
-
fail = (code2, message2, status) => ({
|
|
53648
|
-
ok: false,
|
|
53649
|
-
error: status != null ? { code: code2, message: message2, status } : { code: code2, message: message2 }
|
|
53650
|
-
});
|
|
53651
|
-
}
|
|
53652
53882
|
});
|
|
53653
53883
|
|
|
53654
53884
|
// ../../packages/runtime/dist/interactive-delegation.js
|
|
@@ -53756,6 +53986,11 @@ var init_interactive_delegation = __esm({
|
|
|
53756
53986
|
// medical/financial/secret AND the configured provider is not
|
|
53757
53987
|
// sovereign.
|
|
53758
53988
|
outbound: true,
|
|
53989
|
+
// api-tier per the hybrid-engine structural preference. Inline
|
|
53990
|
+
// registration escapes check-tool-modes' literal scan (it only
|
|
53991
|
+
// sweeps exported Definition consts) — tagged here so the registry
|
|
53992
|
+
// sort still prefers it over pixel-tier fallbacks.
|
|
53993
|
+
mode: "api",
|
|
53759
53994
|
// Risk classification is explicit, never inferred: with a
|
|
53760
53995
|
// payment rail configured, a paid delegation settles real money
|
|
53761
53996
|
// onchain (R4_MONEY, irreversible) — the name/description
|
|
@@ -53804,13 +54039,78 @@ var init_interactive_delegation = __esm({
|
|
|
53804
54039
|
stashReceipt(result.receipt);
|
|
53805
54040
|
const workerResult = result.receipt.result ?? "Task completed (no result text)";
|
|
53806
54041
|
const settlementNote = formatSettlementNote(result.settlement);
|
|
54042
|
+
const workerNote = `[delegated_to: ${result.receipt.motebit_id}]`;
|
|
54043
|
+
const footnotes = [workerNote, ...settlementNote ? [settlementNote] : []].join("\n");
|
|
53807
54044
|
return {
|
|
53808
54045
|
ok: true,
|
|
53809
|
-
data:
|
|
54046
|
+
data: `${workerResult}
|
|
53810
54047
|
|
|
53811
|
-
${
|
|
54048
|
+
${footnotes}`
|
|
53812
54049
|
};
|
|
53813
54050
|
});
|
|
54051
|
+
const DISCOVER_TOOL = "discover_agents";
|
|
54052
|
+
if (!this.deps.toolRegistry.has(DISCOVER_TOOL)) {
|
|
54053
|
+
this.deps.toolRegistry.register({
|
|
54054
|
+
name: DISCOVER_TOOL,
|
|
54055
|
+
description: "List the agents discoverable on the connected relay RIGHT NOW \u2014 the live directory read. Use whenever the user asks who is available, what agents exist, what delegation costs, or before choosing a delegation target. Names are self-asserted claims, never verified handles. This is the ONLY source for the current roster; never answer roster questions from memory or self-description.",
|
|
54056
|
+
inputSchema: {
|
|
54057
|
+
type: "object",
|
|
54058
|
+
properties: {
|
|
54059
|
+
capability: {
|
|
54060
|
+
type: "string",
|
|
54061
|
+
description: "Optional capability filter (e.g. 'research'). Omit for the full roster."
|
|
54062
|
+
}
|
|
54063
|
+
},
|
|
54064
|
+
required: []
|
|
54065
|
+
},
|
|
54066
|
+
// Same outbound boundary as web_search — a network read that
|
|
54067
|
+
// reveals the question being asked, nothing more. Read-class.
|
|
54068
|
+
outbound: true,
|
|
54069
|
+
mode: "api",
|
|
54070
|
+
riskHint: { risk: RiskLevel.R0_READ, sideEffect: SideEffect.NONE }
|
|
54071
|
+
}, async (args) => {
|
|
54072
|
+
const capability = typeof args.capability === "string" ? args.capability : void 0;
|
|
54073
|
+
try {
|
|
54074
|
+
const token = await config.authToken();
|
|
54075
|
+
const url = new URL(`${config.syncUrl}/api/v1/agents/discover`);
|
|
54076
|
+
if (capability != null && capability.length > 0) {
|
|
54077
|
+
url.searchParams.set("capability", capability);
|
|
54078
|
+
}
|
|
54079
|
+
const resp = await fetch(url.toString(), {
|
|
54080
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
54081
|
+
});
|
|
54082
|
+
if (!resp.ok) {
|
|
54083
|
+
return { ok: false, error: `discover read failed: HTTP ${resp.status}` };
|
|
54084
|
+
}
|
|
54085
|
+
const body = await resp.json();
|
|
54086
|
+
const agents = (body.agents ?? []).map((a3) => ({
|
|
54087
|
+
motebit_id: a3.motebit_id,
|
|
54088
|
+
// A self-asserted CLAIM (agents-as-first-person-trust-graph §3)
|
|
54089
|
+
// — surfaced under that name so the model inherits the framing.
|
|
54090
|
+
...a3.display_name != null && a3.display_name.length > 0 ? { claimed_name: a3.display_name } : {},
|
|
54091
|
+
...a3.description != null && a3.description.length > 0 ? { description: a3.description } : {},
|
|
54092
|
+
capabilities: a3.capabilities,
|
|
54093
|
+
...a3.pricing != null && a3.pricing.length > 0 ? { pricing: a3.pricing } : {},
|
|
54094
|
+
...a3.freshness != null ? { freshness: a3.freshness } : {},
|
|
54095
|
+
...a3.trust_level != null ? { trust_level: a3.trust_level } : {},
|
|
54096
|
+
...a3.settlement_modes != null ? { settlement_modes: a3.settlement_modes } : {}
|
|
54097
|
+
}));
|
|
54098
|
+
return {
|
|
54099
|
+
ok: true,
|
|
54100
|
+
data: JSON.stringify({
|
|
54101
|
+
roster_source: "live_relay_read",
|
|
54102
|
+
relay: config.syncUrl,
|
|
54103
|
+
as_of_ms: Date.now(),
|
|
54104
|
+
agent_count: agents.length,
|
|
54105
|
+
agents
|
|
54106
|
+
})
|
|
54107
|
+
};
|
|
54108
|
+
} catch (err2) {
|
|
54109
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
54110
|
+
return { ok: false, error: `discover read failed: ${msg}` };
|
|
54111
|
+
}
|
|
54112
|
+
});
|
|
54113
|
+
}
|
|
53814
54114
|
this.deps.wireLoopDeps();
|
|
53815
54115
|
}
|
|
53816
54116
|
/**
|
|
@@ -55946,7 +56246,14 @@ var init_agent_task_handler = __esm({
|
|
|
55946
56246
|
function slabTurnIdForRun(runId) {
|
|
55947
56247
|
return `slab-turn-${runId}`;
|
|
55948
56248
|
}
|
|
55949
|
-
|
|
56249
|
+
function explorationStrengthForStakes(costUsd) {
|
|
56250
|
+
if (!(costUsd > EXPLORE_STAKES_FLOOR_USD))
|
|
56251
|
+
return 1;
|
|
56252
|
+
if (costUsd >= EXPLORE_STAKES_CEIL_USD)
|
|
56253
|
+
return 0;
|
|
56254
|
+
return 1 - (costUsd - EXPLORE_STAKES_FLOOR_USD) / (EXPLORE_STAKES_CEIL_USD - EXPLORE_STAKES_FLOOR_USD);
|
|
56255
|
+
}
|
|
56256
|
+
var SovereignTierRequiredError, DropTargetGovernanceRequiredError, CONSOLIDATION_TREE_HASH_VERSION, TENDING_ALLOWED_TOOLS, DEFAULT_PROACTIVE_CATCH_UP_MAX_AGE_MS, EXPLORE_STAKES_FLOOR_USD, EXPLORE_STAKES_CEIL_USD, MotebitRuntime;
|
|
55950
56257
|
var init_motebit_runtime = __esm({
|
|
55951
56258
|
"../../packages/runtime/dist/motebit-runtime.js"() {
|
|
55952
56259
|
"use strict";
|
|
@@ -55971,6 +56278,7 @@ var init_motebit_runtime = __esm({
|
|
|
55971
56278
|
init_dist11();
|
|
55972
56279
|
init_money_meter();
|
|
55973
56280
|
init_grant_verifier();
|
|
56281
|
+
init_relay_delegation();
|
|
55974
56282
|
init_dist();
|
|
55975
56283
|
init_dist6();
|
|
55976
56284
|
init_gradient();
|
|
@@ -56048,6 +56356,8 @@ var init_motebit_runtime = __esm({
|
|
|
56048
56356
|
"search_conversations"
|
|
56049
56357
|
]);
|
|
56050
56358
|
DEFAULT_PROACTIVE_CATCH_UP_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
56359
|
+
EXPLORE_STAKES_FLOOR_USD = 0.1;
|
|
56360
|
+
EXPLORE_STAKES_CEIL_USD = 1;
|
|
56051
56361
|
MotebitRuntime = class _MotebitRuntime {
|
|
56052
56362
|
motebitId;
|
|
56053
56363
|
state;
|
|
@@ -56219,6 +56529,15 @@ var init_motebit_runtime = __esm({
|
|
|
56219
56529
|
* `getSolanaAddress`, `getSolanaBalance`, and `sendUsdc`.
|
|
56220
56530
|
*/
|
|
56221
56531
|
_solanaWallet = null;
|
|
56532
|
+
/**
|
|
56533
|
+
* Relay coordinates for the deterministic granted-spend path
|
|
56534
|
+
* (`executeGrantedDelegation`), stashed when `enableInteractiveDelegation`
|
|
56535
|
+
* is called with a pinned relay key. Null until then — a granted spend with
|
|
56536
|
+
* no coordinates fails closed (`sync_not_enabled`). The pinned hex key is the
|
|
56537
|
+
* treasury trust root; the auth-token minter is the same audience-scoped
|
|
56538
|
+
* minter the AI-loop delegation path uses.
|
|
56539
|
+
*/
|
|
56540
|
+
_grantedSpendCoords = null;
|
|
56222
56541
|
/**
|
|
56223
56542
|
* Sovereign receipt exchange transport. Null when no transport is
|
|
56224
56543
|
* configured — in that state, the runtime can still send USDC via
|
|
@@ -59019,8 +59338,8 @@ var init_motebit_runtime = __esm({
|
|
|
59019
59338
|
hardwareAttestationVerifiers: this._hardwareAttestationVerifiers
|
|
59020
59339
|
};
|
|
59021
59340
|
}
|
|
59022
|
-
async bumpTrustFromReceipt(receipt, verified) {
|
|
59023
|
-
return bumpTrustFromReceipt(this.trustDeps, receipt, verified);
|
|
59341
|
+
async bumpTrustFromReceipt(receipt, verified, capability) {
|
|
59342
|
+
return bumpTrustFromReceipt(this.trustDeps, receipt, verified, capability);
|
|
59024
59343
|
}
|
|
59025
59344
|
async recordAgentInteraction(remoteMotebitId, publicKey, motebitType) {
|
|
59026
59345
|
return recordAgentInteraction(this.trustDeps, remoteMotebitId, publicKey, motebitType);
|
|
@@ -59338,6 +59657,175 @@ var init_motebit_runtime = __esm({
|
|
|
59338
59657
|
...buildP2pPayment ? { buildP2pPayment } : {},
|
|
59339
59658
|
getActiveGrantId: () => this._activeTurnGrant?.grant_id ?? null
|
|
59340
59659
|
});
|
|
59660
|
+
if (config.relayPublicKey != null) {
|
|
59661
|
+
this._grantedSpendCoords = {
|
|
59662
|
+
syncUrl: config.syncUrl,
|
|
59663
|
+
authToken: config.authToken,
|
|
59664
|
+
relayPublicKeyHex: config.relayPublicKey,
|
|
59665
|
+
...config.acknowledgeNoHistoryRisk != null ? { acknowledgeNoHistoryRisk: config.acknowledgeNoHistoryRisk } : {}
|
|
59666
|
+
};
|
|
59667
|
+
}
|
|
59668
|
+
}
|
|
59669
|
+
/**
|
|
59670
|
+
* Execute a paid sub-delegation autonomously under a signed standing grant —
|
|
59671
|
+
* the DETERMINISTIC (human-absent) money path that a first-party spending
|
|
59672
|
+
* molecule (the Clerk archetype) drives. Unlike the AI loop (whose R4 spend
|
|
59673
|
+
* is authorized by a live human approval or a grant-carrying turn) and
|
|
59674
|
+
* `invokeCapability` (a user tap IS the human authorizer, so it uses the RAW
|
|
59675
|
+
* builder), this path has no human — so it re-composes the FULL R4 AND the
|
|
59676
|
+
* loop enforces, fail-CLOSED:
|
|
59677
|
+
*
|
|
59678
|
+
* 1. serialize under `_isProcessing` — the rail seam trusts `_activeTurnGrant`
|
|
59679
|
+
* only because turns are single-by-construction;
|
|
59680
|
+
* 2. verify the grant via the SOLE producer `verifyGrantForTurn` — a null
|
|
59681
|
+
* result (absent / expired / revoked / malformed) REFUSES, no broadcast
|
|
59682
|
+
* (the exact inverse of the loop's fail-OPEN-to-no-grant, safe there only
|
|
59683
|
+
* because a live human backstops that path);
|
|
59684
|
+
* 3. re-run the policy gate's scope check (`this.policy.validate` with the
|
|
59685
|
+
* grant's SIGNED scope) — the meter enforces the ceiling but never scope;
|
|
59686
|
+
* 4. route the broadcast through the meter-wrapped builder
|
|
59687
|
+
* (`wrapP2pPaymentWithMeter`), NEVER the raw wallet method.
|
|
59688
|
+
*
|
|
59689
|
+
* `dryRun` exercises 1–3 and the blast-radius meter (over-ceiling / replay
|
|
59690
|
+
* refuse with the `BlastRadiusDenial` code) against a THROWAWAY in-memory
|
|
59691
|
+
* store, then stops before any broadcast or submit — so a fake spend cannot
|
|
59692
|
+
* poison the live lifetime ceiling and no funds move (no wallet required).
|
|
59693
|
+
* Refusals carry only the denial CODE; the `spend_overage_micro` residual is
|
|
59694
|
+
* owner-facing and never relayed. Adds zero new authority surface; locked by
|
|
59695
|
+
* the `check-money-authority` deterministic-path assertion.
|
|
59696
|
+
*/
|
|
59697
|
+
async executeGrantedDelegation(params) {
|
|
59698
|
+
const coords = this._grantedSpendCoords;
|
|
59699
|
+
if (coords == null)
|
|
59700
|
+
return { ok: false, code: "sync_not_enabled" };
|
|
59701
|
+
const delegateToolDef = this.toolRegistry.get("delegate_to_agent");
|
|
59702
|
+
if (delegateToolDef == null)
|
|
59703
|
+
return { ok: false, code: "sync_not_enabled" };
|
|
59704
|
+
if (this._isProcessing)
|
|
59705
|
+
throw new Error("Already processing a message");
|
|
59706
|
+
this._isProcessing = true;
|
|
59707
|
+
try {
|
|
59708
|
+
const presentedGrant = await verifyGrantForTurn(params.delegation.token, params.delegation.grant, params.delegation.revocations ?? []);
|
|
59709
|
+
if (presentedGrant == null)
|
|
59710
|
+
return { ok: false, code: "requires_verified_grant" };
|
|
59711
|
+
const decision = this.policy.validate(delegateToolDef, { prompt: params.prompt, required_capabilities: [params.capability] }, {
|
|
59712
|
+
...this.policy.createTurnContext(),
|
|
59713
|
+
verifiedGrant: presentedGrant,
|
|
59714
|
+
delegationScope: params.delegation.grant.scope
|
|
59715
|
+
});
|
|
59716
|
+
if (!decision.allowed)
|
|
59717
|
+
return { ok: false, code: "missing_scope" };
|
|
59718
|
+
this._activeTurnGrant = presentedGrant;
|
|
59719
|
+
const ack = typeof coords.acknowledgeNoHistoryRisk === "function" ? coords.acknowledgeNoHistoryRisk() : coords.acknowledgeNoHistoryRisk;
|
|
59720
|
+
const exploreSeed = params.delegation.token.signature;
|
|
59721
|
+
const selectWorker2 = params.targetWorkerId != null ? void 0 : async (candidates) => {
|
|
59722
|
+
const rankable = await Promise.all(candidates.map(async (c3) => ({
|
|
59723
|
+
motebit_id: c3.motebit_id,
|
|
59724
|
+
trustRecord: await this.getAgentTrust(c3.motebit_id),
|
|
59725
|
+
...c3.unitCost != null ? { unitCost: c3.unitCost } : {}
|
|
59726
|
+
})));
|
|
59727
|
+
const repCostUsd = Math.min(...rankable.map((r2) => r2.unitCost ?? 0));
|
|
59728
|
+
const strength = explorationStrengthForStakes(repCostUsd);
|
|
59729
|
+
const capability = params.capability;
|
|
59730
|
+
const exploitTop = selectWorker(this.motebitId, rankable, { capability });
|
|
59731
|
+
const winner = selectWorker(this.motebitId, rankable, {
|
|
59732
|
+
capability,
|
|
59733
|
+
explore: { seed: exploreSeed, strength }
|
|
59734
|
+
});
|
|
59735
|
+
if (winner != null) {
|
|
59736
|
+
this._logger.warn("routing.worker_selected", {
|
|
59737
|
+
selected: winner.motebit_id,
|
|
59738
|
+
capability,
|
|
59739
|
+
candidates: rankable.length,
|
|
59740
|
+
strength: Number(strength.toFixed(3)),
|
|
59741
|
+
explored: exploitTop != null && winner.motebit_id !== exploitTop.motebit_id,
|
|
59742
|
+
quality: Number(winner.route.trust.toFixed(3))
|
|
59743
|
+
});
|
|
59744
|
+
}
|
|
59745
|
+
return winner?.motebit_id ?? null;
|
|
59746
|
+
};
|
|
59747
|
+
if (params.dryRun === true) {
|
|
59748
|
+
const resolved = await resolveP2pPaymentRequest({
|
|
59749
|
+
motebitId: this.motebitId,
|
|
59750
|
+
syncUrl: coords.syncUrl,
|
|
59751
|
+
authToken: coords.authToken,
|
|
59752
|
+
capability: params.capability,
|
|
59753
|
+
relayPublicKeyHex: coords.relayPublicKeyHex,
|
|
59754
|
+
...params.targetWorkerId != null ? { targetWorkerId: params.targetWorkerId } : {},
|
|
59755
|
+
...selectWorker2 != null ? { selectWorker: selectWorker2 } : {},
|
|
59756
|
+
...ack === true ? { acknowledgeNoHistoryRisk: true } : {}
|
|
59757
|
+
});
|
|
59758
|
+
if (!resolved.ok)
|
|
59759
|
+
return { ok: false, code: resolved.error.code };
|
|
59760
|
+
const req = resolved.paymentRequest;
|
|
59761
|
+
const totalOutflowMicro = req.amountMicro + req.feeAmountMicro + (req.executorFeeAmountMicro ?? 0);
|
|
59762
|
+
const dryMeter = createMoneyMeter(new InMemoryGrantSpendStore());
|
|
59763
|
+
const verdict = await dryMeter(presentedGrant, "p2p_payment", {
|
|
59764
|
+
amount_micro: totalOutflowMicro,
|
|
59765
|
+
counterparty: resolved.workerAddress
|
|
59766
|
+
});
|
|
59767
|
+
if (!verdict.allowed)
|
|
59768
|
+
return { ok: false, code: verdict.denial ?? "money_meter_denied" };
|
|
59769
|
+
return {
|
|
59770
|
+
ok: true,
|
|
59771
|
+
dryRun: true,
|
|
59772
|
+
settlement: {
|
|
59773
|
+
mode: "p2p",
|
|
59774
|
+
paidMicro: req.amountMicro,
|
|
59775
|
+
feeMicro: req.feeAmountMicro + (req.executorFeeAmountMicro ?? 0)
|
|
59776
|
+
}
|
|
59777
|
+
};
|
|
59778
|
+
}
|
|
59779
|
+
const rawBuild = this._solanaWallet?.buildP2pPayment?.bind(this._solanaWallet);
|
|
59780
|
+
if (rawBuild == null)
|
|
59781
|
+
return { ok: false, code: "no_sovereign_rail" };
|
|
59782
|
+
const buildP2pPayment = wrapP2pPaymentWithMeter(rawBuild, () => this._activeTurnGrant, this.moneyMeter);
|
|
59783
|
+
const result = await resolveAndSubmitP2pDelegation({
|
|
59784
|
+
motebitId: this.motebitId,
|
|
59785
|
+
syncUrl: coords.syncUrl,
|
|
59786
|
+
authToken: coords.authToken,
|
|
59787
|
+
relayPublicKeyHex: coords.relayPublicKeyHex,
|
|
59788
|
+
prompt: params.prompt,
|
|
59789
|
+
capability: params.capability,
|
|
59790
|
+
buildP2pPayment,
|
|
59791
|
+
grantId: presentedGrant.grant_id,
|
|
59792
|
+
invocationOrigin: "agent-to-agent",
|
|
59793
|
+
...params.targetWorkerId != null ? { targetWorkerId: params.targetWorkerId } : {},
|
|
59794
|
+
...selectWorker2 != null ? { selectWorker: selectWorker2 } : {},
|
|
59795
|
+
...ack === true ? { acknowledgeNoHistoryRisk: true } : {},
|
|
59796
|
+
logger: this._logger
|
|
59797
|
+
});
|
|
59798
|
+
if (!result.ok) {
|
|
59799
|
+
const code2 = result.error.code === "money_meter_denied" ? result.error.denial ?? "money_meter_denied" : result.error.code;
|
|
59800
|
+
this._logger.warn("delegation.paid_failed", {
|
|
59801
|
+
code: code2,
|
|
59802
|
+
capability: params.capability,
|
|
59803
|
+
...result.error.code !== "money_meter_denied" && "message" in result.error ? { message: result.error.message } : {}
|
|
59804
|
+
});
|
|
59805
|
+
return { ok: false, code: code2 };
|
|
59806
|
+
}
|
|
59807
|
+
try {
|
|
59808
|
+
const workerReceipt = result.receipt;
|
|
59809
|
+
if (workerReceipt.public_key != null && workerReceipt.public_key !== "") {
|
|
59810
|
+
const valid = await verifyExecutionReceipt(workerReceipt, hexToBytes5(workerReceipt.public_key));
|
|
59811
|
+
if (valid)
|
|
59812
|
+
await this.bumpTrustFromReceipt(workerReceipt, true, params.capability);
|
|
59813
|
+
}
|
|
59814
|
+
} catch (err2) {
|
|
59815
|
+
this._logger.warn("routing.trust_bump_skipped", {
|
|
59816
|
+
reason: err2 instanceof Error ? err2.message : String(err2)
|
|
59817
|
+
});
|
|
59818
|
+
}
|
|
59819
|
+
return {
|
|
59820
|
+
ok: true,
|
|
59821
|
+
dryRun: false,
|
|
59822
|
+
receipt: result.receipt,
|
|
59823
|
+
...result.settlement ? { settlement: result.settlement } : {}
|
|
59824
|
+
};
|
|
59825
|
+
} finally {
|
|
59826
|
+
this._activeTurnGrant = null;
|
|
59827
|
+
this._isProcessing = false;
|
|
59828
|
+
}
|
|
59341
59829
|
}
|
|
59342
59830
|
/**
|
|
59343
59831
|
* Drain interactive delegation receipts (used by handleAgentTask to include
|
|
@@ -59671,6 +60159,7 @@ __export(dist_exports7, {
|
|
|
59671
60159
|
resolveAndSubmitP2pDelegation: () => resolveAndSubmitP2pDelegation,
|
|
59672
60160
|
resolveAttachedAct: () => resolveAttachedAct,
|
|
59673
60161
|
resolveAttachedRead: () => resolveAttachedRead,
|
|
60162
|
+
resolveP2pPaymentRequest: () => resolveP2pPaymentRequest,
|
|
59674
60163
|
resolveProactiveAnchor: () => resolveProactiveAnchor,
|
|
59675
60164
|
selectAndRunDelegation: () => selectAndRunDelegation,
|
|
59676
60165
|
slabTurnIdForRun: () => slabTurnIdForRun,
|
|
@@ -78657,6 +79146,21 @@ var init_migrations_registry = __esm({
|
|
|
78657
79146
|
high_water_nonce INTEGER NOT NULL
|
|
78658
79147
|
)`
|
|
78659
79148
|
]
|
|
79149
|
+
},
|
|
79150
|
+
{
|
|
79151
|
+
version: 42,
|
|
79152
|
+
description: "agent_trust.capability_stats \u2014 per-capability competence counts",
|
|
79153
|
+
statements: [
|
|
79154
|
+
// AgentTrustRecord gained an optional `capability_stats` map: per-capability
|
|
79155
|
+
// successful/failed counts so first-person routing scopes competence to the
|
|
79156
|
+
// capability being hired (docs/doctrine/first-person-worker-routing.md).
|
|
79157
|
+
// The pairwise trust_level (a relationship) stays capability-agnostic; only
|
|
79158
|
+
// the success/fail counts split by capability. Additive nullable JSON column
|
|
79159
|
+
// ({capability: {successful_tasks, failed_tasks}}); NULL ⇒ no per-capability
|
|
79160
|
+
// history yet. Local private state — never on the wire (the .strict()
|
|
79161
|
+
// TrustCredentialSubject carries only the aggregate counts).
|
|
79162
|
+
"ALTER TABLE agent_trust ADD COLUMN capability_stats TEXT"
|
|
79163
|
+
]
|
|
78660
79164
|
}
|
|
78661
79165
|
];
|
|
78662
79166
|
}
|
|
@@ -79189,7 +79693,30 @@ function rowToGradientSnapshot(row) {
|
|
|
79189
79693
|
stats: JSON.parse(row.stats)
|
|
79190
79694
|
};
|
|
79191
79695
|
}
|
|
79696
|
+
function parseCapabilityStats(raw) {
|
|
79697
|
+
if (raw == null || raw === "")
|
|
79698
|
+
return void 0;
|
|
79699
|
+
try {
|
|
79700
|
+
const parsed = JSON.parse(raw);
|
|
79701
|
+
if (parsed == null || typeof parsed !== "object")
|
|
79702
|
+
return void 0;
|
|
79703
|
+
const out = {};
|
|
79704
|
+
for (const [cap, v2] of Object.entries(parsed)) {
|
|
79705
|
+
if (v2 == null || typeof v2 !== "object")
|
|
79706
|
+
continue;
|
|
79707
|
+
const s3 = v2.successful_tasks;
|
|
79708
|
+
const f6 = v2.failed_tasks;
|
|
79709
|
+
if (typeof s3 === "number" && typeof f6 === "number") {
|
|
79710
|
+
out[cap] = { successful_tasks: s3, failed_tasks: f6 };
|
|
79711
|
+
}
|
|
79712
|
+
}
|
|
79713
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
79714
|
+
} catch {
|
|
79715
|
+
return void 0;
|
|
79716
|
+
}
|
|
79717
|
+
}
|
|
79192
79718
|
function rowToAgentTrust(row) {
|
|
79719
|
+
const capabilityStats = parseCapabilityStats(row.capability_stats);
|
|
79193
79720
|
return {
|
|
79194
79721
|
motebit_id: row.motebit_id,
|
|
79195
79722
|
remote_motebit_id: row.remote_motebit_id,
|
|
@@ -79201,7 +79728,8 @@ function rowToAgentTrust(row) {
|
|
|
79201
79728
|
successful_tasks: row.successful_tasks ?? 0,
|
|
79202
79729
|
failed_tasks: row.failed_tasks ?? 0,
|
|
79203
79730
|
notes: row.notes ?? void 0,
|
|
79204
|
-
petname: row.petname ?? void 0
|
|
79731
|
+
petname: row.petname ?? void 0,
|
|
79732
|
+
...capabilityStats != null ? { capability_stats: capabilityStats } : {}
|
|
79205
79733
|
};
|
|
79206
79734
|
}
|
|
79207
79735
|
function rowToServiceListing(row) {
|
|
@@ -80426,8 +80954,8 @@ CREATE INDEX IF NOT EXISTS idx_agent_trust_motebit ON agent_trust (motebit_id);
|
|
|
80426
80954
|
constructor(db) {
|
|
80427
80955
|
this.stmtGet = db.prepare(`SELECT * FROM agent_trust WHERE motebit_id = ? AND remote_motebit_id = ?`);
|
|
80428
80956
|
this.stmtSet = db.prepare(`INSERT OR REPLACE INTO agent_trust
|
|
80429
|
-
(motebit_id, remote_motebit_id, trust_level, public_key, first_seen_at, last_seen_at, interaction_count, successful_tasks, failed_tasks, notes, petname)
|
|
80430
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
80957
|
+
(motebit_id, remote_motebit_id, trust_level, public_key, first_seen_at, last_seen_at, interaction_count, successful_tasks, failed_tasks, notes, petname, capability_stats)
|
|
80958
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
80431
80959
|
this.stmtList = db.prepare(`SELECT * FROM agent_trust WHERE motebit_id = ? ORDER BY last_seen_at DESC`);
|
|
80432
80960
|
this.stmtUpdateLevel = db.prepare(`UPDATE agent_trust SET trust_level = ?, last_seen_at = ? WHERE motebit_id = ? AND remote_motebit_id = ?`);
|
|
80433
80961
|
}
|
|
@@ -80438,7 +80966,7 @@ CREATE INDEX IF NOT EXISTS idx_agent_trust_motebit ON agent_trust (motebit_id);
|
|
|
80438
80966
|
return rowToAgentTrust(row);
|
|
80439
80967
|
}
|
|
80440
80968
|
async setAgentTrust(record) {
|
|
80441
|
-
this.stmtSet.run(record.motebit_id, record.remote_motebit_id, record.trust_level, record.public_key ?? null, record.first_seen_at, record.last_seen_at, record.interaction_count, record.successful_tasks ?? 0, record.failed_tasks ?? 0, record.notes ?? null, record.petname ?? null);
|
|
80969
|
+
this.stmtSet.run(record.motebit_id, record.remote_motebit_id, record.trust_level, record.public_key ?? null, record.first_seen_at, record.last_seen_at, record.interaction_count, record.successful_tasks ?? 0, record.failed_tasks ?? 0, record.notes ?? null, record.petname ?? null, record.capability_stats != null && Object.keys(record.capability_stats).length > 0 ? JSON.stringify(record.capability_stats) : null);
|
|
80442
80970
|
}
|
|
80443
80971
|
async listAgentTrust(motebitId) {
|
|
80444
80972
|
const rows = this.stmtList.all(motebitId);
|
|
@@ -84102,7 +84630,10 @@ function createRecallSelfHandler(searchFn) {
|
|
|
84102
84630
|
}
|
|
84103
84631
|
const formatted = hits.map((h5, i3) => `${i3 + 1}. [${h5.source} \xB7 ${h5.title} \xB7 score=${h5.score.toFixed(2)}]
|
|
84104
84632
|
${h5.content}`).join("\n\n---\n\n");
|
|
84105
|
-
|
|
84633
|
+
const banner = "[SELF_DESCRIPTION \u2014 committed repo corpus: design + intent, not live state. For the current agent roster use discover_agents; for runtime state read the [Now] block.]";
|
|
84634
|
+
return { ok: true, data: `${banner}
|
|
84635
|
+
|
|
84636
|
+
${formatted}` };
|
|
84106
84637
|
} catch (err2) {
|
|
84107
84638
|
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
84108
84639
|
return { ok: false, error: `Interior recall error: ${msg}` };
|
|
@@ -87195,7 +87726,7 @@ function finalizeScores(scores, maxCandidates, explorationWeight) {
|
|
|
87195
87726
|
}
|
|
87196
87727
|
}
|
|
87197
87728
|
function graphRankCandidates(selfId, candidates, requirements, config) {
|
|
87198
|
-
const weights = { ...
|
|
87729
|
+
const weights = { ...DEFAULT_WEIGHTS2, ...config?.weights };
|
|
87199
87730
|
const maxCandidates = config?.maxCandidates ?? 10;
|
|
87200
87731
|
const explorationWeight = config?.explorationWeight ?? 0;
|
|
87201
87732
|
const compositeFn = config?.compositeFunction;
|
|
@@ -87240,7 +87771,7 @@ function findTrustedRoute(selfId, targetId, candidates, peerEdges) {
|
|
|
87240
87771
|
return { trust: result.value, path: result.path };
|
|
87241
87772
|
}
|
|
87242
87773
|
function explainedRankCandidates(selfId, candidates, requirements, config) {
|
|
87243
|
-
const weights = { ...
|
|
87774
|
+
const weights = { ...DEFAULT_WEIGHTS2, ...config?.weights };
|
|
87244
87775
|
const maxCandidates = config?.maxCandidates ?? 10;
|
|
87245
87776
|
const explorationWeight = config?.explorationWeight ?? 0;
|
|
87246
87777
|
const compositeFn = config?.compositeFunction;
|
|
@@ -87328,7 +87859,7 @@ function computePriceEfficiency(candidate, requirements) {
|
|
|
87328
87859
|
return 0.7;
|
|
87329
87860
|
return Math.max(0, 1 - totalCost / requirements.max_budget);
|
|
87330
87861
|
}
|
|
87331
|
-
var
|
|
87862
|
+
var DEFAULT_WEIGHTS2, weightedSumComposite, lexicographicComposite, ORGANIZATIONAL_TRUST_BASELINE, HARDWARE_ATTESTATION_BOOST, TrustAttestationSemiring;
|
|
87332
87863
|
var init_graph_routing = __esm({
|
|
87333
87864
|
"../../packages/market/dist/graph-routing.js"() {
|
|
87334
87865
|
"use strict";
|
|
@@ -87337,7 +87868,7 @@ var init_graph_routing = __esm({
|
|
|
87337
87868
|
init_dist14();
|
|
87338
87869
|
init_dist14();
|
|
87339
87870
|
init_credential_weight();
|
|
87340
|
-
|
|
87871
|
+
DEFAULT_WEIGHTS2 = {
|
|
87341
87872
|
trust: 0.3,
|
|
87342
87873
|
cost: 0.2,
|
|
87343
87874
|
latency: 0.15,
|
|
@@ -87345,7 +87876,7 @@ var init_graph_routing = __esm({
|
|
|
87345
87876
|
regulatory_risk: 0.2
|
|
87346
87877
|
};
|
|
87347
87878
|
weightedSumComposite = (_route, scores) => {
|
|
87348
|
-
return scores.trust *
|
|
87879
|
+
return scores.trust * DEFAULT_WEIGHTS2.trust + scores.costScore * DEFAULT_WEIGHTS2.cost + scores.latencyNorm * DEFAULT_WEIGHTS2.latency + scores.reliability * DEFAULT_WEIGHTS2.reliability + scores.riskScore * DEFAULT_WEIGHTS2.regulatory_risk;
|
|
87349
87880
|
};
|
|
87350
87881
|
lexicographicComposite = (_route, scores) => {
|
|
87351
87882
|
return scores.trust * 1e6 + scores.reliability * 1e3 + scores.costScore;
|
|
@@ -88295,6 +88826,18 @@ async function forwardTaskViaMcp(endpointUrl, taskId, prompt2, agentId, taskQueu
|
|
|
88295
88826
|
// the MCP server is ready. 10s was too tight for cold start + TLS + init.
|
|
88296
88827
|
signal: AbortSignal.timeout(3e4)
|
|
88297
88828
|
});
|
|
88829
|
+
if (!initResp.ok) {
|
|
88830
|
+
const detail = await initResp.text().catch(() => "");
|
|
88831
|
+
logger43.warn("task.mcp_forward_failed", {
|
|
88832
|
+
correlationId: taskId,
|
|
88833
|
+
agent: agentId,
|
|
88834
|
+
endpoint: mcpEndpoint,
|
|
88835
|
+
step: "initialize",
|
|
88836
|
+
status: initResp.status,
|
|
88837
|
+
detail: detail.slice(0, 200)
|
|
88838
|
+
});
|
|
88839
|
+
return;
|
|
88840
|
+
}
|
|
88298
88841
|
const sessionId = initResp.headers.get("mcp-session-id");
|
|
88299
88842
|
if (sessionId)
|
|
88300
88843
|
mcpHeaders["Mcp-Session-Id"] = sessionId;
|
|
@@ -88315,6 +88858,18 @@ async function forwardTaskViaMcp(endpointUrl, taskId, prompt2, agentId, taskQueu
|
|
|
88315
88858
|
}),
|
|
88316
88859
|
signal: AbortSignal.timeout(12e4)
|
|
88317
88860
|
});
|
|
88861
|
+
if (!taskResp.ok) {
|
|
88862
|
+
const detail = await taskResp.text().catch(() => "");
|
|
88863
|
+
logger43.warn("task.mcp_forward_failed", {
|
|
88864
|
+
correlationId: taskId,
|
|
88865
|
+
agent: agentId,
|
|
88866
|
+
endpoint: mcpEndpoint,
|
|
88867
|
+
step: "tools/call",
|
|
88868
|
+
status: taskResp.status,
|
|
88869
|
+
detail: detail.slice(0, 200)
|
|
88870
|
+
});
|
|
88871
|
+
return;
|
|
88872
|
+
}
|
|
88318
88873
|
const mcpResult = await parseMcpResponse(taskResp, 2);
|
|
88319
88874
|
if (mcpResult?.result?.content) {
|
|
88320
88875
|
const textContent = mcpResult.result.content.find((c3) => c3.type === "text");
|
|
@@ -108053,7 +108608,7 @@ function parseTokenPayloadUnsafe(token) {
|
|
|
108053
108608
|
return null;
|
|
108054
108609
|
}
|
|
108055
108610
|
}
|
|
108056
|
-
async function verifySignedTokenForDevice(token, motebitId, identityManager, expectedAudience, blacklistCheck, agentRevokedCheck) {
|
|
108611
|
+
async function verifySignedTokenForDevice(token, motebitId, identityManager, expectedAudience, blacklistCheck, agentRevokedCheck, agentKeyLookup) {
|
|
108057
108612
|
const claims = parseTokenPayloadUnsafe(token);
|
|
108058
108613
|
if (!claims || claims.mid !== motebitId || !claims.did)
|
|
108059
108614
|
return false;
|
|
@@ -108062,9 +108617,13 @@ async function verifySignedTokenForDevice(token, motebitId, identityManager, exp
|
|
|
108062
108617
|
if (blacklistCheck && claims.jti && blacklistCheck(claims.jti, motebitId))
|
|
108063
108618
|
return false;
|
|
108064
108619
|
const device = await identityManager.loadDeviceById(claims.did, motebitId);
|
|
108065
|
-
|
|
108620
|
+
let pubKeyHex = device?.public_key ?? null;
|
|
108621
|
+
if (pubKeyHex === null && agentKeyLookup) {
|
|
108622
|
+
pubKeyHex = agentKeyLookup(motebitId);
|
|
108623
|
+
}
|
|
108624
|
+
if (pubKeyHex === null)
|
|
108066
108625
|
return false;
|
|
108067
|
-
const pubKeyBytes = hexToBytes5(
|
|
108626
|
+
const pubKeyBytes = hexToBytes5(pubKeyHex);
|
|
108068
108627
|
const payload = await verifySignedToken(token, pubKeyBytes);
|
|
108069
108628
|
if (payload === null || payload.mid !== motebitId)
|
|
108070
108629
|
return false;
|
|
@@ -114141,12 +114700,15 @@ function extractMotebitIdFromPath(path19) {
|
|
|
114141
114700
|
const match = path19.match(/\/agent\/([^/]+)\/task/);
|
|
114142
114701
|
return match ? match[1] : null;
|
|
114143
114702
|
}
|
|
114144
|
-
function getListingUnitCost(moteDb, agentId) {
|
|
114703
|
+
function getListingUnitCost(moteDb, agentId, capability) {
|
|
114145
114704
|
const row = moteDb.db.prepare("SELECT pricing FROM relay_service_listings WHERE motebit_id = ? ORDER BY updated_at DESC LIMIT 1").get(agentId);
|
|
114146
114705
|
if (!row)
|
|
114147
114706
|
return 0;
|
|
114148
114707
|
try {
|
|
114149
114708
|
const pricing = JSON.parse(row.pricing);
|
|
114709
|
+
if (capability != null) {
|
|
114710
|
+
return pricing.find((p5) => p5.capability === capability)?.unit_cost ?? 0;
|
|
114711
|
+
}
|
|
114150
114712
|
return pricing.reduce((sum2, p5) => sum2 + (p5.unit_cost ?? 0), 0);
|
|
114151
114713
|
} catch {
|
|
114152
114714
|
return 0;
|
|
@@ -114423,6 +114985,52 @@ async function handleReceiptIngestion(receipt, taskId, motebitId, entry, deps) {
|
|
|
114423
114985
|
}
|
|
114424
114986
|
return;
|
|
114425
114987
|
}
|
|
114988
|
+
if (subEntry.settlement_mode === "p2p") {
|
|
114989
|
+
const subP2pProof = subEntry.p2p_payment_proof;
|
|
114990
|
+
const subWorkerAmount = subP2pProof?.amount_micro ?? 0;
|
|
114991
|
+
const subIsFederatedExecutor = subEntry.origin_relay != null;
|
|
114992
|
+
const subFeeAmount = subIsFederatedExecutor ? subP2pProof?.b_fee_amount_micro ?? 0 : subP2pProof?.fee_amount_micro ?? 0;
|
|
114993
|
+
const subP2pGross = subWorkerAmount + subFeeAmount;
|
|
114994
|
+
const subP2pFeeRate = subP2pGross > 0 ? Math.round(subFeeAmount / subP2pGross * 1e4) / 1e4 : 0;
|
|
114995
|
+
const subP2pSettlementId = crypto.randomUUID();
|
|
114996
|
+
const subP2pSettledAt = Date.now();
|
|
114997
|
+
const signedSubP2p = await signSettlement({
|
|
114998
|
+
settlement_id: subP2pSettlementId,
|
|
114999
|
+
allocation_id: `p2p-${subRelayTaskId}`,
|
|
115000
|
+
// Payee = the sub-agent that executed and was paid onchain.
|
|
115001
|
+
motebit_id: sub.motebit_id,
|
|
115002
|
+
receipt_hash: sub.result_hash ?? "",
|
|
115003
|
+
ledger_hash: null,
|
|
115004
|
+
amount_settled: subWorkerAmount,
|
|
115005
|
+
platform_fee: subFeeAmount,
|
|
115006
|
+
platform_fee_rate: subP2pFeeRate,
|
|
115007
|
+
// Lane in the signed body — the relay's custody posture is
|
|
115008
|
+
// committed-to, not derivable.
|
|
115009
|
+
settlement_mode: "p2p",
|
|
115010
|
+
status: "completed",
|
|
115011
|
+
settled_at: subP2pSettledAt,
|
|
115012
|
+
issuer_relay_id: relayIdentity.relayMotebitId
|
|
115013
|
+
}, relayIdentity.privateKey);
|
|
115014
|
+
moteDb.db.prepare(`INSERT OR IGNORE INTO relay_settlements
|
|
115015
|
+
(settlement_id, allocation_id, task_id, motebit_id, receipt_hash,
|
|
115016
|
+
amount_settled, platform_fee, platform_fee_rate, status, settled_at,
|
|
115017
|
+
settlement_mode, p2p_tx_hash, payment_verification_status, delegator_id,
|
|
115018
|
+
issuer_relay_id, suite, signature, record_json)
|
|
115019
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(subP2pSettlementId, `p2p-${subRelayTaskId}`, subRelayTaskId, sub.motebit_id, sub.result_hash ?? "", subWorkerAmount, subFeeAmount, subP2pFeeRate, "completed", subP2pSettledAt, "p2p", subP2pProof?.tx_hash ?? null, "pending", subEntry.submitted_by ?? null, signedSubP2p.issuer_relay_id, signedSubP2p.suite, signedSubP2p.signature, canonicalJson(signedSubP2p));
|
|
115020
|
+
logger33.info("multihop.settlement.p2p_recorded", {
|
|
115021
|
+
correlationId: parentTaskId,
|
|
115022
|
+
subTaskId: subRelayTaskId,
|
|
115023
|
+
subAgent: sub.motebit_id,
|
|
115024
|
+
net: subWorkerAmount,
|
|
115025
|
+
fee: subFeeAmount,
|
|
115026
|
+
depth
|
|
115027
|
+
});
|
|
115028
|
+
const nestedReceipts2 = sub.delegation_receipts ?? [];
|
|
115029
|
+
for (const nested of nestedReceipts2) {
|
|
115030
|
+
await settleSubReceipt(nested, parentTaskId, depth + 1);
|
|
115031
|
+
}
|
|
115032
|
+
return;
|
|
115033
|
+
}
|
|
114426
115034
|
logger33.error("multihop.settlement.relay_residual_fired", {
|
|
114427
115035
|
correlationId: parentTaskId,
|
|
114428
115036
|
subTaskId: subRelayTaskId,
|
|
@@ -115041,7 +115649,10 @@ async function registerTaskRoutes(deps) {
|
|
|
115041
115649
|
};
|
|
115042
115650
|
const callerMotebitId = c3.get("callerMotebitId");
|
|
115043
115651
|
const submittedBy = callerMotebitId ?? body.submitted_by;
|
|
115044
|
-
const
|
|
115652
|
+
const isP2pProofSubmission = typeof body.target_agent === "string" && body.target_agent.length > 0;
|
|
115653
|
+
const pricingAgent = isP2pProofSubmission ? body.target_agent : motebitId;
|
|
115654
|
+
const pricingCapability = isP2pProofSubmission && Array.isArray(body.required_capabilities) && body.required_capabilities.length === 1 ? String(body.required_capabilities[0]) : void 0;
|
|
115655
|
+
const unitCostAtSubmission = getListingUnitCost(moteDb, pricingAgent, pricingCapability);
|
|
115045
115656
|
const priceSnapshot = unitCostAtSubmission > 0 ? toMicro(computeGrossAmount(unitCostAtSubmission, platformFeeRate)) : void 0;
|
|
115046
115657
|
const x402TxHash = lastSettleTxHash;
|
|
115047
115658
|
const x402Net = lastSettleNetwork;
|
|
@@ -115100,7 +115711,14 @@ async function registerTaskRoutes(deps) {
|
|
|
115100
115711
|
}
|
|
115101
115712
|
const unitCostMicro = unitCostAtSubmission > 0 ? toMicro(unitCostAtSubmission) : void 0;
|
|
115102
115713
|
if (unitCostMicro != null && proof.amount_micro !== unitCostMicro) {
|
|
115103
|
-
throw new TaskError(
|
|
115714
|
+
throw new TaskError(
|
|
115715
|
+
"TASK_P2P_AMOUNT_MISMATCH",
|
|
115716
|
+
// Report the NET worker-leg amount the check actually compares against
|
|
115717
|
+
// (`unitCostMicro`), not the gross `priceSnapshot` — the earlier
|
|
115718
|
+
// message showed the gross and misled the diagnosis.
|
|
115719
|
+
`Payment worker-leg amount ${proof.amount_micro} does not match expected ${unitCostMicro} for capability "${pricingCapability ?? "?"}"`,
|
|
115720
|
+
400
|
|
115721
|
+
);
|
|
115104
115722
|
}
|
|
115105
115723
|
if (unitCostMicro != null && platformFeeRate > 0) {
|
|
115106
115724
|
const expectedFeeMicro = computeP2pFeeMicro(unitCostMicro, platformFeeRate);
|
|
@@ -115247,7 +115865,54 @@ async function registerTaskRoutes(deps) {
|
|
|
115247
115865
|
let routed = false;
|
|
115248
115866
|
let federationAttempted = false;
|
|
115249
115867
|
let routingChoice;
|
|
115250
|
-
|
|
115868
|
+
let pinnedLocalHandled = false;
|
|
115869
|
+
if (settlementMode === "p2p" && body.target_agent != null && !federatedP2pIntent) {
|
|
115870
|
+
pinnedLocalHandled = true;
|
|
115871
|
+
const pinnedId = body.target_agent;
|
|
115872
|
+
routingChoice = {
|
|
115873
|
+
selected_agent: pinnedId,
|
|
115874
|
+
composite_score: 1,
|
|
115875
|
+
sub_scores: { pinned: 1 },
|
|
115876
|
+
routing_paths: [[pinnedId]],
|
|
115877
|
+
alternatives_considered: 0
|
|
115878
|
+
};
|
|
115879
|
+
const pinnedPeers = connections.get(pinnedId);
|
|
115880
|
+
if (pinnedPeers && pinnedPeers.length > 0) {
|
|
115881
|
+
for (const peer of pinnedPeers) {
|
|
115882
|
+
peer.ws.send(payload);
|
|
115883
|
+
}
|
|
115884
|
+
routed = true;
|
|
115885
|
+
logger33.info("task.p2p_pinned_dispatched", {
|
|
115886
|
+
correlationId: taskId,
|
|
115887
|
+
worker: pinnedId,
|
|
115888
|
+
via: "websocket"
|
|
115889
|
+
});
|
|
115890
|
+
} else {
|
|
115891
|
+
const pinnedReg = moteDb.db.prepare("SELECT endpoint_url FROM agent_registry WHERE motebit_id = ? AND expires_at > ?").get(pinnedId, Date.now());
|
|
115892
|
+
if (pinnedReg?.endpoint_url?.trim()) {
|
|
115893
|
+
void forwardTaskViaMcp(pinnedReg.endpoint_url, taskId, body.prompt, pinnedId, taskQueue, logger33, apiToken, async (receiptCandidate) => {
|
|
115894
|
+
const mcpEntry = taskQueue.get(taskId);
|
|
115895
|
+
if (!mcpEntry || mcpEntry.settled)
|
|
115896
|
+
return;
|
|
115897
|
+
await handleReceiptIngestion(receiptCandidate, taskId, mcpEntry.task.motebit_id, mcpEntry, ingestionDeps);
|
|
115898
|
+
});
|
|
115899
|
+
routed = true;
|
|
115900
|
+
logger33.info("task.p2p_pinned_dispatched", {
|
|
115901
|
+
correlationId: taskId,
|
|
115902
|
+
worker: pinnedId,
|
|
115903
|
+
via: "mcp",
|
|
115904
|
+
endpoint: pinnedReg.endpoint_url
|
|
115905
|
+
});
|
|
115906
|
+
} else {
|
|
115907
|
+
logger33.error("task.p2p_pinned_unroutable", {
|
|
115908
|
+
correlationId: taskId,
|
|
115909
|
+
worker: pinnedId,
|
|
115910
|
+
reason: "no WebSocket connection and no registered endpoint_url"
|
|
115911
|
+
});
|
|
115912
|
+
}
|
|
115913
|
+
}
|
|
115914
|
+
}
|
|
115915
|
+
if (!pinnedLocalHandled && requiredCaps.length > 0) {
|
|
115251
115916
|
try {
|
|
115252
115917
|
const { profiles, requirements } = taskRouter.buildCandidateProfiles(requiredCaps[0], void 0, 20, callerMotebitId);
|
|
115253
115918
|
const multiCapProfiles = requiredCaps.length > 1 ? profiles.filter((p5) => requiredCaps.every((cap) => p5.listing?.capabilities.includes(cap))) : profiles;
|
|
@@ -115485,6 +116150,12 @@ async function registerTaskRoutes(deps) {
|
|
|
115485
116150
|
});
|
|
115486
116151
|
} else {
|
|
115487
116152
|
taskRouter.recordPeerForwardResult(peerEndpoint, false);
|
|
116153
|
+
logger33.warn("task.forward_rejected", {
|
|
116154
|
+
correlationId: taskId,
|
|
116155
|
+
peerRelay: peerEndpoint,
|
|
116156
|
+
targetAgent: selId,
|
|
116157
|
+
status: resp.status
|
|
116158
|
+
});
|
|
115488
116159
|
}
|
|
115489
116160
|
} catch (fwdErr) {
|
|
115490
116161
|
taskRouter.recordPeerForwardResult(peerEndpoint, false);
|
|
@@ -115523,7 +116194,7 @@ async function registerTaskRoutes(deps) {
|
|
|
115523
116194
|
throw err2;
|
|
115524
116195
|
}
|
|
115525
116196
|
}
|
|
115526
|
-
if (!routed && !federationAttempted) {
|
|
116197
|
+
if (!pinnedLocalHandled && !routed && !federationAttempted) {
|
|
115527
116198
|
const peers = connections.get(motebitId);
|
|
115528
116199
|
if (peers) {
|
|
115529
116200
|
for (const peer of peers) {
|
|
@@ -115537,7 +116208,7 @@ async function registerTaskRoutes(deps) {
|
|
|
115537
116208
|
}
|
|
115538
116209
|
}
|
|
115539
116210
|
}
|
|
115540
|
-
if (!routed && !federationAttempted && requiredCaps.length > 0) {
|
|
116211
|
+
if (!pinnedLocalHandled && !routed && !federationAttempted && requiredCaps.length > 0) {
|
|
115541
116212
|
const now2 = Date.now();
|
|
115542
116213
|
const capFilter = requiredCaps[0];
|
|
115543
116214
|
const httpCandidate = moteDb.db.prepare(`SELECT r.motebit_id, r.endpoint_url FROM agent_registry r
|
|
@@ -115554,7 +116225,7 @@ async function registerTaskRoutes(deps) {
|
|
|
115554
116225
|
routed = true;
|
|
115555
116226
|
}
|
|
115556
116227
|
}
|
|
115557
|
-
if (!routed && !federationAttempted && pushAdapter) {
|
|
116228
|
+
if (!pinnedLocalHandled && !routed && !federationAttempted && pushAdapter) {
|
|
115558
116229
|
void attemptPushWake(motebitId, { pushAdapter, db: moteDb.db });
|
|
115559
116230
|
}
|
|
115560
116231
|
const responseBody = {
|
|
@@ -116592,6 +117263,11 @@ async function createSyncRelay(config) {
|
|
|
116592
117263
|
return acc;
|
|
116593
117264
|
}, {})
|
|
116594
117265
|
});
|
|
117266
|
+
const agentRegistryKeyLookup = (mid) => {
|
|
117267
|
+
const row = moteDb.db.prepare("SELECT public_key FROM agent_registry WHERE motebit_id = ?").get(mid);
|
|
117268
|
+
return row?.public_key ?? null;
|
|
117269
|
+
};
|
|
117270
|
+
const verifySignedTokenForDeviceWithFallback = (token, mid, im, aud, blacklistCheck, agentRevokedCheck, agentKeyLookup) => verifySignedTokenForDevice(token, mid, im, aud, blacklistCheck, agentRevokedCheck, agentKeyLookup ?? agentRegistryKeyLookup);
|
|
116595
117271
|
const { allLimiters, wsLimiter } = registerMiddleware({
|
|
116596
117272
|
app,
|
|
116597
117273
|
apiToken,
|
|
@@ -116602,7 +117278,7 @@ async function createSyncRelay(config) {
|
|
|
116602
117278
|
getFreezeReason,
|
|
116603
117279
|
isTokenBlacklisted,
|
|
116604
117280
|
isAgentRevoked,
|
|
116605
|
-
verifySignedTokenForDevice,
|
|
117281
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116606
117282
|
parseTokenPayloadUnsafe,
|
|
116607
117283
|
getShuttingDown: config.getShuttingDown,
|
|
116608
117284
|
getConnectionCount: () => getConnectionCount(),
|
|
@@ -116685,7 +117361,7 @@ async function createSyncRelay(config) {
|
|
|
116685
117361
|
wsLimiter,
|
|
116686
117362
|
isTokenBlacklisted,
|
|
116687
117363
|
isAgentRevoked,
|
|
116688
|
-
verifySignedTokenForDevice,
|
|
117364
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116689
117365
|
parseTokenPayloadUnsafe,
|
|
116690
117366
|
logger: logger43,
|
|
116691
117367
|
onCommandResponse: handleCommandResponse,
|
|
@@ -116696,7 +117372,7 @@ async function createSyncRelay(config) {
|
|
|
116696
117372
|
apiToken,
|
|
116697
117373
|
identityManager,
|
|
116698
117374
|
parseTokenPayloadUnsafe,
|
|
116699
|
-
verifySignedTokenForDevice,
|
|
117375
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116700
117376
|
isTokenBlacklisted,
|
|
116701
117377
|
isAgentRevoked
|
|
116702
117378
|
});
|
|
@@ -116712,7 +117388,7 @@ async function createSyncRelay(config) {
|
|
|
116712
117388
|
getFreezeReason,
|
|
116713
117389
|
isTokenBlacklisted,
|
|
116714
117390
|
isAgentRevoked,
|
|
116715
|
-
verifySignedTokenForDevice,
|
|
117391
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116716
117392
|
parseTokenPayloadUnsafe
|
|
116717
117393
|
});
|
|
116718
117394
|
const federationCallbacks = createFederationCallbacks({
|
|
@@ -116920,7 +117596,7 @@ async function createSyncRelay(config) {
|
|
|
116920
117596
|
apiToken,
|
|
116921
117597
|
identityManager,
|
|
116922
117598
|
parseTokenPayloadUnsafe,
|
|
116923
|
-
verifySignedTokenForDevice,
|
|
117599
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116924
117600
|
isTokenBlacklisted,
|
|
116925
117601
|
isAgentRevoked
|
|
116926
117602
|
});
|
|
@@ -116984,7 +117660,7 @@ async function createSyncRelay(config) {
|
|
|
116984
117660
|
federationConfig,
|
|
116985
117661
|
federationQueryCache,
|
|
116986
117662
|
parseTokenPayloadUnsafe,
|
|
116987
|
-
verifySignedTokenForDevice,
|
|
117663
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
116988
117664
|
isTokenBlacklisted,
|
|
116989
117665
|
isAgentRevoked
|
|
116990
117666
|
});
|
|
@@ -117182,7 +117858,7 @@ async function createSyncRelay(config) {
|
|
|
117182
117858
|
maxTasksPerSubmitter: MAX_TASKS_PER_SUBMITTER,
|
|
117183
117859
|
x402Config,
|
|
117184
117860
|
parseTokenPayloadUnsafe,
|
|
117185
|
-
verifySignedTokenForDevice,
|
|
117861
|
+
verifySignedTokenForDevice: verifySignedTokenForDeviceWithFallback,
|
|
117186
117862
|
isTokenBlacklisted,
|
|
117187
117863
|
isAgentRevoked,
|
|
117188
117864
|
platformFeeRate,
|