@agent-native/core 0.49.2 → 0.49.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/agent/engine/builder-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/engine/index.d.ts +1 -1
- package/dist/agent/engine/index.d.ts.map +1 -1
- package/dist/agent/engine/index.js +1 -1
- package/dist/agent/engine/index.js.map +1 -1
- package/dist/agent/engine/registry.d.ts +1 -0
- package/dist/agent/engine/registry.d.ts.map +1 -1
- package/dist/agent/engine/registry.js +11 -0
- package/dist/agent/engine/registry.js.map +1 -1
- package/dist/agent/model-config.d.ts +2 -2
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +2 -6
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +3 -2
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/code-agent-executor.d.ts.map +1 -1
- package/dist/cli/code-agent-executor.js +3 -2
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +117 -33
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +20 -0
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +256 -40
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +2 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +5 -5
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +0 -7
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +14 -0
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +64 -2
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +0 -5
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +3 -2
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +3 -2
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/mcp/connect-route.d.ts +2 -0
- package/dist/mcp/connect-route.d.ts.map +1 -1
- package/dist/mcp/connect-route.js +3 -0
- package/dist/mcp/connect-route.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/observability/evals.d.ts.map +1 -1
- package/dist/observability/evals.js +5 -3
- package/dist/observability/evals.js.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +6 -3
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js +5 -1
- package/dist/scripts/agent-engines/manage-agent-engine.js.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.d.ts.map +1 -1
- package/dist/scripts/agent-engines/set-agent-engine.js +7 -2
- package/dist/scripts/agent-engines/set-agent-engine.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +14 -4
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/complete-text.d.ts.map +1 -1
- package/dist/server/complete-text.js +3 -2
- package/dist/server/complete-text.js.map +1 -1
- package/dist/server/core-routes-plugin.d.ts +2 -0
- package/dist/server/core-routes-plugin.d.ts.map +1 -1
- package/dist/server/core-routes-plugin.js +1 -0
- package/dist/server/core-routes-plugin.js.map +1 -1
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -6
- package/dist/triggers/dispatcher.d.ts.map +1 -1
- package/dist/triggers/dispatcher.js +3 -2
- package/dist/triggers/dispatcher.js.map +1 -1
- package/docs/content/external-agents.md +1 -1
- package/docs/content/plan-plugin.md +2 -2
- package/docs/content/pr-visual-recap.md +12 -4
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -6
|
@@ -115,14 +115,15 @@ To re-authenticate an already-installed local/fallback client without
|
|
|
115
115
|
reinstalling skills or connectors, use:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
npx @agent-native/core@latest reconnect https://dispatch.agent-native.com --client codex
|
|
118
|
+
npx -y @agent-native/core@latest reconnect https://dispatch.agent-native.com --client codex
|
|
119
119
|
# or:
|
|
120
|
-
npx @agent-native/core@latest connect reconnect https://dispatch.agent-native.com --client codex
|
|
120
|
+
npx -y @agent-native/core@latest connect reconnect https://dispatch.agent-native.com --client codex
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
With no URL, `reconnect` searches
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
With no URL, `reconnect` searches local client configs for the existing Agent
|
|
124
|
+
Native MCP entry. With a URL, it reconnects only the clients that already have
|
|
125
|
+
that MCP URL; pass `--client` to limit which configs it searches. Pass
|
|
126
|
+
`--name <serverName>` only when you need to force a custom server name.
|
|
126
127
|
|
|
127
128
|
Under the hood: a logged-in browser session mints an `A2A_SECRET`-signed JWT
|
|
128
129
|
carrying the caller's `sub` + `org_domain` and a unique `jti`, so tool runs
|
|
@@ -360,7 +361,7 @@ before telling the user they are unauthenticated.
|
|
|
360
361
|
|
|
361
362
|
- Do connect local/fallback clients to Dispatch with
|
|
362
363
|
`npx @agent-native/core@latest connect https://dispatch.agent-native.com`;
|
|
363
|
-
use `npx @agent-native/core@latest reconnect ...` for reauth without
|
|
364
|
+
use `npx -y @agent-native/core@latest reconnect ...` for reauth without
|
|
364
365
|
reinstalling; use a direct app URL only when the host should be isolated to
|
|
365
366
|
one app.
|
|
366
367
|
- Do add a `link` builder to any action that produces or lists a navigable
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,8BAA8B,CAAC;AAStC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKrD,iBAAS,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,kBAAkB,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAsFA;AAED,iBAAS,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB3E;AAID,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC9C,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgBD;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgC/D;AA4QD,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -9,7 +9,7 @@ import { subscribe, unsubscribe } from "../event-bus/index.js";
|
|
|
9
9
|
import { resourceListAllOwners, resourcePut } from "../resources/store.js";
|
|
10
10
|
import { runWithRequestContext } from "../server/request-context.js";
|
|
11
11
|
import { runAgentLoop, actionsToEngineTools, getOwnerActiveApiKey, } from "../agent/production-agent.js";
|
|
12
|
-
import { getStoredModelForEngine, resolveEngine, } from "../agent/engine/index.js";
|
|
12
|
+
import { getStoredModelForEngine, normalizeModelForEngine, resolveEngine, } from "../agent/engine/index.js";
|
|
13
13
|
import { createThread } from "../chat-threads/store.js";
|
|
14
14
|
import { evaluateCondition } from "./condition-evaluator.js";
|
|
15
15
|
// Re-use the job frontmatter parser — triggers extend the same format.
|
|
@@ -321,9 +321,10 @@ async function dispatchAgentic(resource, meta, body, payload, eventMeta, apiKey)
|
|
|
321
321
|
apiKey,
|
|
322
322
|
appId: _deps.appId,
|
|
323
323
|
});
|
|
324
|
-
const
|
|
324
|
+
const modelCandidate = _deps.model ??
|
|
325
325
|
(await getStoredModelForEngine(engine, { appId: _deps.appId })) ??
|
|
326
326
|
engine.defaultModel;
|
|
327
|
+
const model = normalizeModelForEngine(engine, modelCandidate);
|
|
327
328
|
await createThread(jobUserEmail, {
|
|
328
329
|
title: `Trigger: ${triggerName} — ${now.toLocaleDateString()}`,
|
|
329
330
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Trigger dispatcher — bridges the event bus to the automation system.\n *\n * On startup, loads all event-triggered jobs from the resources store,\n * subscribes to their events, and dispatches them (condition eval → agent\n * loop) when matching events fire.\n */\n\nimport { subscribe, unsubscribe } from \"../event-bus/index.js\";\nimport type { EventMeta } from \"../event-bus/types.js\";\nimport { resourceListAllOwners, resourcePut } from \"../resources/store.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n runAgentLoop,\n actionsToEngineTools,\n getOwnerActiveApiKey,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport {\n getStoredModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport type { AgentChatEvent } from \"../agent/types.js\";\nimport { evaluateCondition } from \"./condition-evaluator.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\n// Re-use the job frontmatter parser — triggers extend the same format.\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/;\n\nfunction parseTriggerFrontmatter(content: string): {\n meta: TriggerFrontmatter;\n body: string;\n} {\n const match = content.match(FRONTMATTER_RE);\n if (!match) {\n return {\n meta: {\n schedule: \"\",\n enabled: false,\n triggerType: \"schedule\",\n mode: \"agentic\",\n },\n body: content,\n };\n }\n\n const yamlBlock = match[1];\n const body = match[2].trim();\n\n const meta: TriggerFrontmatter = {\n schedule: \"\",\n enabled: true,\n triggerType: \"schedule\",\n mode: \"agentic\",\n };\n\n for (const line of yamlBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n let value = line.slice(colonIdx + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n switch (key) {\n case \"schedule\":\n meta.schedule = value;\n break;\n case \"enabled\":\n meta.enabled = value !== \"false\";\n break;\n case \"triggerType\":\n meta.triggerType =\n value === \"event\" || value === \"schedule\" ? value : \"schedule\";\n break;\n case \"event\":\n meta.event = value;\n break;\n case \"condition\":\n meta.condition = value;\n break;\n case \"mode\":\n meta.mode =\n value === \"deterministic\" || value === \"agentic\" ? value : \"agentic\";\n break;\n case \"domain\":\n meta.domain = value;\n break;\n case \"createdBy\":\n meta.createdBy = value;\n break;\n case \"orgId\":\n meta.orgId = value;\n break;\n case \"runAs\":\n meta.runAs =\n value === \"shared\" || value === \"creator\" ? value : undefined;\n break;\n case \"lastRun\":\n meta.lastRun = value;\n break;\n case \"lastStatus\":\n meta.lastStatus = value as TriggerFrontmatter[\"lastStatus\"];\n break;\n case \"lastError\":\n meta.lastError = value;\n break;\n case \"nextRun\":\n meta.nextRun = value;\n break;\n }\n }\n\n return { meta, body };\n}\n\nfunction buildTriggerContent(meta: TriggerFrontmatter, body: string): string {\n const lines = [\"---\"];\n lines.push(`schedule: \"${meta.schedule}\"`);\n lines.push(`enabled: ${meta.enabled}`);\n lines.push(`triggerType: ${meta.triggerType}`);\n if (meta.event) lines.push(`event: ${meta.event}`);\n if (meta.condition)\n lines.push(`condition: \"${meta.condition.replace(/\"/g, '\\\\\"')}\"`);\n lines.push(`mode: ${meta.mode}`);\n if (meta.domain) lines.push(`domain: ${meta.domain}`);\n if (meta.createdBy) lines.push(`createdBy: ${meta.createdBy}`);\n if (meta.orgId) lines.push(`orgId: ${meta.orgId}`);\n if (meta.runAs) lines.push(`runAs: ${meta.runAs}`);\n if (meta.lastRun) lines.push(`lastRun: ${meta.lastRun}`);\n if (meta.lastStatus) lines.push(`lastStatus: ${meta.lastStatus}`);\n if (meta.lastError)\n lines.push(`lastError: \"${meta.lastError.replace(/\"/g, '\\\\\"')}\"`);\n if (meta.nextRun) lines.push(`nextRun: ${meta.nextRun}`);\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(body);\n return lines.join(\"\\n\");\n}\n\n// ─── Dispatcher deps (same pattern as SchedulerDeps) ────────────────────────\n\nexport interface TriggerDispatcherDeps {\n getActions: () => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n apiKey?: string;\n model?: string;\n /** App/template id used for org-scoped per-app model defaults. */\n appId?: string;\n}\n\n// Track active subscriptions (eventName -> subscription id) to avoid\n// double-subscribing AND so subscriptions for events that no longer have any\n// enabled trigger can be torn down — otherwise deleted/disabled triggers leave\n// phantom bus listeners that fire handleEvent forever.\nconst _eventSubscriptions = new Map<string, string>();\n// In-flight agentic dispatches keyed by `${owner}:${path}`. Guards against the\n// check-then-write TOCTOU window in handleEvent: two near-simultaneous fires of\n// the same event both pass the `lastStatus !== \"running\"` check (which has\n// several awaits before the DB is marked running) and would otherwise launch\n// two concurrent agent runs for one trigger. Sufficient for single-process\n// deployments; multi-instance would need a conditional DB update.\nconst _dispatchingTriggers = new Set<string>();\nlet _deps: TriggerDispatcherDeps | null = null;\n\n/**\n * Initialize the trigger dispatcher. Call once at server startup.\n * Loads all event-triggered jobs and subscribes to their events.\n */\nexport async function initTriggerDispatcher(\n deps: TriggerDispatcherDeps,\n): Promise<void> {\n _deps = deps;\n await refreshEventSubscriptions();\n}\n\n/**\n * Refresh event subscriptions from the resource store.\n * Call after creating/updating triggers.\n */\nexport async function refreshEventSubscriptions(): Promise<void> {\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const eventNames = new Set<string>();\n\n for (const resource of jobResources) {\n if (!resource.path.endsWith(\".md\")) continue;\n const { meta } = parseTriggerFrontmatter(resource.content);\n if (meta.triggerType === \"event\" && meta.event && meta.enabled) {\n eventNames.add(meta.event);\n }\n }\n\n // Tear down subscriptions whose event no longer has any enabled trigger.\n for (const [eventName, subId] of [..._eventSubscriptions]) {\n if (!eventNames.has(eventName)) {\n unsubscribe(subId);\n _eventSubscriptions.delete(eventName);\n }\n }\n\n for (const eventName of eventNames) {\n if (!_eventSubscriptions.has(eventName)) {\n const subId = subscribe(eventName, (payload, eventMeta) =>\n handleEvent(eventName, payload, eventMeta),\n );\n _eventSubscriptions.set(eventName, subId);\n }\n }\n } catch (err) {\n console.error(\"[triggers] Failed to refresh event subscriptions:\", err);\n }\n}\n\nasync function handleEvent(\n eventName: string,\n payload: unknown,\n eventMeta: EventMeta,\n): Promise<void> {\n if (!_deps) return;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const matchingTriggers = jobResources.filter((r) => {\n if (!r.path.endsWith(\".md\")) return false;\n const { meta } = parseTriggerFrontmatter(r.content);\n // Scope: only dispatch triggers owned by the event's owner,\n // or shared triggers. Prevents cross-tenant trigger execution.\n if (\n eventMeta.owner &&\n r.owner !== eventMeta.owner &&\n r.owner !== \"__shared__\"\n ) {\n return false;\n }\n return (\n meta.triggerType === \"event\" &&\n meta.event === eventName &&\n meta.enabled &&\n meta.lastStatus !== \"running\"\n );\n });\n\n for (const resource of matchingTriggers) {\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n if (!body.trim()) continue;\n\n // Resolve API key for condition evaluation\n const owner = meta.createdBy || resource.owner;\n const userApiKey = await getOwnerActiveApiKey(owner);\n const apiKey =\n userApiKey || _deps.apiKey || process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n console.warn(\n `[triggers] No API key for trigger \"${resource.path}\" — skipping`,\n );\n continue;\n }\n\n // Evaluate condition\n const matches = await evaluateCondition(meta.condition, payload, apiKey);\n if (!matches) continue;\n\n // Dispatch. Guard against concurrent duplicate dispatch of the same\n // trigger (TOCTOU on lastStatus) with an in-process lock keyed on the\n // trigger's identity.\n const dispatchKey = `${resource.owner}:${resource.path}`;\n if (_dispatchingTriggers.has(dispatchKey)) continue;\n if (meta.mode === \"agentic\") {\n _dispatchingTriggers.add(dispatchKey);\n try {\n await dispatchAgentic(\n resource,\n meta,\n body,\n payload,\n eventMeta,\n apiKey,\n );\n } finally {\n _dispatchingTriggers.delete(dispatchKey);\n }\n } else {\n console.warn(\n `[triggers] Deterministic mode not yet implemented for \"${resource.path}\" — skipping`,\n );\n }\n }\n } catch (err) {\n console.error(`[triggers] Error handling event \"${eventName}\":`, err);\n }\n}\n\n/**\n * Validate that the run-as user still exists and (if scoped to an org) is\n * still a member of that org. Mirrors the recurring-jobs scheduler check\n * (audit 12 #10): event-triggered automations must stop firing when the\n * creator is removed/demoted.\n */\nasync function isTriggerRunAsStillValid(\n jobUserEmail: string,\n jobOrgId: string | undefined,\n): Promise<{ ok: boolean; reason?: string }> {\n if (jobUserEmail === \"__shared__\") return { ok: true };\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const db = getDbExec();\n const userResult = await db.execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [jobUserEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${jobUserEmail}\" no longer exists` };\n }\n if (jobOrgId) {\n const memberResult = await db.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [jobOrgId, jobUserEmail],\n });\n if (!memberResult.rows || memberResult.rows.length === 0) {\n return {\n ok: false,\n reason: `user \"${jobUserEmail}\" is no longer a member of org \"${jobOrgId}\"`,\n };\n }\n }\n return { ok: true };\n } catch (err: any) {\n const msg = err?.message?.toLowerCase() ?? \"\";\n if (\n msg.includes(\"does not exist\") ||\n msg.includes(\"no such table\") ||\n msg.includes(\"undefined table\")\n ) {\n return { ok: true };\n }\n console.warn(\n `[triggers] User/membership validation failed for \"${jobUserEmail}\":`,\n err?.message,\n );\n return { ok: true };\n }\n}\n\nasync function dispatchAgentic(\n resource: { path: string; owner: string; content: string },\n meta: TriggerFrontmatter,\n body: string,\n payload: unknown,\n eventMeta: EventMeta,\n apiKey: string,\n): Promise<void> {\n if (!_deps) return;\n\n const triggerName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n const now = new Date();\n\n const jobUserEmail = meta.createdBy || resource.owner;\n const jobOrgId = meta.orgId ?? undefined;\n\n // SECURITY (audit 12 #10): re-validate the run-as user/membership on\n // every dispatch. Sharing revocation, user deletion, and org-member\n // removal must take effect for already-scheduled triggers. Skip the\n // dispatch on failure; leave the trigger entry alone for admin review.\n const validity = await isTriggerRunAsStillValid(jobUserEmail, jobOrgId);\n if (!validity.ok) {\n console.warn(\n `[triggers] Skipping trigger \"${triggerName}\": ${validity.reason}. ` +\n `User/membership no longer valid — leaving entry for admin review.`,\n );\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = validity.reason;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n return;\n }\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n await runWithRequestContext(\n { userEmail: jobUserEmail, orgId: jobOrgId },\n async () => {\n try {\n const actions = _deps!.getActions();\n const systemPrompt = await _deps!.getSystemPrompt(jobUserEmail);\n const tools = actionsToEngineTools(actions);\n\n const engine = await resolveEngine({\n apiKey,\n appId: _deps!.appId,\n });\n const model =\n _deps!.model ??\n (await getStoredModelForEngine(engine, { appId: _deps!.appId })) ??\n engine.defaultModel;\n await createThread(jobUserEmail, {\n title: `Trigger: ${triggerName} — ${now.toLocaleDateString()}`,\n });\n\n let payloadStr: string;\n try {\n payloadStr = JSON.stringify(payload, null, 2);\n } catch {\n payloadStr = String(payload);\n }\n\n const triggerText = `[Automation Trigger: ${triggerName}]\nEvent: ${meta.event}\nEvent ID: ${eventMeta.eventId}\nFired at: ${eventMeta.emittedAt}\n\nEvent payload:\n${payloadStr}\n\nExecute the following automation instructions:\n\n${body}`;\n\n const messages = [\n {\n role: \"user\" as const,\n content: [{ type: \"text\" as const, text: triggerText }],\n },\n ];\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5 * 60 * 1000);\n\n const events: AgentChatEvent[] = [];\n\n try {\n await runAgentLoop({\n engine,\n model,\n systemPrompt,\n tools,\n messages,\n actions,\n send: (event) => events.push(event),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeout);\n }\n\n meta.lastStatus = \"success\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n console.log(`[triggers] \"${triggerName}\" completed successfully`);\n } catch (err: any) {\n meta.lastStatus = \"error\";\n meta.lastError = err?.message?.slice(0, 200) || \"Unknown error\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.error(`[triggers] \"${triggerName}\" failed:`, err?.message);\n }\n },\n );\n}\n\nexport { parseTriggerFrontmatter, buildTriggerContent };\n"]}
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/triggers/dispatcher.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Trigger dispatcher — bridges the event bus to the automation system.\n *\n * On startup, loads all event-triggered jobs from the resources store,\n * subscribes to their events, and dispatches them (condition eval → agent\n * loop) when matching events fire.\n */\n\nimport { subscribe, unsubscribe } from \"../event-bus/index.js\";\nimport type { EventMeta } from \"../event-bus/types.js\";\nimport { resourceListAllOwners, resourcePut } from \"../resources/store.js\";\nimport { runWithRequestContext } from \"../server/request-context.js\";\nimport {\n runAgentLoop,\n actionsToEngineTools,\n getOwnerActiveApiKey,\n type ActionEntry,\n} from \"../agent/production-agent.js\";\nimport {\n getStoredModelForEngine,\n normalizeModelForEngine,\n resolveEngine,\n} from \"../agent/engine/index.js\";\nimport { createThread } from \"../chat-threads/store.js\";\nimport type { AgentChatEvent } from \"../agent/types.js\";\nimport { evaluateCondition } from \"./condition-evaluator.js\";\nimport type { TriggerFrontmatter } from \"./types.js\";\n\n// Re-use the job frontmatter parser — triggers extend the same format.\nconst FRONTMATTER_RE = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/;\n\nfunction parseTriggerFrontmatter(content: string): {\n meta: TriggerFrontmatter;\n body: string;\n} {\n const match = content.match(FRONTMATTER_RE);\n if (!match) {\n return {\n meta: {\n schedule: \"\",\n enabled: false,\n triggerType: \"schedule\",\n mode: \"agentic\",\n },\n body: content,\n };\n }\n\n const yamlBlock = match[1];\n const body = match[2].trim();\n\n const meta: TriggerFrontmatter = {\n schedule: \"\",\n enabled: true,\n triggerType: \"schedule\",\n mode: \"agentic\",\n };\n\n for (const line of yamlBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n let value = line.slice(colonIdx + 1).trim();\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n switch (key) {\n case \"schedule\":\n meta.schedule = value;\n break;\n case \"enabled\":\n meta.enabled = value !== \"false\";\n break;\n case \"triggerType\":\n meta.triggerType =\n value === \"event\" || value === \"schedule\" ? value : \"schedule\";\n break;\n case \"event\":\n meta.event = value;\n break;\n case \"condition\":\n meta.condition = value;\n break;\n case \"mode\":\n meta.mode =\n value === \"deterministic\" || value === \"agentic\" ? value : \"agentic\";\n break;\n case \"domain\":\n meta.domain = value;\n break;\n case \"createdBy\":\n meta.createdBy = value;\n break;\n case \"orgId\":\n meta.orgId = value;\n break;\n case \"runAs\":\n meta.runAs =\n value === \"shared\" || value === \"creator\" ? value : undefined;\n break;\n case \"lastRun\":\n meta.lastRun = value;\n break;\n case \"lastStatus\":\n meta.lastStatus = value as TriggerFrontmatter[\"lastStatus\"];\n break;\n case \"lastError\":\n meta.lastError = value;\n break;\n case \"nextRun\":\n meta.nextRun = value;\n break;\n }\n }\n\n return { meta, body };\n}\n\nfunction buildTriggerContent(meta: TriggerFrontmatter, body: string): string {\n const lines = [\"---\"];\n lines.push(`schedule: \"${meta.schedule}\"`);\n lines.push(`enabled: ${meta.enabled}`);\n lines.push(`triggerType: ${meta.triggerType}`);\n if (meta.event) lines.push(`event: ${meta.event}`);\n if (meta.condition)\n lines.push(`condition: \"${meta.condition.replace(/\"/g, '\\\\\"')}\"`);\n lines.push(`mode: ${meta.mode}`);\n if (meta.domain) lines.push(`domain: ${meta.domain}`);\n if (meta.createdBy) lines.push(`createdBy: ${meta.createdBy}`);\n if (meta.orgId) lines.push(`orgId: ${meta.orgId}`);\n if (meta.runAs) lines.push(`runAs: ${meta.runAs}`);\n if (meta.lastRun) lines.push(`lastRun: ${meta.lastRun}`);\n if (meta.lastStatus) lines.push(`lastStatus: ${meta.lastStatus}`);\n if (meta.lastError)\n lines.push(`lastError: \"${meta.lastError.replace(/\"/g, '\\\\\"')}\"`);\n if (meta.nextRun) lines.push(`nextRun: ${meta.nextRun}`);\n lines.push(\"---\");\n lines.push(\"\");\n lines.push(body);\n return lines.join(\"\\n\");\n}\n\n// ─── Dispatcher deps (same pattern as SchedulerDeps) ────────────────────────\n\nexport interface TriggerDispatcherDeps {\n getActions: () => Record<string, ActionEntry>;\n getSystemPrompt: (owner: string) => Promise<string>;\n apiKey?: string;\n model?: string;\n /** App/template id used for org-scoped per-app model defaults. */\n appId?: string;\n}\n\n// Track active subscriptions (eventName -> subscription id) to avoid\n// double-subscribing AND so subscriptions for events that no longer have any\n// enabled trigger can be torn down — otherwise deleted/disabled triggers leave\n// phantom bus listeners that fire handleEvent forever.\nconst _eventSubscriptions = new Map<string, string>();\n// In-flight agentic dispatches keyed by `${owner}:${path}`. Guards against the\n// check-then-write TOCTOU window in handleEvent: two near-simultaneous fires of\n// the same event both pass the `lastStatus !== \"running\"` check (which has\n// several awaits before the DB is marked running) and would otherwise launch\n// two concurrent agent runs for one trigger. Sufficient for single-process\n// deployments; multi-instance would need a conditional DB update.\nconst _dispatchingTriggers = new Set<string>();\nlet _deps: TriggerDispatcherDeps | null = null;\n\n/**\n * Initialize the trigger dispatcher. Call once at server startup.\n * Loads all event-triggered jobs and subscribes to their events.\n */\nexport async function initTriggerDispatcher(\n deps: TriggerDispatcherDeps,\n): Promise<void> {\n _deps = deps;\n await refreshEventSubscriptions();\n}\n\n/**\n * Refresh event subscriptions from the resource store.\n * Call after creating/updating triggers.\n */\nexport async function refreshEventSubscriptions(): Promise<void> {\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const eventNames = new Set<string>();\n\n for (const resource of jobResources) {\n if (!resource.path.endsWith(\".md\")) continue;\n const { meta } = parseTriggerFrontmatter(resource.content);\n if (meta.triggerType === \"event\" && meta.event && meta.enabled) {\n eventNames.add(meta.event);\n }\n }\n\n // Tear down subscriptions whose event no longer has any enabled trigger.\n for (const [eventName, subId] of [..._eventSubscriptions]) {\n if (!eventNames.has(eventName)) {\n unsubscribe(subId);\n _eventSubscriptions.delete(eventName);\n }\n }\n\n for (const eventName of eventNames) {\n if (!_eventSubscriptions.has(eventName)) {\n const subId = subscribe(eventName, (payload, eventMeta) =>\n handleEvent(eventName, payload, eventMeta),\n );\n _eventSubscriptions.set(eventName, subId);\n }\n }\n } catch (err) {\n console.error(\"[triggers] Failed to refresh event subscriptions:\", err);\n }\n}\n\nasync function handleEvent(\n eventName: string,\n payload: unknown,\n eventMeta: EventMeta,\n): Promise<void> {\n if (!_deps) return;\n\n try {\n const jobResources = await resourceListAllOwners(\"jobs/\");\n const matchingTriggers = jobResources.filter((r) => {\n if (!r.path.endsWith(\".md\")) return false;\n const { meta } = parseTriggerFrontmatter(r.content);\n // Scope: only dispatch triggers owned by the event's owner,\n // or shared triggers. Prevents cross-tenant trigger execution.\n if (\n eventMeta.owner &&\n r.owner !== eventMeta.owner &&\n r.owner !== \"__shared__\"\n ) {\n return false;\n }\n return (\n meta.triggerType === \"event\" &&\n meta.event === eventName &&\n meta.enabled &&\n meta.lastStatus !== \"running\"\n );\n });\n\n for (const resource of matchingTriggers) {\n const { meta, body } = parseTriggerFrontmatter(resource.content);\n if (!body.trim()) continue;\n\n // Resolve API key for condition evaluation\n const owner = meta.createdBy || resource.owner;\n const userApiKey = await getOwnerActiveApiKey(owner);\n const apiKey =\n userApiKey || _deps.apiKey || process.env.ANTHROPIC_API_KEY;\n if (!apiKey) {\n console.warn(\n `[triggers] No API key for trigger \"${resource.path}\" — skipping`,\n );\n continue;\n }\n\n // Evaluate condition\n const matches = await evaluateCondition(meta.condition, payload, apiKey);\n if (!matches) continue;\n\n // Dispatch. Guard against concurrent duplicate dispatch of the same\n // trigger (TOCTOU on lastStatus) with an in-process lock keyed on the\n // trigger's identity.\n const dispatchKey = `${resource.owner}:${resource.path}`;\n if (_dispatchingTriggers.has(dispatchKey)) continue;\n if (meta.mode === \"agentic\") {\n _dispatchingTriggers.add(dispatchKey);\n try {\n await dispatchAgentic(\n resource,\n meta,\n body,\n payload,\n eventMeta,\n apiKey,\n );\n } finally {\n _dispatchingTriggers.delete(dispatchKey);\n }\n } else {\n console.warn(\n `[triggers] Deterministic mode not yet implemented for \"${resource.path}\" — skipping`,\n );\n }\n }\n } catch (err) {\n console.error(`[triggers] Error handling event \"${eventName}\":`, err);\n }\n}\n\n/**\n * Validate that the run-as user still exists and (if scoped to an org) is\n * still a member of that org. Mirrors the recurring-jobs scheduler check\n * (audit 12 #10): event-triggered automations must stop firing when the\n * creator is removed/demoted.\n */\nasync function isTriggerRunAsStillValid(\n jobUserEmail: string,\n jobOrgId: string | undefined,\n): Promise<{ ok: boolean; reason?: string }> {\n if (jobUserEmail === \"__shared__\") return { ok: true };\n try {\n const { getDbExec } = await import(\"../db/client.js\");\n const db = getDbExec();\n const userResult = await db.execute({\n sql: `SELECT 1 FROM \"user\" WHERE email = ? LIMIT 1`,\n args: [jobUserEmail],\n });\n if (!userResult.rows || userResult.rows.length === 0) {\n return { ok: false, reason: `user \"${jobUserEmail}\" no longer exists` };\n }\n if (jobOrgId) {\n const memberResult = await db.execute({\n sql: `SELECT 1 FROM org_members WHERE org_id = ? AND LOWER(email) = LOWER(?) LIMIT 1`,\n args: [jobOrgId, jobUserEmail],\n });\n if (!memberResult.rows || memberResult.rows.length === 0) {\n return {\n ok: false,\n reason: `user \"${jobUserEmail}\" is no longer a member of org \"${jobOrgId}\"`,\n };\n }\n }\n return { ok: true };\n } catch (err: any) {\n const msg = err?.message?.toLowerCase() ?? \"\";\n if (\n msg.includes(\"does not exist\") ||\n msg.includes(\"no such table\") ||\n msg.includes(\"undefined table\")\n ) {\n return { ok: true };\n }\n console.warn(\n `[triggers] User/membership validation failed for \"${jobUserEmail}\":`,\n err?.message,\n );\n return { ok: true };\n }\n}\n\nasync function dispatchAgentic(\n resource: { path: string; owner: string; content: string },\n meta: TriggerFrontmatter,\n body: string,\n payload: unknown,\n eventMeta: EventMeta,\n apiKey: string,\n): Promise<void> {\n if (!_deps) return;\n\n const triggerName = resource.path.replace(/^jobs\\//, \"\").replace(/\\.md$/, \"\");\n const now = new Date();\n\n const jobUserEmail = meta.createdBy || resource.owner;\n const jobOrgId = meta.orgId ?? undefined;\n\n // SECURITY (audit 12 #10): re-validate the run-as user/membership on\n // every dispatch. Sharing revocation, user deletion, and org-member\n // removal must take effect for already-scheduled triggers. Skip the\n // dispatch on failure; leave the trigger entry alone for admin review.\n const validity = await isTriggerRunAsStillValid(jobUserEmail, jobOrgId);\n if (!validity.ok) {\n console.warn(\n `[triggers] Skipping trigger \"${triggerName}\": ${validity.reason}. ` +\n `User/membership no longer valid — leaving entry for admin review.`,\n );\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"skipped\";\n meta.lastError = validity.reason;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n return;\n }\n\n // Mark as running\n meta.lastRun = now.toISOString();\n meta.lastStatus = \"running\";\n meta.lastError = undefined;\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n await runWithRequestContext(\n { userEmail: jobUserEmail, orgId: jobOrgId },\n async () => {\n try {\n const actions = _deps!.getActions();\n const systemPrompt = await _deps!.getSystemPrompt(jobUserEmail);\n const tools = actionsToEngineTools(actions);\n\n const engine = await resolveEngine({\n apiKey,\n appId: _deps!.appId,\n });\n const modelCandidate =\n _deps!.model ??\n (await getStoredModelForEngine(engine, { appId: _deps!.appId })) ??\n engine.defaultModel;\n const model = normalizeModelForEngine(engine, modelCandidate);\n await createThread(jobUserEmail, {\n title: `Trigger: ${triggerName} — ${now.toLocaleDateString()}`,\n });\n\n let payloadStr: string;\n try {\n payloadStr = JSON.stringify(payload, null, 2);\n } catch {\n payloadStr = String(payload);\n }\n\n const triggerText = `[Automation Trigger: ${triggerName}]\nEvent: ${meta.event}\nEvent ID: ${eventMeta.eventId}\nFired at: ${eventMeta.emittedAt}\n\nEvent payload:\n${payloadStr}\n\nExecute the following automation instructions:\n\n${body}`;\n\n const messages = [\n {\n role: \"user\" as const,\n content: [{ type: \"text\" as const, text: triggerText }],\n },\n ];\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5 * 60 * 1000);\n\n const events: AgentChatEvent[] = [];\n\n try {\n await runAgentLoop({\n engine,\n model,\n systemPrompt,\n tools,\n messages,\n actions,\n send: (event) => events.push(event),\n signal: controller.signal,\n });\n } finally {\n clearTimeout(timeout);\n }\n\n meta.lastStatus = \"success\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n\n console.log(`[triggers] \"${triggerName}\" completed successfully`);\n } catch (err: any) {\n meta.lastStatus = \"error\";\n meta.lastError = err?.message?.slice(0, 200) || \"Unknown error\";\n await resourcePut(\n resource.owner,\n resource.path,\n buildTriggerContent(meta, body),\n );\n console.error(`[triggers] \"${triggerName}\" failed:`, err?.message);\n }\n },\n );\n}\n\nexport { parseTriggerFrontmatter, buildTriggerContent };\n"]}
|
|
@@ -155,7 +155,7 @@ The connection is **per-user, scoped, and revocable**. In the OAuth path, the ho
|
|
|
155
155
|
Once connected, auth should persist long-term — access tokens last 30 days by default (override with `MCP_OAUTH_ACCESS_TOKEN_TTL` on the server, e.g. `7d` or `12h`) with a sliding 365-day refresh window, so random 401s should be rare. When one does happen, use the lightweight reconnect command rather than reinstalling:
|
|
156
156
|
|
|
157
157
|
```bash
|
|
158
|
-
npx @agent-native/core@latest reconnect https://plan.agent-native.com
|
|
158
|
+
npx -y @agent-native/core@latest reconnect https://plan.agent-native.com
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
`reconnect` finds any MCP config entry whose URL ends in `/_agent-native/mcp` for the given host (matching by URL regardless of connector name), then refreshes or replaces the auth material without touching your installed skills or re-running the full install flow. Pass the base app URL (e.g. `https://plan.agent-native.com`) — the `/_agent-native/mcp` suffix is inferred.
|
|
@@ -23,7 +23,7 @@ long-lived (30-day default, sliding 365-day refresh), so this should be rare;
|
|
|
23
23
|
when it happens, the lightweight fix is:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npx @agent-native/core@latest reconnect https://plan.agent-native.com
|
|
26
|
+
npx -y @agent-native/core@latest reconnect https://plan.agent-native.com
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
`reconnect` finds and refreshes the connector by URL — no reinstall needed. In
|
|
@@ -113,7 +113,7 @@ codex mcp login plan # OAuth in the browser
|
|
|
113
113
|
|
|
114
114
|
After install, **start a new Codex thread** so the skills and MCP tools load into the session. The plugin ships a URL-only connector (`[mcp_servers.plan]` → `https://plan.agent-native.com/_agent-native/mcp`); `codex mcp login plan` runs the OAuth flow. The universal CLI route above also works for Codex (`npx @agent-native/core@latest skills add visual-plan --client codex`) if you prefer one command that installs and authenticates together.
|
|
115
115
|
|
|
116
|
-
> **Older installs:** if your config still has an `agent-native-plans` entry pointing at the same URL, running `npx @agent-native/core@latest reconnect https://plan.agent-native.com` (or `skills add visual-plan` for a full reinstall) consolidates it to the canonical `plan` name.
|
|
116
|
+
> **Older installs:** if your config still has an `agent-native-plans` entry pointing at the same URL, running `npx -y @agent-native/core@latest reconnect https://plan.agent-native.com` (or `skills add visual-plan` for a full reinstall) consolidates it to the canonical `plan` name.
|
|
117
117
|
|
|
118
118
|
## Updates {#updates}
|
|
119
119
|
|
|
@@ -309,16 +309,24 @@ on:
|
|
|
309
309
|
|
|
310
310
|
jobs:
|
|
311
311
|
visual-recap:
|
|
312
|
+
permissions:
|
|
313
|
+
actions: write
|
|
314
|
+
contents: read
|
|
315
|
+
checks: write
|
|
316
|
+
issues: write
|
|
317
|
+
pull-requests: write
|
|
312
318
|
uses: BuilderIO/agent-native/.github/workflows/pr-visual-recap-reusable.yml@main
|
|
313
319
|
secrets:
|
|
314
320
|
PLAN_RECAP_TOKEN: ${{ secrets.PLAN_RECAP_TOKEN }}
|
|
315
321
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
316
|
-
|
|
317
|
-
|
|
322
|
+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
|
323
|
+
PLAN_RECAP_APP_URL: ${{ secrets.PLAN_RECAP_APP_URL }}
|
|
318
324
|
with:
|
|
325
|
+
agent: ${{ vars.VISUAL_RECAP_AGENT || 'claude' }}
|
|
326
|
+
model: ${{ vars.VISUAL_RECAP_MODEL || '' }}
|
|
327
|
+
reasoning: ${{ vars.VISUAL_RECAP_REASONING || '' }}
|
|
328
|
+
skill-source: ${{ vars.VISUAL_RECAP_SKILL_SOURCE || 'auto' }}
|
|
319
329
|
# cli-version: "latest" # pin to a specific @agent-native/core version
|
|
320
|
-
# reasoning: "high" # codex only: none|minimal|low|medium|high|xhigh
|
|
321
|
-
# skill-source: "repo" # pin to committed visual-recap skill
|
|
322
330
|
```
|
|
323
331
|
|
|
324
332
|
The same secrets and variables described in [Secrets and variables](#secrets-and-variables) apply — set them in your repo settings the same way as for the copy variant.
|
package/package.json
CHANGED
|
@@ -115,14 +115,15 @@ To re-authenticate an already-installed local/fallback client without
|
|
|
115
115
|
reinstalling skills or connectors, use:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
npx @agent-native/core@latest reconnect https://dispatch.agent-native.com --client codex
|
|
118
|
+
npx -y @agent-native/core@latest reconnect https://dispatch.agent-native.com --client codex
|
|
119
119
|
# or:
|
|
120
|
-
npx @agent-native/core@latest connect reconnect https://dispatch.agent-native.com --client codex
|
|
120
|
+
npx -y @agent-native/core@latest connect reconnect https://dispatch.agent-native.com --client codex
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
With no URL, `reconnect` searches
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
With no URL, `reconnect` searches local client configs for the existing Agent
|
|
124
|
+
Native MCP entry. With a URL, it reconnects only the clients that already have
|
|
125
|
+
that MCP URL; pass `--client` to limit which configs it searches. Pass
|
|
126
|
+
`--name <serverName>` only when you need to force a custom server name.
|
|
126
127
|
|
|
127
128
|
Under the hood: a logged-in browser session mints an `A2A_SECRET`-signed JWT
|
|
128
129
|
carrying the caller's `sub` + `org_domain` and a unique `jti`, so tool runs
|
|
@@ -360,7 +361,7 @@ before telling the user they are unauthenticated.
|
|
|
360
361
|
|
|
361
362
|
- Do connect local/fallback clients to Dispatch with
|
|
362
363
|
`npx @agent-native/core@latest connect https://dispatch.agent-native.com`;
|
|
363
|
-
use `npx @agent-native/core@latest reconnect ...` for reauth without
|
|
364
|
+
use `npx -y @agent-native/core@latest reconnect ...` for reauth without
|
|
364
365
|
reinstalling; use a direct app URL only when the host should be isolated to
|
|
365
366
|
one app.
|
|
366
367
|
- Do add a `link` builder to any action that produces or lists a navigable
|