@nookplot/runtime 0.5.143 → 0.5.144
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/__tests__/apiMarketplace.test.js +2 -189
- package/dist/__tests__/apiMarketplace.test.js.map +1 -1
- package/dist/__tests__/autonomous.dedup.test.js +0 -11
- package/dist/__tests__/autonomous.dedup.test.js.map +1 -1
- package/dist/__tests__/autonomous.getAvailableActions.test.js +1 -13
- package/dist/__tests__/autonomous.getAvailableActions.test.js.map +1 -1
- package/dist/__tests__/bdAgentPack.test.d.ts +2 -0
- package/dist/__tests__/bdAgentPack.test.d.ts.map +1 -0
- package/dist/__tests__/bdAgentPack.test.js +44 -0
- package/dist/__tests__/bdAgentPack.test.js.map +1 -0
- package/dist/__tests__/codegen-drift.test.js +1 -3
- package/dist/__tests__/codegen-drift.test.js.map +1 -1
- package/dist/__tests__/conversation/modelThresholdsParity.test.js +14 -19
- package/dist/__tests__/conversation/modelThresholdsParity.test.js.map +1 -1
- package/dist/__tests__/economy.frontierInference.test.d.ts +2 -0
- package/dist/__tests__/economy.frontierInference.test.d.ts.map +1 -0
- package/dist/__tests__/economy.frontierInference.test.js +61 -0
- package/dist/__tests__/economy.frontierInference.test.js.map +1 -0
- package/dist/__tests__/economy.surplusBranch.test.js +0 -64
- package/dist/__tests__/economy.surplusBranch.test.js.map +1 -1
- package/dist/__tests__/externalMcpTools.test.d.ts +2 -0
- package/dist/__tests__/externalMcpTools.test.d.ts.map +1 -0
- package/dist/__tests__/externalMcpTools.test.js +94 -0
- package/dist/__tests__/externalMcpTools.test.js.map +1 -0
- package/dist/__tests__/helpers/mockRuntime.d.ts.map +1 -1
- package/dist/__tests__/helpers/mockRuntime.js +0 -7
- package/dist/__tests__/helpers/mockRuntime.js.map +1 -1
- package/dist/__tests__/pack.gating.test.d.ts +2 -0
- package/dist/__tests__/pack.gating.test.d.ts.map +1 -0
- package/dist/__tests__/pack.gating.test.js +134 -0
- package/dist/__tests__/pack.gating.test.js.map +1 -0
- package/dist/__tests__/pack.test.d.ts +2 -0
- package/dist/__tests__/pack.test.d.ts.map +1 -0
- package/dist/__tests__/pack.test.js +299 -0
- package/dist/__tests__/pack.test.js.map +1 -0
- package/dist/__tests__/packLoader.test.d.ts +2 -0
- package/dist/__tests__/packLoader.test.d.ts.map +1 -0
- package/dist/__tests__/packLoader.test.js +304 -0
- package/dist/__tests__/packLoader.test.js.map +1 -0
- package/dist/__tests__/presetLoader.test.js +17 -0
- package/dist/__tests__/presetLoader.test.js.map +1 -1
- package/dist/actionCatalog.d.ts.map +1 -1
- package/dist/actionCatalog.generated.d.ts +1 -1
- package/dist/actionCatalog.generated.d.ts.map +1 -1
- package/dist/actionCatalog.generated.js +22 -137
- package/dist/actionCatalog.generated.js.map +1 -1
- package/dist/actionCatalog.js +13 -11
- package/dist/actionCatalog.js.map +1 -1
- package/dist/api-marketplace.d.ts +0 -146
- package/dist/api-marketplace.d.ts.map +1 -1
- package/dist/api-marketplace.js +0 -218
- package/dist/api-marketplace.js.map +1 -1
- package/dist/autonomous.d.ts +33 -17
- package/dist/autonomous.d.ts.map +1 -1
- package/dist/autonomous.js +122 -273
- package/dist/autonomous.js.map +1 -1
- package/dist/contentSafety.d.ts +1 -1
- package/dist/contentSafety.d.ts.map +1 -1
- package/dist/contentSafety.js +2 -6
- package/dist/contentSafety.js.map +1 -1
- package/dist/discovery.js +1 -1
- package/dist/discovery.js.map +1 -1
- package/dist/economy.d.ts +15 -10
- package/dist/economy.d.ts.map +1 -1
- package/dist/economy.js +29 -16
- package/dist/economy.js.map +1 -1
- package/dist/frontierPass.d.ts +30 -0
- package/dist/frontierPass.d.ts.map +1 -0
- package/dist/frontierPass.js +42 -0
- package/dist/frontierPass.js.map +1 -0
- package/dist/identity.d.ts +0 -51
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +0 -50
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +8 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -16
- package/dist/index.js.map +1 -1
- package/dist/pack.d.ts +181 -0
- package/dist/pack.d.ts.map +1 -0
- package/dist/pack.js +379 -0
- package/dist/pack.js.map +1 -0
- package/dist/packLoader.d.ts +109 -0
- package/dist/packLoader.d.ts.map +1 -0
- package/dist/packLoader.js +236 -0
- package/dist/packLoader.js.map +1 -0
- package/dist/presetLoader.d.ts +3 -1
- package/dist/presetLoader.d.ts.map +1 -1
- package/dist/presetLoader.js +7 -1
- package/dist/presetLoader.js.map +1 -1
- package/dist/signalActionMap.d.ts +17 -1
- package/dist/signalActionMap.d.ts.map +1 -1
- package/dist/signalActionMap.js +42 -17
- package/dist/signalActionMap.js.map +1 -1
- package/dist/swarms.d.ts +0 -13
- package/dist/swarms.d.ts.map +1 -1
- package/dist/swarms.js +0 -4
- package/dist/swarms.js.map +1 -1
- package/dist/tools.d.ts +23 -7
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +21 -7
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +0 -21
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/autonomous.goalBootstrap.test.d.ts +0 -2
- package/dist/__tests__/autonomous.goalBootstrap.test.d.ts.map +0 -1
- package/dist/__tests__/autonomous.goalBootstrap.test.js +0 -148
- package/dist/__tests__/autonomous.goalBootstrap.test.js.map +0 -1
- package/dist/__tests__/autonomous.miningTrack.test.d.ts +0 -2
- package/dist/__tests__/autonomous.miningTrack.test.d.ts.map +0 -1
- package/dist/__tests__/autonomous.miningTrack.test.js +0 -38
- package/dist/__tests__/autonomous.miningTrack.test.js.map +0 -1
- package/dist/__tests__/autonomous.payApi.test.d.ts +0 -2
- package/dist/__tests__/autonomous.payApi.test.d.ts.map +0 -1
- package/dist/__tests__/autonomous.payApi.test.js +0 -73
- package/dist/__tests__/autonomous.payApi.test.js.map +0 -1
- package/dist/__tests__/autonomous.workspaceOpportunity.test.d.ts +0 -2
- package/dist/__tests__/autonomous.workspaceOpportunity.test.d.ts.map +0 -1
- package/dist/__tests__/autonomous.workspaceOpportunity.test.js +0 -200
- package/dist/__tests__/autonomous.workspaceOpportunity.test.js.map +0 -1
- package/dist/__tests__/goalLoop.test.d.ts +0 -2
- package/dist/__tests__/goalLoop.test.d.ts.map +0 -1
- package/dist/__tests__/goalLoop.test.js +0 -358
- package/dist/__tests__/goalLoop.test.js.map +0 -1
- package/dist/__tests__/loadProfile.test.d.ts +0 -8
- package/dist/__tests__/loadProfile.test.d.ts.map +0 -1
- package/dist/__tests__/loadProfile.test.js +0 -134
- package/dist/__tests__/loadProfile.test.js.map +0 -1
- package/dist/__tests__/mining.test.d.ts +0 -2
- package/dist/__tests__/mining.test.d.ts.map +0 -1
- package/dist/__tests__/mining.test.js +0 -306
- package/dist/__tests__/mining.test.js.map +0 -1
- package/dist/__tests__/signalActionMap.test.d.ts +0 -17
- package/dist/__tests__/signalActionMap.test.d.ts.map +0 -1
- package/dist/__tests__/signalActionMap.test.js +0 -165
- package/dist/__tests__/signalActionMap.test.js.map +0 -1
- package/dist/__tests__/usdcBudget.test.d.ts +0 -2
- package/dist/__tests__/usdcBudget.test.d.ts.map +0 -1
- package/dist/__tests__/usdcBudget.test.js +0 -128
- package/dist/__tests__/usdcBudget.test.js.map +0 -1
- package/dist/__tests__/x402.test.d.ts +0 -2
- package/dist/__tests__/x402.test.d.ts.map +0 -1
- package/dist/__tests__/x402.test.js +0 -117
- package/dist/__tests__/x402.test.js.map +0 -1
- package/dist/goal/goalLoop.d.ts +0 -78
- package/dist/goal/goalLoop.d.ts.map +0 -1
- package/dist/goal/goalLoop.js +0 -388
- package/dist/goal/goalLoop.js.map +0 -1
- package/dist/goal/goalPrompts.d.ts +0 -20
- package/dist/goal/goalPrompts.d.ts.map +0 -1
- package/dist/goal/goalPrompts.js +0 -54
- package/dist/goal/goalPrompts.js.map +0 -1
- package/dist/goal/types.d.ts +0 -102
- package/dist/goal/types.d.ts.map +0 -1
- package/dist/goal/types.js +0 -7
- package/dist/goal/types.js.map +0 -1
- package/dist/loadProfile.d.ts +0 -100
- package/dist/loadProfile.d.ts.map +0 -1
- package/dist/loadProfile.js +0 -221
- package/dist/loadProfile.js.map +0 -1
- package/dist/usdcBudget.d.ts +0 -90
- package/dist/usdcBudget.d.ts.map +0 -1
- package/dist/usdcBudget.js +0 -155
- package/dist/usdcBudget.js.map +0 -1
- package/dist/x402.d.ts +0 -69
- package/dist/x402.d.ts.map +0 -1
- package/dist/x402.js +0 -139
- package/dist/x402.js.map +0 -1
package/dist/autonomous.js
CHANGED
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
* @module autonomous
|
|
41
41
|
*/
|
|
42
42
|
import { prepareSignRelay } from "./signing.js";
|
|
43
|
-
import {
|
|
43
|
+
import { runFrontierPass } from "./frontierPass.js";
|
|
44
44
|
import { wrapUntrusted, sanitizeForPrompt, UNTRUSTED_CONTENT_INSTRUCTION } from "./contentSafety.js";
|
|
45
|
-
import { getAvailableActionsFromMap } from "./signalActionMap.js";
|
|
45
|
+
import { getAvailableActionsFromMap, resolveDispatchToolName, CORE_ACTIONS } from "./signalActionMap.js";
|
|
46
|
+
import { resolvePackActions } from "./pack.js";
|
|
46
47
|
import { getCategoryListing, getToolsInCategory } from "./actionCatalog.js";
|
|
47
48
|
import { WakeUpStack } from "./wakeUpStack.js";
|
|
48
|
-
import { GoalLoop } from "./goal/goalLoop.js";
|
|
49
49
|
import { hooks as defaultHooks } from "./hooks.js";
|
|
50
50
|
import { guardrails as defaultGuardrails, GuardrailTripped, InputGuardrailTripped, } from "./guardrails.js";
|
|
51
51
|
import { buildCorrectivePrompt, checkForDoomLoopFromSignatures, makeSignature, } from "./doomLoop.js";
|
|
@@ -63,7 +63,7 @@ const ON_CHAIN_ACTIONS = new Set([
|
|
|
63
63
|
"cancel_bounty", "unclaim_bounty",
|
|
64
64
|
"expire_disputed_bounty", "sweep_treasury_fees", // V8
|
|
65
65
|
"sweep_creator_refund", // V9 H4 admin recovery
|
|
66
|
-
"create_listing", "list_service", "update_service", "create_agreement",
|
|
66
|
+
"create_listing", "list_service", "update_service", "create_agreement",
|
|
67
67
|
"deliver_work", "settle_agreement", "dispute_agreement", "cancel_agreement",
|
|
68
68
|
"expire_dispute", "expire_delivered",
|
|
69
69
|
"deploy_preview",
|
|
@@ -101,6 +101,7 @@ const ON_CHAIN_ACTIONS = new Set([
|
|
|
101
101
|
// roadmap §1h Decision 11. Approval-gates the submission before the gateway
|
|
102
102
|
// pipes the artifact through /submit-solution → submitRlmTrajectory.
|
|
103
103
|
"submit_rlm",
|
|
104
|
+
// API marketplace on-chain actions use existing service/* prepare endpoints
|
|
104
105
|
// Social (missing)
|
|
105
106
|
"remove_vote", "revoke_attestation",
|
|
106
107
|
// Bounty lifecycle (missing)
|
|
@@ -124,9 +125,6 @@ const ON_CHAIN_ACTIONS = new Set([
|
|
|
124
125
|
"claim_pending_guild_mining_treasury",
|
|
125
126
|
// Ecosystem partner protocols (raw-tx, agent pays own gas)
|
|
126
127
|
"ecosystem_stake_tokens", "ecosystem_claim_rewards",
|
|
127
|
-
// Per-call x402 API purchase (client-signed EIP-3009 USDC auth, spends real
|
|
128
|
-
// USDC) — gated for the same reason as ecosystem_*: it moves the agent's money.
|
|
129
|
-
"pay_api",
|
|
130
128
|
// V11: Multi-payout Open bounties (6 actions — creator + submitter + recovery)
|
|
131
129
|
"create_open_bounty", "submit_open_bounty", "approve_open_submission",
|
|
132
130
|
"top_up_open_bounty", "close_open_bounty", "sweep_worker_payout",
|
|
@@ -148,8 +146,8 @@ const ON_CHAIN_ACTIONS = new Set([
|
|
|
148
146
|
* // → "- reply: Send a text reply in the current context. Params: content (string)\n..."
|
|
149
147
|
* ```
|
|
150
148
|
*/
|
|
151
|
-
export function getAvailableActions(signalType, loadedCategories) {
|
|
152
|
-
return getAvailableActionsFromMap(signalType, loadedCategories ?? new Set());
|
|
149
|
+
export function getAvailableActions(signalType, loadedCategories, externalActions, packActions) {
|
|
150
|
+
return getAvailableActionsFromMap(signalType, loadedCategories ?? new Set(), externalActions, packActions);
|
|
153
151
|
}
|
|
154
152
|
/**
|
|
155
153
|
* Maps a `mining_opportunity` signal's optional `track` field to the
|
|
@@ -210,6 +208,29 @@ export class AutonomousAgent {
|
|
|
210
208
|
this.approvalHandler = options.onApproval;
|
|
211
209
|
this.cooldownSec = options.responseCooldown ?? 120;
|
|
212
210
|
this.wakeUpStack = new WakeUpStack(runtime);
|
|
211
|
+
this.packActions = options.pack ? resolvePackActions(options.pack) : null;
|
|
212
|
+
}
|
|
213
|
+
/** External MCP tools (mounted servers) exposed as `mcp__<server>__<tool>` actions. */
|
|
214
|
+
externalMcpActions = [];
|
|
215
|
+
/**
|
|
216
|
+
* Resolved action set of the loaded pack (null = no pack, ungated).
|
|
217
|
+
* Set once at construction from options.pack — packs are immutable per load.
|
|
218
|
+
*/
|
|
219
|
+
packActions;
|
|
220
|
+
/**
|
|
221
|
+
* Fetch the agent's mounted external MCP tools and expose them as
|
|
222
|
+
* available actions (ROADMAP_external-mcp-connectors Phase 1). Runs at
|
|
223
|
+
* start(); call again after connectMcpServer to pick up new mounts.
|
|
224
|
+
*/
|
|
225
|
+
async refreshExternalMcpActions() {
|
|
226
|
+
const tools = await this.runtime.tools.listMcpTools();
|
|
227
|
+
// The gateway computes the provider-safe wire name at discovery; tools
|
|
228
|
+
// without one (unmappable names) are visible in listMcpTools but can
|
|
229
|
+
// never be dispatched, so they don't surface as actions.
|
|
230
|
+
this.externalMcpActions = tools
|
|
231
|
+
.map((t) => t.wireName)
|
|
232
|
+
.filter((n) => typeof n === "string" && n.startsWith("mcp__"));
|
|
233
|
+
return this.externalMcpActions;
|
|
213
234
|
}
|
|
214
235
|
/** Start listening for proactive signals and action requests. */
|
|
215
236
|
start() {
|
|
@@ -246,19 +267,11 @@ export class AutonomousAgent {
|
|
|
246
267
|
if (this.verbose) {
|
|
247
268
|
console.log("[autonomous] AutonomousAgent started — handling signals + actions");
|
|
248
269
|
}
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
// step for reactive agents too (CLAUDE.md rule — small code change).
|
|
253
|
-
this.loadedCategories.add("tools");
|
|
254
|
-
this.loadedCategories.add("discovery");
|
|
255
|
-
this.loadedCategories.add("knowledge");
|
|
256
|
-
// Goal bootstrap — run the GoalLoop in background if this agent was
|
|
257
|
-
// forged with initial_goal set (L1 swarm auto-deploy). Failures are
|
|
258
|
-
// non-fatal: the agent continues in normal reactive mode.
|
|
259
|
-
this.maybeBootstrapGoal().catch((err) => {
|
|
270
|
+
// External MCP tools — loaded once at boot so mounted servers' tools
|
|
271
|
+
// surface in getAvailableActions and dispatch as `mcp:<server>:<tool>`.
|
|
272
|
+
this.refreshExternalMcpActions().catch((err) => {
|
|
260
273
|
if (this.verbose) {
|
|
261
|
-
console.error("[autonomous]
|
|
274
|
+
console.error("[autonomous] External MCP tool load failed:", err);
|
|
262
275
|
}
|
|
263
276
|
});
|
|
264
277
|
}
|
|
@@ -270,157 +283,6 @@ export class AutonomousAgent {
|
|
|
270
283
|
}
|
|
271
284
|
}
|
|
272
285
|
// ================================================================
|
|
273
|
-
// Goal bootstrap (L3 — migration 247)
|
|
274
|
-
// ================================================================
|
|
275
|
-
/**
|
|
276
|
-
* Check whether this agent has an initial_goal + pending status, and
|
|
277
|
-
* if so, spin up a GoalLoop in the background. Non-blocking — start()
|
|
278
|
-
* returns immediately so WebSocket signal subscriptions are live even
|
|
279
|
-
* while the goal loop is running its first step.
|
|
280
|
-
*/
|
|
281
|
-
async maybeBootstrapGoal() {
|
|
282
|
-
let goalConfig;
|
|
283
|
-
try {
|
|
284
|
-
goalConfig = await this.runtime.identity.getGoal();
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
if (this.verbose) {
|
|
288
|
-
console.error("[autonomous] getGoal failed — treating as no goal:", err);
|
|
289
|
-
}
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
if (!goalConfig || !goalConfig.initialGoal)
|
|
293
|
-
return;
|
|
294
|
-
if (goalConfig.goalStatus !== "pending") {
|
|
295
|
-
if (this.verbose) {
|
|
296
|
-
console.log(`[autonomous] Skipping goal bootstrap — status is ${goalConfig.goalStatus}, not 'pending'`);
|
|
297
|
-
}
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
if (this.verbose) {
|
|
301
|
-
console.log(`[autonomous] Goal bootstrap: "${goalConfig.initialGoal.slice(0, 80)}..." budget=${goalConfig.goalBudgetNook ?? "unlimited"}`);
|
|
302
|
-
}
|
|
303
|
-
// Transition status atomically before running the loop. If the
|
|
304
|
-
// gateway rejects (network, permissions), bail out — we do not want
|
|
305
|
-
// to run the loop with a mismatched DB state.
|
|
306
|
-
try {
|
|
307
|
-
await this.runtime.identity.updateGoalStatus("in_progress");
|
|
308
|
-
}
|
|
309
|
-
catch (err) {
|
|
310
|
-
if (this.verbose) {
|
|
311
|
-
console.error("[autonomous] Failed to transition goal → in_progress:", err);
|
|
312
|
-
}
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const budgetNook = goalConfig.goalBudgetNook ? BigInt(goalConfig.goalBudgetNook) : 0n;
|
|
316
|
-
const loopOptions = {
|
|
317
|
-
runtime: this.runtime,
|
|
318
|
-
goal: goalConfig.initialGoal,
|
|
319
|
-
budgetNook,
|
|
320
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
321
|
-
verbose: this.verbose,
|
|
322
|
-
};
|
|
323
|
-
const loop = new GoalLoop(loopOptions);
|
|
324
|
-
let result;
|
|
325
|
-
try {
|
|
326
|
-
result = await loop.run();
|
|
327
|
-
}
|
|
328
|
-
catch (err) {
|
|
329
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
330
|
-
if (this.verbose) {
|
|
331
|
-
console.error("[autonomous] GoalLoop threw:", err);
|
|
332
|
-
}
|
|
333
|
-
// Transition to failed so the UI reflects the error.
|
|
334
|
-
await this.runtime.identity.updateGoalStatus("failed").catch(() => { });
|
|
335
|
-
await this.runtime.identity.createPendingTask({
|
|
336
|
-
reason: "unclear_goal",
|
|
337
|
-
description: `Goal loop crashed: ${msg.slice(0, 400)}`,
|
|
338
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
339
|
-
}).catch(() => { });
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
await this.handleGoalResult(result, goalConfig);
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Dispatch on the terminal state of a GoalLoop run:
|
|
346
|
-
* - complete → store artifact in private KG, pause agent
|
|
347
|
-
* - blocked_budget → create pending task (budget_exhausted), pause
|
|
348
|
-
* - blocked_stuck → create pending task (stuck_3x), pause
|
|
349
|
-
* - blocked_capability → create pending task (needs_capability), pause
|
|
350
|
-
*/
|
|
351
|
-
async handleGoalResult(result, goalConfig) {
|
|
352
|
-
if (result.outcome === "complete") {
|
|
353
|
-
// Store deliverable in private KG
|
|
354
|
-
let artifactId = null;
|
|
355
|
-
try {
|
|
356
|
-
const storeResult = (await this.runtime.connection.request("POST", "/v1/agents/me/knowledge", {
|
|
357
|
-
contentText: result.artifact.body,
|
|
358
|
-
title: result.artifact.title,
|
|
359
|
-
domain: result.artifact.domain,
|
|
360
|
-
visibility: "private",
|
|
361
|
-
knowledgeType: "fact",
|
|
362
|
-
sourceType: "import",
|
|
363
|
-
metadata: {
|
|
364
|
-
goal: goalConfig.initialGoal,
|
|
365
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
366
|
-
stepsExecuted: result.stepsExecuted,
|
|
367
|
-
spentNook: result.spentNook.toString(),
|
|
368
|
-
},
|
|
369
|
-
}));
|
|
370
|
-
artifactId = storeResult?.id ?? null;
|
|
371
|
-
}
|
|
372
|
-
catch (err) {
|
|
373
|
-
if (this.verbose) {
|
|
374
|
-
console.error("[autonomous] Failed to store goal artifact:", err);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
try {
|
|
378
|
-
await this.runtime.identity.completeGoal(artifactId ?? "unknown");
|
|
379
|
-
}
|
|
380
|
-
catch (err) {
|
|
381
|
-
if (this.verbose) {
|
|
382
|
-
console.error("[autonomous] completeGoal failed:", err);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// Q3: agent pauses after completion, does not stay reactive
|
|
386
|
-
this.stop();
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
if (result.outcome === "blocked_budget") {
|
|
390
|
-
// initialGoal is non-null here — maybeBootstrapGoal returned early otherwise.
|
|
391
|
-
const goalText = goalConfig.initialGoal ?? "(unknown)";
|
|
392
|
-
await this.runtime.identity.createPendingTask({
|
|
393
|
-
reason: "budget_exhausted",
|
|
394
|
-
description: `Needs top-off to continue goal: ${goalText.slice(0, 300)}`,
|
|
395
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
396
|
-
}).catch(() => { });
|
|
397
|
-
await this.runtime.identity.updateGoalStatus("paused_awaiting_topoff").catch(() => { });
|
|
398
|
-
this.stop();
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
if (result.outcome === "blocked_stuck") {
|
|
402
|
-
await this.runtime.identity.createPendingTask({
|
|
403
|
-
reason: "stuck_3x",
|
|
404
|
-
description: result.stuckReason,
|
|
405
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
406
|
-
}).catch(() => { });
|
|
407
|
-
await this.runtime.identity.updateGoalStatus("blocked_needs_decision").catch(() => { });
|
|
408
|
-
this.stop();
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
if (result.outcome === "blocked_capability") {
|
|
412
|
-
await this.runtime.identity.createPendingTask({
|
|
413
|
-
reason: "needs_capability",
|
|
414
|
-
description: result.capabilityNeeded,
|
|
415
|
-
suggestedPresetId: result.suggestedPreset,
|
|
416
|
-
parentSwarmId: goalConfig.goalParentSwarmId,
|
|
417
|
-
}).catch(() => { });
|
|
418
|
-
await this.runtime.identity.updateGoalStatus("blocked_needs_decision").catch(() => { });
|
|
419
|
-
this.stop();
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
// ================================================================
|
|
424
286
|
// Signal handling (proactive.signal)
|
|
425
287
|
// ================================================================
|
|
426
288
|
/**
|
|
@@ -502,8 +364,6 @@ export class AutonomousAgent {
|
|
|
502
364
|
return `proj_bounty_done:${data.bountyId ?? ""}`;
|
|
503
365
|
case "guild_opportunity":
|
|
504
366
|
return `guild:${data.guildId ?? ""}:${addr}`;
|
|
505
|
-
case "workspace_opportunity":
|
|
506
|
-
return `workspace:${data.workspaceId ?? data.sourceId ?? ""}:${addr}`;
|
|
507
367
|
case "team_assembly_suggested":
|
|
508
368
|
return `team_suggest:${data.txHash ?? ""}`;
|
|
509
369
|
case "team_invitation":
|
|
@@ -653,7 +513,9 @@ export class AutonomousAgent {
|
|
|
653
513
|
case "community_gap":
|
|
654
514
|
await this.handleCommunityGap(data);
|
|
655
515
|
break;
|
|
656
|
-
|
|
516
|
+
case "directive":
|
|
517
|
+
await this.handleDirective(data);
|
|
518
|
+
break;
|
|
657
519
|
case "files_committed":
|
|
658
520
|
await this.handleFilesCommitted(data);
|
|
659
521
|
break;
|
|
@@ -766,10 +628,6 @@ export class AutonomousAgent {
|
|
|
766
628
|
case "guild_opportunity":
|
|
767
629
|
await this.handleGuildOpportunity(data);
|
|
768
630
|
break;
|
|
769
|
-
// ── Open Cognitive Workspaces (P3): discoverable/open workspace to join ──
|
|
770
|
-
case "workspace_opportunity":
|
|
771
|
-
await this.handleWorkspaceOpportunity(data);
|
|
772
|
-
break;
|
|
773
631
|
// ── Mining signals ──
|
|
774
632
|
case "mining_opportunity":
|
|
775
633
|
await this.handleMiningOpportunity(data);
|
|
@@ -1296,51 +1154,6 @@ export class AutonomousAgent {
|
|
|
1296
1154
|
console.error("[autonomous] Guild opportunity handling failed:", err);
|
|
1297
1155
|
}
|
|
1298
1156
|
}
|
|
1299
|
-
async handleWorkspaceOpportunity(data) {
|
|
1300
|
-
const meta = data;
|
|
1301
|
-
const name = meta.name ?? meta.title ?? "Unknown Workspace";
|
|
1302
|
-
const workspaceId = meta.workspaceId ?? meta.sourceId ?? "";
|
|
1303
|
-
const visibility = meta.visibility ?? "discoverable";
|
|
1304
|
-
const description = meta.description ?? data.messagePreview ?? "";
|
|
1305
|
-
const memberCount = meta.memberCount ?? 0;
|
|
1306
|
-
const regionCounts = meta.regionCounts ?? {};
|
|
1307
|
-
const openJoinRole = meta.openJoinRole ?? 0;
|
|
1308
|
-
try {
|
|
1309
|
-
const isOpen = visibility === "open";
|
|
1310
|
-
const joinNote = isOpen
|
|
1311
|
-
? `You can self-join instantly (you would join as ${openJoinRole === 1 ? "editor" : "viewer"}).`
|
|
1312
|
-
: "You can request to join; the owner approves.";
|
|
1313
|
-
const regionSummary = Object.entries(regionCounts)
|
|
1314
|
-
.map(([r, c]) => `${r}: ${c}`)
|
|
1315
|
-
.join(", ") || "no cognitive state yet";
|
|
1316
|
-
const prompt = `${UNTRUSTED_CONTENT_INSTRUCTION}\n\n` +
|
|
1317
|
-
"A cognitive workspace opportunity was found on Nookplot.\n" +
|
|
1318
|
-
`Workspace: ${sanitizeForPrompt(name)}\n` +
|
|
1319
|
-
`Description: ${wrapUntrusted(description, "workspace description")}\n` +
|
|
1320
|
-
`Visibility: ${visibility}\n` +
|
|
1321
|
-
`Members: ${memberCount}\n` +
|
|
1322
|
-
`Cognitive state: ${sanitizeForPrompt(regionSummary)}\n` +
|
|
1323
|
-
`ID: ${workspaceId}\n` +
|
|
1324
|
-
`${joinNote}\n\n` +
|
|
1325
|
-
"Should you join this workspace to collaborate on its shared reasoning state? Respond with INTERESTED or SKIP.\n" +
|
|
1326
|
-
"If interested, briefly explain why (under 200 chars).\n\n" +
|
|
1327
|
-
"Format:\nDECISION: INTERESTED or SKIP\nREASON: why you want to join";
|
|
1328
|
-
const response = await this.generateResponse(prompt);
|
|
1329
|
-
const text = response?.trim() ?? "";
|
|
1330
|
-
if (text.toUpperCase().includes("INTERESTED")) {
|
|
1331
|
-
if (this.verbose) {
|
|
1332
|
-
console.log(`[autonomous] ✓ Interested in workspace "${name}" (supervised — join surfaced as an action)`);
|
|
1333
|
-
}
|
|
1334
|
-
// Joining is surfaced as an available action (join_workspace /
|
|
1335
|
-
// request_workspace_join) for the agent's decision loop — not
|
|
1336
|
-
// auto-executed here (adversarial default: no auto-join).
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
catch (err) {
|
|
1340
|
-
if (this.verbose)
|
|
1341
|
-
console.error("[autonomous] Workspace opportunity handling failed:", err);
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
1157
|
async handleMiningOpportunity(data) {
|
|
1345
1158
|
const meta = data;
|
|
1346
1159
|
const opportunityType = meta.opportunityType ?? "unknown";
|
|
@@ -1625,7 +1438,11 @@ export class AutonomousAgent {
|
|
|
1625
1438
|
console.log("[autonomous] No action parsed from response");
|
|
1626
1439
|
return;
|
|
1627
1440
|
}
|
|
1628
|
-
|
|
1441
|
+
// Wire names (`mcp__<server>__<tool>`) are case-sensitive registry keys —
|
|
1442
|
+
// lowercasing a mixed-case server/tool segment would dispatch a name that
|
|
1443
|
+
// doesn't exist (and trip pack gating with a misleading refusal).
|
|
1444
|
+
const rawAction = actionMatch[1];
|
|
1445
|
+
const actionType = rawAction.startsWith("mcp__") ? rawAction : rawAction.toLowerCase();
|
|
1629
1446
|
let payload = {};
|
|
1630
1447
|
const paramsMatch = text.match(/PARAMS:\s*(\{[\s\S]*\})/i);
|
|
1631
1448
|
if (paramsMatch) {
|
|
@@ -2233,7 +2050,40 @@ export class AutonomousAgent {
|
|
|
2233
2050
|
console.error("[autonomous] Community gap handling failed:", err);
|
|
2234
2051
|
}
|
|
2235
2052
|
}
|
|
2236
|
-
|
|
2053
|
+
async handleDirective(data) {
|
|
2054
|
+
const directiveContent = data.messagePreview ?? "";
|
|
2055
|
+
const channelId = data.channelId;
|
|
2056
|
+
const community = data.community ?? "general";
|
|
2057
|
+
try {
|
|
2058
|
+
const prompt = `${UNTRUSTED_CONTENT_INSTRUCTION}\n\n` +
|
|
2059
|
+
"You received a directive on Nookplot.\n" +
|
|
2060
|
+
`Directive:\n${wrapUntrusted(directiveContent, "directive")}\n\n` +
|
|
2061
|
+
"Follow the directive and compose your response.\n" +
|
|
2062
|
+
"If it asks you to post, write the post content.\n" +
|
|
2063
|
+
"If it asks you to discuss, write a discussion message.\n" +
|
|
2064
|
+
"If you can't follow this directive, respond with exactly: [SKIP]\n\n" +
|
|
2065
|
+
"Your response (under 500 chars):";
|
|
2066
|
+
const response = await this.generateResponse(prompt);
|
|
2067
|
+
const content = response?.trim() ?? "";
|
|
2068
|
+
if (content && content !== "[SKIP]") {
|
|
2069
|
+
if (channelId) {
|
|
2070
|
+
await this.runtime.channels.send(channelId, content);
|
|
2071
|
+
if (this.verbose)
|
|
2072
|
+
console.log(`[autonomous] ✓ Directive response sent to channel ${channelId.slice(0, 12)}`);
|
|
2073
|
+
}
|
|
2074
|
+
else {
|
|
2075
|
+
const title = content.slice(0, 100);
|
|
2076
|
+
await this.runtime.memory.publishKnowledge({ title, body: content, community });
|
|
2077
|
+
if (this.verbose)
|
|
2078
|
+
console.log(`[autonomous] ✓ Directive response posted in ${community}`);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
catch (err) {
|
|
2083
|
+
if (this.verbose)
|
|
2084
|
+
console.error("[autonomous] Directive handling failed:", err);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2237
2087
|
// ================================================================
|
|
2238
2088
|
// Project collaboration signal handlers
|
|
2239
2089
|
// ================================================================
|
|
@@ -2867,6 +2717,16 @@ export class AutonomousAgent {
|
|
|
2867
2717
|
// ================================================================
|
|
2868
2718
|
// Action request handling (proactive.action.request)
|
|
2869
2719
|
// ================================================================
|
|
2720
|
+
/**
|
|
2721
|
+
* Execute a `use_frontier_model` action — delegates to the shared
|
|
2722
|
+
* {@link runFrontierPass} so the runtime + CLI dispatch paths can't drift on
|
|
2723
|
+
* this money path. Consumes an owner-reserved pass, runs a one-shot Surplus
|
|
2724
|
+
* completion paid by the agent's OWN x402 key, finalizes (or reverts on
|
|
2725
|
+
* failure). Returns the frontier answer, or an `{ error }` tool result.
|
|
2726
|
+
*/
|
|
2727
|
+
async executeFrontierPass(args, agentAddress) {
|
|
2728
|
+
return runFrontierPass(this.runtime.connection, this.runtime.economy, args, agentAddress);
|
|
2729
|
+
}
|
|
2870
2730
|
async handleActionRequest(event) {
|
|
2871
2731
|
if (!this.isRunning)
|
|
2872
2732
|
return;
|
|
@@ -2882,6 +2742,29 @@ export class AutonomousAgent {
|
|
|
2882
2742
|
if (this.verbose) {
|
|
2883
2743
|
console.log(`[autonomous] Action request: ${actionType}${actionId ? ` (${actionId})` : ""}`);
|
|
2884
2744
|
}
|
|
2745
|
+
// Pack gating (ROADMAP_external-mcp-connectors Phase 3): with a pack
|
|
2746
|
+
// loaded, refuse anything outside CORE ∪ pack ∪ mounted-MCP. Gated
|
|
2747
|
+
// prompts never offer these — this guard catches handler-injected or
|
|
2748
|
+
// hallucinated action types.
|
|
2749
|
+
if (this.packActions) {
|
|
2750
|
+
const allowed = actionType.startsWith("mcp__")
|
|
2751
|
+
? this.externalMcpActions.includes(actionType)
|
|
2752
|
+
: CORE_ACTIONS.includes(actionType) || this.packActions.includes(actionType);
|
|
2753
|
+
if (!allowed) {
|
|
2754
|
+
if (this.verbose)
|
|
2755
|
+
console.log(`[autonomous] Action denied by pack gating: ${actionType}`);
|
|
2756
|
+
hooks.emitFireAndForget("action_rejected", {
|
|
2757
|
+
actionType, args, reason: "Not allowed by loaded pack", actionId,
|
|
2758
|
+
});
|
|
2759
|
+
if (actionId) {
|
|
2760
|
+
try {
|
|
2761
|
+
await this.runtime.proactive.rejectDelegatedAction(actionId, "Not allowed by loaded pack");
|
|
2762
|
+
}
|
|
2763
|
+
catch { /* best-effort */ }
|
|
2764
|
+
}
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2885
2768
|
// Approval gate: on-chain actions require approval when handler is set
|
|
2886
2769
|
if (this.approvalHandler && ON_CHAIN_ACTIONS.has(actionType)) {
|
|
2887
2770
|
const approved = await this.approvalHandler(actionType, args);
|
|
@@ -2920,18 +2803,6 @@ export class AutonomousAgent {
|
|
|
2920
2803
|
triggers: this.doomLoopTriggers,
|
|
2921
2804
|
actionType,
|
|
2922
2805
|
});
|
|
2923
|
-
// Track C.2: also push to gateway as fire-and-forget telemetry so
|
|
2924
|
-
// ops dashboards can answer "which tools most often misbehave?"
|
|
2925
|
-
// and "is this agent stuck right now?" — see
|
|
2926
|
-
// gateway/src/services/doomLoopMetrics.ts. Errors are swallowed so
|
|
2927
|
-
// a backend outage never blocks the runtime's recovery path.
|
|
2928
|
-
void this.runtime.connection
|
|
2929
|
-
.request("POST", "/v1/agents/me/doom-loop-event", {
|
|
2930
|
-
offender: doomOffender,
|
|
2931
|
-
triggers: this.doomLoopTriggers,
|
|
2932
|
-
actionType,
|
|
2933
|
-
})
|
|
2934
|
-
.catch(() => { });
|
|
2935
2806
|
if (this.doomLoopTriggers >= AUTONOMOUS_DOOM_LOOP_MAX_TRIGGERS) {
|
|
2936
2807
|
if (this.verbose) {
|
|
2937
2808
|
console.warn(`[autonomous] ✗ doom loop on '${doomOffender}' (${this.doomLoopTriggers} triggers) — aborting cycle`);
|
|
@@ -3037,43 +2908,21 @@ export class AutonomousAgent {
|
|
|
3037
2908
|
});
|
|
3038
2909
|
return;
|
|
3039
2910
|
}
|
|
3040
|
-
// ── Intercept
|
|
3041
|
-
//
|
|
3042
|
-
//
|
|
3043
|
-
//
|
|
3044
|
-
//
|
|
3045
|
-
if (actionType === "
|
|
3046
|
-
|
|
3047
|
-
if (!privateKey)
|
|
3048
|
-
throw new Error("pay_api requires the agent's private key (none configured)");
|
|
3049
|
-
const budget = this.runtime.usdcBudget;
|
|
3050
|
-
const maxForCall = budget.maxForNextCall(); // bigint | undefined; 0n = exhausted
|
|
3051
|
-
if (maxForCall === 0n) {
|
|
3052
|
-
result = { paid: false, blocked: "usdc_budget_exhausted", reason: `USDC daily spend cap exhausted (spent ${formatUsdc(budget.spent)})` };
|
|
3053
|
-
}
|
|
3054
|
-
else {
|
|
3055
|
-
const { ethers } = await import("ethers");
|
|
3056
|
-
const wallet = new ethers.Wallet(privateKey);
|
|
3057
|
-
const payResult = await this.runtime.x402.payAndCall({
|
|
3058
|
-
listingId: args.listingId,
|
|
3059
|
-
path: String(args.path ?? ""),
|
|
3060
|
-
method: args.method,
|
|
3061
|
-
body: args.body,
|
|
3062
|
-
...(maxForCall !== undefined ? { maxAmountBaseUnits: maxForCall } : {}),
|
|
3063
|
-
}, wallet);
|
|
3064
|
-
if (payResult.paid && payResult.amountPaidBaseUnits)
|
|
3065
|
-
budget.record(BigInt(payResult.amountPaidBaseUnits));
|
|
3066
|
-
result = { ...payResult };
|
|
3067
|
-
}
|
|
2911
|
+
// ── Intercept use_frontier_model (client-executed frontier pass) ──
|
|
2912
|
+
// Not a gateway tool: consume an owner-reserved pass, run a one-shot
|
|
2913
|
+
// Surplus completion paid by the agent's OWN client-signed x402 key, then
|
|
2914
|
+
// finalize (or revert on failure). The gateway can't run this
|
|
2915
|
+
// non-custodially. See ROADMAP_frontier-passes.md.
|
|
2916
|
+
if (actionType === "use_frontier_model") {
|
|
2917
|
+
result = await this.executeFrontierPass(args, agentAddress);
|
|
3068
2918
|
result = await guardrails.runOutput(actionType, result);
|
|
3069
2919
|
hooks.emitFireAndForget("tool_output", { toolName: actionType, args, result });
|
|
3070
|
-
// No txHash — the settlement tx is internal to the facilitator.
|
|
3071
2920
|
if (actionId)
|
|
3072
2921
|
await this.runtime.proactive.completeAction(actionId, undefined, result);
|
|
3073
2922
|
if (this.verbose)
|
|
3074
|
-
console.log(`[autonomous] ✓
|
|
2923
|
+
console.log(`[autonomous] ✓ use_frontier_model`);
|
|
3075
2924
|
hooks.emitFireAndForget("action_end", {
|
|
3076
|
-
actionType, args, result, durationMs: Date.now() - startTime, actionId,
|
|
2925
|
+
actionType, args, result, durationMs: Date.now() - startTime, actionId,
|
|
3077
2926
|
});
|
|
3078
2927
|
return;
|
|
3079
2928
|
}
|
|
@@ -3084,7 +2933,7 @@ export class AutonomousAgent {
|
|
|
3084
2933
|
// the original `payload` — otherwise input-guardrail mutations
|
|
3085
2934
|
// (lowercase normalization, content sanitization, etc.) silently get
|
|
3086
2935
|
// dropped on the way to the gateway.
|
|
3087
|
-
const toolName =
|
|
2936
|
+
const toolName = resolveDispatchToolName(actionType);
|
|
3088
2937
|
const dispatchPayload = {
|
|
3089
2938
|
...args,
|
|
3090
2939
|
...(suggestedContent ? { suggestedContent } : {}),
|
|
@@ -3653,7 +3502,7 @@ export class AutonomousAgent {
|
|
|
3653
3502
|
if (!this.generateResponse)
|
|
3654
3503
|
return;
|
|
3655
3504
|
try {
|
|
3656
|
-
const actions = getAvailableActionsFromMap("swarm_subtask_available", this.loadedCategories);
|
|
3505
|
+
const actions = getAvailableActionsFromMap("swarm_subtask_available", this.loadedCategories, this.externalMcpActions, this.packActions);
|
|
3657
3506
|
const prompt = `A swarm "${sanitizeForPrompt(swarmTitle.slice(0, 100))}" has open subtasks matching your skills.\n` +
|
|
3658
3507
|
`Swarm ID: ${swarmId}\n` +
|
|
3659
3508
|
`Matching skills: ${skillTags.slice(0, 10).join(", ")}\n\n` +
|
|
@@ -3681,7 +3530,7 @@ export class AutonomousAgent {
|
|
|
3681
3530
|
if (!this.generateResponse)
|
|
3682
3531
|
return;
|
|
3683
3532
|
try {
|
|
3684
|
-
const actions = getAvailableActionsFromMap("swarm_result_submitted", this.loadedCategories);
|
|
3533
|
+
const actions = getAvailableActionsFromMap("swarm_result_submitted", this.loadedCategories, this.externalMcpActions, this.packActions);
|
|
3685
3534
|
const prompt = `A result was submitted for subtask "${sanitizeForPrompt(subtaskTitle.slice(0, 100))}" in your swarm.\n` +
|
|
3686
3535
|
`Swarm ID: ${swarmId}\n` +
|
|
3687
3536
|
`Submitted by: ${sanitizeForPrompt((submittedBy).slice(0, 12))}...\n\n` +
|
|
@@ -3731,7 +3580,7 @@ export class AutonomousAgent {
|
|
|
3731
3580
|
searchResult = await this.parseAndExecuteAction(searchText);
|
|
3732
3581
|
}
|
|
3733
3582
|
// Step 2: Based on search results, store an insight
|
|
3734
|
-
const actions = getAvailableActionsFromMap("dream_prompt", this.loadedCategories);
|
|
3583
|
+
const actions = getAvailableActionsFromMap("dream_prompt", this.loadedCategories, this.externalMcpActions, this.packActions);
|
|
3735
3584
|
const searchContext = searchResult
|
|
3736
3585
|
? `\nSearch results (summarized): ${JSON.stringify(searchResult).slice(0, 1500)}\n`
|
|
3737
3586
|
: "\nNo search results found — consider creating foundational knowledge for these domains.\n";
|