@agent-native/core 0.22.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action-change-marker.d.ts +11 -0
- package/dist/action-change-marker.d.ts.map +1 -0
- package/dist/action-change-marker.js +52 -0
- package/dist/action-change-marker.js.map +1 -0
- package/dist/action.d.ts +2 -2
- package/dist/action.js +1 -1
- package/dist/action.js.map +1 -1
- package/dist/agent/production-agent.d.ts +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -6
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/client/agent-sidebar-state.d.ts.map +1 -1
- package/dist/client/agent-sidebar-state.js +0 -7
- package/dist/client/agent-sidebar-state.js.map +1 -1
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +7 -0
- package/dist/scripts/runner.js.map +1 -1
- package/dist/server/action-change.d.ts +8 -0
- package/dist/server/action-change.d.ts.map +1 -0
- package/dist/server/action-change.js +38 -0
- package/dist/server/action-change.js.map +1 -0
- package/dist/server/action-routes.d.ts.map +1 -1
- package/dist/server/action-routes.js +4 -6
- package/dist/server/action-routes.js.map +1 -1
- package/dist/server/poll.d.ts.map +1 -1
- package/dist/server/poll.js +55 -3
- package/dist/server/poll.js.map +1 -1
- package/dist/templates/default/.agents/skills/actions/SKILL.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -1
- package/docs/content/external-agents.md +1 -1
- package/docs/content/what-is-agent-native.md +1 -1
- package/package.json +1 -1
- package/src/templates/default/.agents/skills/actions/SKILL.md +1 -1
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -1
package/dist/server/poll.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Polling-based change notification.\n *\n * Replaces SSE with a simple version counter. Each DB mutation (app-state,\n * settings, resources) increments the version. Clients poll `/_agent-native/poll?since=N`\n * and receive any events that occurred after version N.\n *\n * Works in all deployment environments (serverless, edge, long-lived).\n *\n * Also detects cross-process DB writes by periodically checking the\n * application_state and settings tables' updated_at timestamps. This ensures\n * that changes made by external processes (e.g., CLI actions, cron jobs)\n * are picked up even though they don't call recordChange() in this process.\n */\n\nimport { EventEmitter } from \"node:events\";\nimport { defineEventHandler, getQuery, setResponseStatus } from \"h3\";\nimport { getAppStateEmitter } from \"../application-state/emitter.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport {\n EXTENSION_CHANGE_MARKER_KEY,\n parseExtensionChangeMarker,\n type ExtensionChangeTarget,\n} from \"../extensions/change-marker.js\";\nimport { getSettingsEmitter } from \"../settings/store.js\";\nimport { getSession } from \"./auth.js\";\n\nexport interface ChangeEvent {\n version: number;\n source: string;\n type: string;\n key?: string;\n /**\n * Owner email for tenant-scoped events. When absent, the event is treated\n * as deployment-global (e.g. table-level \"something changed\" pings) and\n * delivered to every authenticated poller. Specific events that should\n * only fan out to one user MUST set this — otherwise polling clients\n * across tenants see each other's signals.\n */\n owner?: string;\n /** Optional org ID for org-scoped events. */\n orgId?: string;\n [k: string]: unknown;\n}\n\n// In-memory ring buffer of recent changes. Kept small since clients\n// poll frequently (every 2-3s) and only need events since their last poll.\nconst MAX_BUFFER = 200;\nlet _version = 0;\nconst _buffer: ChangeEvent[] = [];\nexport const POLL_CHANGE_EVENT = \"poll-change\";\nconst _pollEmitter = new EventEmitter();\n_pollEmitter.setMaxListeners(0);\n\n/**\n * Whether we've seeded _version from the DB. In serverless (Netlify,\n * Vercel, etc.) each invocation starts fresh — without seeding, _version\n * resets to 0 and polling clients see the version jump backwards, causing\n * duplicate events and stuck UI.\n */\nlet _versionSeeded = false;\n\n/** Tracks the latest updated_at we've seen from the DB, per table. */\nlet _lastDbCheck = 0;\nlet _lastAppStateTs = 0;\nlet _lastSettingsTs = 0;\nlet _lastExtensionsTs = 0;\nlet _lastExtensionsUpdatedAt: string | number | undefined;\nlet _lastExtensionMarkerTs = 0;\n\n/**\n * Tracks the latest updated_at seen on the `__screen_refresh__` key in\n * application_state. Bumped when the agent calls the `refresh-screen` tool,\n * and surfaced as a distinct `screen-refresh` event so clients can remount\n * the main content subtree via React key.\n *\n * `_screenRefreshInitialized` guards against spurious emits on the first\n * poll after a restart (where an existing row would look like a fresh bump).\n * Once we've taken a baseline reading, any subsequent increase emits.\n */\nlet _lastScreenRefreshTs = 0;\nlet _screenRefreshInitialized = false;\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nlet _localEmittersWired = false;\n\nfunction wireLocalEmitters(): void {\n if (_localEmittersWired) return;\n _localEmittersWired = true;\n getAppStateEmitter().on(\"app-state\", (event) => {\n recordChange(event);\n });\n getSettingsEmitter().on(\"settings\", (event) => {\n recordChange(event);\n });\n}\n\nfunction timestampValue(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") return 0;\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction sqlWatermarkValue(value: unknown): string | number | undefined {\n if (typeof value === \"string\" && value.length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n return undefined;\n}\n\nasync function readMaxUpdatedAtRaw(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<unknown> {\n try {\n const result = await db.execute(\n `SELECT MAX(updated_at) as max_ts FROM ${table}`,\n );\n return result.rows[0]?.max_ts;\n } catch {\n // Optional framework tables may not exist in every app yet.\n return undefined;\n }\n}\n\nasync function readMaxUpdatedAt(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<number> {\n return timestampValue(await readMaxUpdatedAtRaw(db, table));\n}\n\nasync function readExtensionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\n/** Get the current global version counter. */\nexport function getVersion(): number {\n return _version;\n}\n\nexport function getPollEmitter(): EventEmitter {\n return _pollEmitter;\n}\n\nexport function canSeeChangeForUser(\n event: ChangeEvent,\n userEmail: string,\n orgId: string | undefined,\n): boolean {\n // Global / unowned events: every authenticated user gets them.\n if (!event.owner && !event.orgId) return true;\n if (event.owner && event.owner === userEmail) return true;\n if (event.orgId && orgId && event.orgId === orgId) return true;\n return false;\n}\n\n/** Record a change event. Called by emitter listeners. */\nexport function recordChange(event: {\n source: string;\n type: string;\n key?: string;\n [k: string]: unknown;\n}): void {\n // Use timestamp-aligned versions so all serverless instances produce\n // values in the same range (seeded from DB, then incremented via\n // Date.now). Plain ++counter diverges across cold starts.\n _version = Math.max(_version + 1, Date.now());\n const entry: ChangeEvent = { ...event, version: _version };\n _buffer.push(entry);\n if (_buffer.length > MAX_BUFFER) {\n _buffer.splice(0, _buffer.length - MAX_BUFFER);\n }\n _pollEmitter.emit(POLL_CHANGE_EVENT, entry);\n}\n\nfunction extensionTargetKey(target: ExtensionChangeTarget): string | null {\n if (target.owner) return `owner:${target.owner}`;\n if (target.orgId) return `org:${target.orgId}`;\n return null;\n}\n\nfunction addExtensionTarget(\n targets: Map<string, ExtensionChangeTarget>,\n target: ExtensionChangeTarget,\n): void {\n const key = extensionTargetKey(target);\n if (key) targets.set(key, target);\n}\n\nfunction recordExtensionChanges(targets: ExtensionChangeTarget[]): void {\n const uniqueTargets = new Map<string, ExtensionChangeTarget>();\n for (const target of targets) addExtensionTarget(uniqueTargets, target);\n for (const target of uniqueTargets.values()) {\n recordChange({\n source: \"extensions\",\n type: \"change\",\n key: \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction extensionTargetsForRow(\n row: Record<string, unknown>,\n shareRows: Array<Record<string, unknown>>,\n): ExtensionChangeTarget[] {\n const targets = new Map<string, ExtensionChangeTarget>();\n const owner = typeof row.owner_email === \"string\" ? row.owner_email : \"\";\n const orgId = typeof row.org_id === \"string\" ? row.org_id : \"\";\n const visibility =\n typeof row.visibility === \"string\" ? row.visibility : \"private\";\n\n if (owner) addExtensionTarget(targets, { owner });\n if (visibility === \"org\" && orgId) addExtensionTarget(targets, { orgId });\n\n for (const share of shareRows) {\n const principalType =\n typeof share.principal_type === \"string\" ? share.principal_type : \"\";\n const principalId =\n typeof share.principal_id === \"string\" ? share.principal_id : \"\";\n if (principalType === \"user\" && principalId) {\n addExtensionTarget(targets, { owner: principalId });\n } else if (principalType === \"org\" && principalId) {\n addExtensionTarget(targets, { orgId: principalId });\n }\n }\n\n return Array.from(targets.values());\n}\n\nasync function readExtensionTargetsForRows(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n rows: Array<Record<string, unknown>>,\n): Promise<ExtensionChangeTarget[][]> {\n const ids = rows\n .map((row) => (typeof row.id === \"string\" ? row.id : \"\"))\n .filter(Boolean);\n const sharesByResourceId = new Map<string, Array<Record<string, unknown>>>();\n\n if (ids.length > 0) {\n try {\n const placeholders = ids.map(() => \"?\").join(\", \");\n const shareResult = await db.execute({\n sql: `SELECT resource_id, principal_type, principal_id FROM tool_shares WHERE resource_id IN (${placeholders})`,\n args: ids,\n });\n for (const share of shareResult.rows) {\n const resourceId =\n typeof share.resource_id === \"string\" ? share.resource_id : \"\";\n if (!resourceId) continue;\n const bucket = sharesByResourceId.get(resourceId) ?? [];\n bucket.push(share);\n sharesByResourceId.set(resourceId, bucket);\n }\n } catch {\n // Sharing tables are optional during early app initialization.\n }\n }\n\n return rows.map((row) =>\n extensionTargetsForRow(\n row,\n sharesByResourceId.get(typeof row.id === \"string\" ? row.id : \"\") ?? [],\n ),\n );\n}\n\n/** Get all changes after a given version. */\nexport function getChangesSince(since: number): {\n version: number;\n events: ChangeEvent[];\n} {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter((e) => e.version > since);\n return { version: _version, events };\n}\n\n/**\n * Get changes after a given version, filtered to events the caller is\n * allowed to see.\n *\n * Filtering rules:\n * - Events without an `owner` are deployment-global (table-level pings,\n * screen-refresh, etc.) and visible to every authenticated user.\n * - Events with `owner === userEmail` go to that user.\n * - Events with `orgId === orgId` go to anyone in that org.\n * - All other owned events are filtered out.\n */\nexport function getChangesSinceForUser(\n since: number,\n userEmail: string,\n orgId: string | undefined,\n): { version: number; events: ChangeEvent[] } {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter(\n (e) => e.version > since && canSeeChangeForUser(e, userEmail, orgId),\n );\n return { version: _version, events };\n}\n\n/**\n * Seed _version from DB timestamps on the first call so serverless\n * cold starts don't return version 0 and confuse polling clients.\n */\nasync function seedVersionFromDb(): Promise<void> {\n if (_versionSeeded) return;\n _versionSeeded = true;\n\n try {\n const db = getDbExec();\n\n const [\n appTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n extensionMarkerTs,\n refreshResult,\n ] = await Promise.all([\n readMaxUpdatedAt(db, \"application_state\"),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n readExtensionMarkerMaxUpdatedAt(db),\n db\n .execute({\n sql: \"SELECT updated_at FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n })\n .catch(() => ({ rows: [] })),\n ]);\n\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n const refreshTs = timestampValue(refreshResult.rows[0]?.updated_at);\n\n // Seed version — never decrease an already-set value\n _version = Math.max(\n _version,\n appTs,\n settingsTs,\n extensionsTs,\n extensionMarkerTs,\n );\n\n // Set baselines so checkExternalDbChanges detects future writes\n _lastAppStateTs = appTs;\n _lastSettingsTs = settingsTs;\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n _lastExtensionMarkerTs = extensionMarkerTs;\n _lastScreenRefreshTs = refreshTs;\n _screenRefreshInitialized = true;\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Check for cross-process DB writes by comparing updated_at timestamps.\n * Runs at most once per second to avoid excessive queries.\n */\nasync function checkExternalDbChanges(): Promise<void> {\n const now = Date.now();\n if (now - _lastDbCheck < 1000) return;\n _lastDbCheck = now;\n\n try {\n const db = getDbExec();\n\n // Check application_state for external writes. Preserve the changed key so\n // clients can invalidate one-shot command queries (`navigate`, `__set_url__`)\n // only when those command rows actually change; noisy keys such as\n // `slide-fit-check` should not wake navigation readers.\n const appResult = await db.execute({\n sql: \"SELECT session_id, key, updated_at FROM application_state WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [_lastAppStateTs],\n });\n if (appResult.rows.length > 0) {\n const appTs = appResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n _lastAppStateTs,\n );\n if (_lastAppStateTs > 0) {\n for (const row of appResult.rows) {\n const key = typeof row.key === \"string\" ? row.key : \"*\";\n if (key === EXTENSION_CHANGE_MARKER_KEY) continue;\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n recordChange({\n source: \"app-state\",\n type: \"change\",\n key,\n ...(owner ? { owner } : {}),\n });\n }\n }\n _lastAppStateTs = appTs;\n }\n\n // Check for screen-refresh requests from the agent. The `refresh-screen`\n // tool writes to application_state under a well-known key; when its\n // updated_at bumps, emit a distinct event so the client invalidates\n // all queries (not just the ones matching its default queryKey prefix).\n const refreshResult = await db.execute({\n sql: \"SELECT updated_at, value FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n });\n const refreshTs = timestampValue(refreshResult.rows[0]?.updated_at);\n if (!_screenRefreshInitialized) {\n _lastScreenRefreshTs = refreshTs;\n _screenRefreshInitialized = true;\n } else if (refreshTs > _lastScreenRefreshTs) {\n let scope: string | undefined;\n try {\n const raw = refreshResult.rows[0]?.value;\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw);\n if (typeof parsed?.scope === \"string\") scope = parsed.scope;\n }\n } catch {}\n recordChange({\n source: \"screen-refresh\",\n type: \"change\",\n key: SCREEN_REFRESH_KEY,\n ...(scope ? { scope } : {}),\n });\n _lastScreenRefreshTs = refreshTs;\n }\n\n // Extension mutations write a durable marker row so delete and hide/unhide\n // operations are visible across serverless invocations. Translate those\n // marker rows back into extension-source events for targeted client\n // invalidation while preserving user/org scope.\n const extensionMarkerTs = await readExtensionMarkerMaxUpdatedAt(db);\n if (extensionMarkerTs > _lastExtensionMarkerTs) {\n const extensionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n const changedExtensionMarkers = extensionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionMarkerTs,\n );\n if (_lastExtensionMarkerTs > 0) {\n recordExtensionChanges(\n changedExtensionMarkers\n .map((row) => parseExtensionChangeMarker(row.session_id, row.value))\n .filter((target): target is ExtensionChangeTarget => !!target),\n );\n }\n _lastExtensionMarkerTs = extensionMarkerTs;\n }\n\n // Check settings for external writes\n const settingsTs = await readMaxUpdatedAt(db, \"settings\");\n if (settingsTs > _lastSettingsTs) {\n if (_lastSettingsTs > 0) {\n recordChange({ source: \"settings\", type: \"change\", key: \"*\" });\n }\n _lastSettingsTs = settingsTs;\n }\n\n // Extension rows live in the legacy physical `tools` table. Keep this as a\n // compatibility fallback for direct table writes, but scope events to the\n // resource owner/share targets instead of broadcasting deployment-wide.\n const extensionsMaxUpdatedAt = await readMaxUpdatedAtRaw(db, \"tools\");\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n if (extensionsTs > _lastExtensionsTs) {\n const since = _lastExtensionsUpdatedAt;\n const extensionResult =\n since === undefined\n ? await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools ORDER BY updated_at ASC\",\n args: [],\n })\n : await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [since],\n });\n const changedExtensionRows = extensionResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionsTs,\n );\n if (_lastExtensionsTs > 0) {\n const targetsByRow = await readExtensionTargetsForRows(\n db,\n changedExtensionRows,\n );\n for (const targets of targetsByRow) recordExtensionChanges(targets);\n }\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n }\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Create an H3 handler for the poll endpoint.\n *\n * GET /_agent-native/poll?since=N → { version, events[] }\n *\n * Requires an authenticated session. Events are filtered to the caller's\n * tenant — global events (owner-less, table-level pings) reach every\n * authenticated caller; owned events reach only the matching user/org.\n * Without auth + filtering, an anonymous attacker could poll the deployment\n * and infer cross-tenant activity from the global event stream.\n */\nexport function createPollHandler() {\n wireLocalEmitters();\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n // On cold start, seed _version from DB so we don't return version: 0\n await seedVersionFromDb();\n // Check for cross-process writes before responding\n await checkExternalDbChanges();\n\n const query = getQuery(event);\n const since = parseInt(String(query.since ?? \"0\"), 10) || 0;\n return getChangesSinceForUser(since, session.email, session.orgId);\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/server/poll.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Polling-based change notification.\n *\n * Replaces SSE with a simple version counter. Each DB mutation (app-state,\n * settings, resources) increments the version. Clients poll `/_agent-native/poll?since=N`\n * and receive any events that occurred after version N.\n *\n * Works in all deployment environments (serverless, edge, long-lived).\n *\n * Also detects cross-process DB writes by periodically checking the\n * application_state and settings tables' updated_at timestamps. This ensures\n * that changes made by external processes (e.g., CLI actions, cron jobs)\n * are picked up even though they don't call recordChange() in this process.\n */\n\nimport { EventEmitter } from \"node:events\";\nimport { defineEventHandler, getQuery, setResponseStatus } from \"h3\";\nimport {\n ACTION_CHANGE_MARKER_KEY,\n parseActionChangeMarker,\n type ActionChangeTarget,\n} from \"../action-change-marker.js\";\nimport { getAppStateEmitter } from \"../application-state/emitter.js\";\nimport { getDbExec } from \"../db/client.js\";\nimport {\n EXTENSION_CHANGE_MARKER_KEY,\n parseExtensionChangeMarker,\n type ExtensionChangeTarget,\n} from \"../extensions/change-marker.js\";\nimport { getSettingsEmitter } from \"../settings/store.js\";\nimport { getSession } from \"./auth.js\";\n\nexport interface ChangeEvent {\n version: number;\n source: string;\n type: string;\n key?: string;\n /**\n * Owner email for tenant-scoped events. When absent, the event is treated\n * as deployment-global (e.g. table-level \"something changed\" pings) and\n * delivered to every authenticated poller. Specific events that should\n * only fan out to one user MUST set this — otherwise polling clients\n * across tenants see each other's signals.\n */\n owner?: string;\n /** Optional org ID for org-scoped events. */\n orgId?: string;\n [k: string]: unknown;\n}\n\n// In-memory ring buffer of recent changes. Kept small since clients\n// poll frequently (every 2-3s) and only need events since their last poll.\nconst MAX_BUFFER = 200;\nlet _version = 0;\nconst _buffer: ChangeEvent[] = [];\nexport const POLL_CHANGE_EVENT = \"poll-change\";\nconst _pollEmitter = new EventEmitter();\n_pollEmitter.setMaxListeners(0);\n\n/**\n * Whether we've seeded _version from the DB. In serverless (Netlify,\n * Vercel, etc.) each invocation starts fresh — without seeding, _version\n * resets to 0 and polling clients see the version jump backwards, causing\n * duplicate events and stuck UI.\n */\nlet _versionSeeded = false;\n\n/** Tracks the latest updated_at we've seen from the DB, per table. */\nlet _lastDbCheck = 0;\nlet _lastAppStateTs = 0;\nlet _lastSettingsTs = 0;\nlet _lastExtensionsTs = 0;\nlet _lastExtensionsUpdatedAt: string | number | undefined;\nlet _lastExtensionMarkerTs = 0;\nlet _lastActionMarkerTs = 0;\n\n/**\n * Tracks the latest updated_at seen on the `__screen_refresh__` key in\n * application_state. Bumped when the agent calls the `refresh-screen` tool,\n * and surfaced as a distinct `screen-refresh` event so clients can remount\n * the main content subtree via React key.\n *\n * `_screenRefreshInitialized` guards against spurious emits on the first\n * poll after a restart (where an existing row would look like a fresh bump).\n * Once we've taken a baseline reading, any subsequent increase emits.\n */\nlet _lastScreenRefreshTs = 0;\nlet _screenRefreshInitialized = false;\nconst SCREEN_REFRESH_KEY = \"__screen_refresh__\";\nlet _localEmittersWired = false;\n\nfunction wireLocalEmitters(): void {\n if (_localEmittersWired) return;\n _localEmittersWired = true;\n getAppStateEmitter().on(\"app-state\", (event) => {\n if (\n event.key === EXTENSION_CHANGE_MARKER_KEY ||\n event.key === ACTION_CHANGE_MARKER_KEY\n ) {\n return;\n }\n recordChange(event);\n });\n getSettingsEmitter().on(\"settings\", (event) => {\n recordChange(event);\n });\n}\n\nfunction timestampValue(value: unknown): number {\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value !== \"string\") return 0;\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction sqlWatermarkValue(value: unknown): string | number | undefined {\n if (typeof value === \"string\" && value.length > 0) return value;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n return undefined;\n}\n\nasync function readMaxUpdatedAtRaw(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<unknown> {\n try {\n const result = await db.execute(\n `SELECT MAX(updated_at) as max_ts FROM ${table}`,\n );\n return result.rows[0]?.max_ts;\n } catch {\n // Optional framework tables may not exist in every app yet.\n return undefined;\n }\n}\n\nasync function readMaxUpdatedAt(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n table: \"application_state\" | \"settings\" | \"tools\",\n): Promise<number> {\n return timestampValue(await readMaxUpdatedAtRaw(db, table));\n}\n\nasync function readExtensionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\nasync function readActionMarkerMaxUpdatedAt(db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n}): Promise<number> {\n try {\n const result = await db.execute({\n sql: \"SELECT MAX(updated_at) as max_ts FROM application_state WHERE key = ?\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n return timestampValue(result.rows[0]?.max_ts);\n } catch {\n return 0;\n }\n}\n\n/** Get the current global version counter. */\nexport function getVersion(): number {\n return _version;\n}\n\nexport function getPollEmitter(): EventEmitter {\n return _pollEmitter;\n}\n\nexport function canSeeChangeForUser(\n event: ChangeEvent,\n userEmail: string,\n orgId: string | undefined,\n): boolean {\n // Global / unowned events: every authenticated user gets them.\n if (!event.owner && !event.orgId) return true;\n if (event.owner && event.owner === userEmail) return true;\n if (event.orgId && orgId && event.orgId === orgId) return true;\n return false;\n}\n\n/** Record a change event. Called by emitter listeners. */\nexport function recordChange(event: {\n source: string;\n type: string;\n key?: string;\n [k: string]: unknown;\n}): void {\n // Use timestamp-aligned versions so all serverless instances produce\n // values in the same range (seeded from DB, then incremented via\n // Date.now). Plain ++counter diverges across cold starts.\n _version = Math.max(_version + 1, Date.now());\n const entry: ChangeEvent = { ...event, version: _version };\n _buffer.push(entry);\n if (_buffer.length > MAX_BUFFER) {\n _buffer.splice(0, _buffer.length - MAX_BUFFER);\n }\n _pollEmitter.emit(POLL_CHANGE_EVENT, entry);\n}\n\nfunction extensionTargetKey(target: ExtensionChangeTarget): string | null {\n if (target.owner) return `owner:${target.owner}`;\n if (target.orgId) return `org:${target.orgId}`;\n return null;\n}\n\nfunction addExtensionTarget(\n targets: Map<string, ExtensionChangeTarget>,\n target: ExtensionChangeTarget,\n): void {\n const key = extensionTargetKey(target);\n if (key) targets.set(key, target);\n}\n\nfunction recordExtensionChanges(targets: ExtensionChangeTarget[]): void {\n const uniqueTargets = new Map<string, ExtensionChangeTarget>();\n for (const target of targets) addExtensionTarget(uniqueTargets, target);\n for (const target of uniqueTargets.values()) {\n recordChange({\n source: \"extensions\",\n type: \"change\",\n key: \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction recordActionChanges(targets: ActionChangeTarget[]): void {\n for (const target of targets) {\n recordChange({\n source: \"action\",\n type: \"change\",\n key: target.actionName ?? \"*\",\n ...(target.owner ? { owner: target.owner } : {}),\n ...(target.orgId ? { orgId: target.orgId } : {}),\n });\n }\n}\n\nfunction extensionTargetsForRow(\n row: Record<string, unknown>,\n shareRows: Array<Record<string, unknown>>,\n): ExtensionChangeTarget[] {\n const targets = new Map<string, ExtensionChangeTarget>();\n const owner = typeof row.owner_email === \"string\" ? row.owner_email : \"\";\n const orgId = typeof row.org_id === \"string\" ? row.org_id : \"\";\n const visibility =\n typeof row.visibility === \"string\" ? row.visibility : \"private\";\n\n if (owner) addExtensionTarget(targets, { owner });\n if (visibility === \"org\" && orgId) addExtensionTarget(targets, { orgId });\n\n for (const share of shareRows) {\n const principalType =\n typeof share.principal_type === \"string\" ? share.principal_type : \"\";\n const principalId =\n typeof share.principal_id === \"string\" ? share.principal_id : \"\";\n if (principalType === \"user\" && principalId) {\n addExtensionTarget(targets, { owner: principalId });\n } else if (principalType === \"org\" && principalId) {\n addExtensionTarget(targets, { orgId: principalId });\n }\n }\n\n return Array.from(targets.values());\n}\n\nasync function readExtensionTargetsForRows(\n db: {\n execute: (\n query: string | { sql: string; args?: unknown[] },\n ) => Promise<{ rows: Array<Record<string, unknown>> }>;\n },\n rows: Array<Record<string, unknown>>,\n): Promise<ExtensionChangeTarget[][]> {\n const ids = rows\n .map((row) => (typeof row.id === \"string\" ? row.id : \"\"))\n .filter(Boolean);\n const sharesByResourceId = new Map<string, Array<Record<string, unknown>>>();\n\n if (ids.length > 0) {\n try {\n const placeholders = ids.map(() => \"?\").join(\", \");\n const shareResult = await db.execute({\n sql: `SELECT resource_id, principal_type, principal_id FROM tool_shares WHERE resource_id IN (${placeholders})`,\n args: ids,\n });\n for (const share of shareResult.rows) {\n const resourceId =\n typeof share.resource_id === \"string\" ? share.resource_id : \"\";\n if (!resourceId) continue;\n const bucket = sharesByResourceId.get(resourceId) ?? [];\n bucket.push(share);\n sharesByResourceId.set(resourceId, bucket);\n }\n } catch {\n // Sharing tables are optional during early app initialization.\n }\n }\n\n return rows.map((row) =>\n extensionTargetsForRow(\n row,\n sharesByResourceId.get(typeof row.id === \"string\" ? row.id : \"\") ?? [],\n ),\n );\n}\n\n/** Get all changes after a given version. */\nexport function getChangesSince(since: number): {\n version: number;\n events: ChangeEvent[];\n} {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter((e) => e.version > since);\n return { version: _version, events };\n}\n\n/**\n * Get changes after a given version, filtered to events the caller is\n * allowed to see.\n *\n * Filtering rules:\n * - Events without an `owner` are deployment-global (table-level pings,\n * screen-refresh, etc.) and visible to every authenticated user.\n * - Events with `owner === userEmail` go to that user.\n * - Events with `orgId === orgId` go to anyone in that org.\n * - All other owned events are filtered out.\n */\nexport function getChangesSinceForUser(\n since: number,\n userEmail: string,\n orgId: string | undefined,\n): { version: number; events: ChangeEvent[] } {\n if (since >= _version) {\n return { version: _version, events: [] };\n }\n const events = _buffer.filter(\n (e) => e.version > since && canSeeChangeForUser(e, userEmail, orgId),\n );\n return { version: _version, events };\n}\n\n/**\n * Seed _version from DB timestamps on the first call so serverless\n * cold starts don't return version 0 and confuse polling clients.\n */\nasync function seedVersionFromDb(): Promise<void> {\n if (_versionSeeded) return;\n _versionSeeded = true;\n\n try {\n const db = getDbExec();\n\n const [\n appTs,\n settingsTs,\n extensionsMaxUpdatedAt,\n extensionMarkerTs,\n actionMarkerTs,\n refreshResult,\n ] = await Promise.all([\n readMaxUpdatedAt(db, \"application_state\"),\n readMaxUpdatedAt(db, \"settings\"),\n readMaxUpdatedAtRaw(db, \"tools\"),\n readExtensionMarkerMaxUpdatedAt(db),\n readActionMarkerMaxUpdatedAt(db),\n db\n .execute({\n sql: \"SELECT updated_at FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n })\n .catch(() => ({ rows: [] })),\n ]);\n\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n const refreshTs = timestampValue(refreshResult.rows[0]?.updated_at);\n\n // Seed version — never decrease an already-set value\n _version = Math.max(\n _version,\n appTs,\n settingsTs,\n extensionsTs,\n extensionMarkerTs,\n actionMarkerTs,\n );\n\n // Set baselines so checkExternalDbChanges detects future writes\n _lastAppStateTs = appTs;\n _lastSettingsTs = settingsTs;\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n _lastExtensionMarkerTs = extensionMarkerTs;\n // Action markers are durable specifically so a web server can observe work\n // performed by a separate action process. Do not baseline past an existing\n // marker on cold start, or the first poll after the action will miss it.\n _lastActionMarkerTs = 0;\n _lastScreenRefreshTs = refreshTs;\n _screenRefreshInitialized = true;\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Check for cross-process DB writes by comparing updated_at timestamps.\n * Runs at most once per second to avoid excessive queries.\n */\nasync function checkExternalDbChanges(): Promise<void> {\n const now = Date.now();\n if (now - _lastDbCheck < 1000) return;\n _lastDbCheck = now;\n\n try {\n const db = getDbExec();\n\n // Check application_state for external writes. Preserve the changed key so\n // clients can invalidate one-shot command queries (`navigate`, `__set_url__`)\n // only when those command rows actually change; noisy keys such as\n // `slide-fit-check` should not wake navigation readers.\n const appResult = await db.execute({\n sql: \"SELECT session_id, key, updated_at FROM application_state WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [_lastAppStateTs],\n });\n if (appResult.rows.length > 0) {\n const appTs = appResult.rows.reduce(\n (max, row) => Math.max(max, timestampValue(row.updated_at)),\n _lastAppStateTs,\n );\n if (_lastAppStateTs > 0) {\n for (const row of appResult.rows) {\n const key = typeof row.key === \"string\" ? row.key : \"*\";\n if (\n key === EXTENSION_CHANGE_MARKER_KEY ||\n key === ACTION_CHANGE_MARKER_KEY\n ) {\n continue;\n }\n const owner =\n typeof row.session_id === \"string\" ? row.session_id : undefined;\n recordChange({\n source: \"app-state\",\n type: \"change\",\n key,\n ...(owner ? { owner } : {}),\n });\n }\n }\n _lastAppStateTs = appTs;\n }\n\n // Mutating actions write a durable marker in addition to the in-process\n // event. This lets dev-mode `pnpm action ...` child processes and\n // serverless action invocations wake the web server's SSE/poll loop as a\n // first-class source:\"action\" event rather than a generic app-state bump.\n const actionMarkerTs = await readActionMarkerMaxUpdatedAt(db);\n if (actionMarkerTs > _lastActionMarkerTs) {\n const actionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [ACTION_CHANGE_MARKER_KEY],\n });\n const changedActionMarkers = actionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastActionMarkerTs,\n );\n recordActionChanges(\n changedActionMarkers\n .map((row) => parseActionChangeMarker(row.session_id, row.value))\n .filter((target): target is ActionChangeTarget => !!target),\n );\n _lastActionMarkerTs = actionMarkerTs;\n }\n\n // Check for screen-refresh requests from the agent. The `refresh-screen`\n // tool writes to application_state under a well-known key; when its\n // updated_at bumps, emit a distinct event so the client invalidates\n // all queries (not just the ones matching its default queryKey prefix).\n const refreshResult = await db.execute({\n sql: \"SELECT updated_at, value FROM application_state WHERE key = ?\",\n args: [SCREEN_REFRESH_KEY],\n });\n const refreshTs = timestampValue(refreshResult.rows[0]?.updated_at);\n if (!_screenRefreshInitialized) {\n _lastScreenRefreshTs = refreshTs;\n _screenRefreshInitialized = true;\n } else if (refreshTs > _lastScreenRefreshTs) {\n let scope: string | undefined;\n try {\n const raw = refreshResult.rows[0]?.value;\n if (typeof raw === \"string\") {\n const parsed = JSON.parse(raw);\n if (typeof parsed?.scope === \"string\") scope = parsed.scope;\n }\n } catch {}\n recordChange({\n source: \"screen-refresh\",\n type: \"change\",\n key: SCREEN_REFRESH_KEY,\n ...(scope ? { scope } : {}),\n });\n _lastScreenRefreshTs = refreshTs;\n }\n\n // Extension mutations write a durable marker row so delete and hide/unhide\n // operations are visible across serverless invocations. Translate those\n // marker rows back into extension-source events for targeted client\n // invalidation while preserving user/org scope.\n const extensionMarkerTs = await readExtensionMarkerMaxUpdatedAt(db);\n if (extensionMarkerTs > _lastExtensionMarkerTs) {\n const extensionMarkerResult = await db.execute({\n sql: \"SELECT session_id, value, updated_at FROM application_state WHERE key = ? ORDER BY updated_at ASC\",\n args: [EXTENSION_CHANGE_MARKER_KEY],\n });\n const changedExtensionMarkers = extensionMarkerResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionMarkerTs,\n );\n if (_lastExtensionMarkerTs > 0) {\n recordExtensionChanges(\n changedExtensionMarkers\n .map((row) => parseExtensionChangeMarker(row.session_id, row.value))\n .filter((target): target is ExtensionChangeTarget => !!target),\n );\n }\n _lastExtensionMarkerTs = extensionMarkerTs;\n }\n\n // Check settings for external writes\n const settingsTs = await readMaxUpdatedAt(db, \"settings\");\n if (settingsTs > _lastSettingsTs) {\n if (_lastSettingsTs > 0) {\n recordChange({ source: \"settings\", type: \"change\", key: \"*\" });\n }\n _lastSettingsTs = settingsTs;\n }\n\n // Extension rows live in the legacy physical `tools` table. Keep this as a\n // compatibility fallback for direct table writes, but scope events to the\n // resource owner/share targets instead of broadcasting deployment-wide.\n const extensionsMaxUpdatedAt = await readMaxUpdatedAtRaw(db, \"tools\");\n const extensionsTs = timestampValue(extensionsMaxUpdatedAt);\n if (extensionsTs > _lastExtensionsTs) {\n const since = _lastExtensionsUpdatedAt;\n const extensionResult =\n since === undefined\n ? await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools ORDER BY updated_at ASC\",\n args: [],\n })\n : await db.execute({\n sql: \"SELECT id, owner_email, org_id, visibility, updated_at FROM tools WHERE updated_at > ? ORDER BY updated_at ASC\",\n args: [since],\n });\n const changedExtensionRows = extensionResult.rows.filter(\n (row) => timestampValue(row.updated_at) > _lastExtensionsTs,\n );\n if (_lastExtensionsTs > 0) {\n const targetsByRow = await readExtensionTargetsForRows(\n db,\n changedExtensionRows,\n );\n for (const targets of targetsByRow) recordExtensionChanges(targets);\n }\n _lastExtensionsTs = extensionsTs;\n _lastExtensionsUpdatedAt = sqlWatermarkValue(extensionsMaxUpdatedAt);\n }\n } catch {\n // Tables may not exist yet — ignore\n }\n}\n\n/**\n * Create an H3 handler for the poll endpoint.\n *\n * GET /_agent-native/poll?since=N → { version, events[] }\n *\n * Requires an authenticated session. Events are filtered to the caller's\n * tenant — global events (owner-less, table-level pings) reach every\n * authenticated caller; owned events reach only the matching user/org.\n * Without auth + filtering, an anonymous attacker could poll the deployment\n * and infer cross-tenant activity from the global event stream.\n */\nexport function createPollHandler() {\n wireLocalEmitters();\n return defineEventHandler(async (event) => {\n const session = await getSession(event).catch(() => null);\n if (!session?.email) {\n setResponseStatus(event, 401);\n return { error: \"Unauthenticated\" };\n }\n // On cold start, seed _version from DB so we don't return version: 0\n await seedVersionFromDb();\n // Check for cross-process writes before responding\n await checkExternalDbChanges();\n\n const query = getQuery(event);\n const since = parseInt(String(query.since ?? \"0\"), 10) || 0;\n return getChangesSinceForUser(since, session.email, session.orgId);\n });\n}\n"]}
|
|
@@ -68,7 +68,7 @@ Controls how the action is exposed as an HTTP endpoint:
|
|
|
68
68
|
|
|
69
69
|
### Screen Refresh (automatic)
|
|
70
70
|
|
|
71
|
-
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the
|
|
71
|
+
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the framework emits a change event with `source: "action"` that the client's `useDbSync` picks up and uses to invalidate `["action"]` React Query keys — so `list-*` / `get-*` hooks refetch without a full page reload. In-process calls emit directly; dev-mode `pnpm action ...` calls also write a durable marker so the web server sees child-process action changes.
|
|
72
72
|
|
|
73
73
|
Rules:
|
|
74
74
|
|
|
@@ -68,7 +68,7 @@ Controls how the action is exposed as an HTTP endpoint:
|
|
|
68
68
|
|
|
69
69
|
### Screen Refresh (automatic)
|
|
70
70
|
|
|
71
|
-
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the
|
|
71
|
+
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the framework emits a change event with `source: "action"` that the client's `useDbSync` picks up and uses to invalidate `["action"]` React Query keys — so `list-*` / `get-*` hooks refetch without a full page reload. In-process calls emit directly; dev-mode `pnpm action ...` calls also write a durable marker so the web server sees child-process action changes.
|
|
72
72
|
|
|
73
73
|
Rules:
|
|
74
74
|
|
|
@@ -247,7 +247,7 @@ export default defineAction({
|
|
|
247
247
|
});
|
|
248
248
|
```
|
|
249
249
|
|
|
250
|
-
`GET` + `readOnly` keeps the action side-effect-free and out of the screen-refresh
|
|
250
|
+
`GET` + `readOnly` keeps the action side-effect-free and out of the screen-refresh change event. `publicAgent` is the **explicit opt-in** — a public web route never implies public MCP/A2A exposure; see [Actions](/docs/actions). Design/content ingest actions MUST read **live** state (the Yjs collaborative document, not the stale DB snapshot column) so the external agent sees what the user actually has on screen. Content's `pull-document` flushes any open live collab session to SQL first; design's `get-design-snapshot` returns the live Yjs file contents plus the user's resolved tweak values.
|
|
251
251
|
|
|
252
252
|
## Advanced: local development & manual setup {#advanced}
|
|
253
253
|
|
|
@@ -53,7 +53,7 @@ It also explains why agent-native can support so many protocols without making e
|
|
|
53
53
|
|
|
54
54
|
## Why every agent needs a UI {#why-every-agent-needs-a-ui}
|
|
55
55
|
|
|
56
|
-
The hot take in 2026 is "apps are dead, agents will replace UIs, everyone will just text an agent in Telegram."
|
|
56
|
+
The hot take in 2026 is "apps are dead, agents will replace UIs, everyone will just text an agent in Telegram." Eh.
|
|
57
57
|
|
|
58
58
|
Even when the agent does all the heavy lifting, humans still need to:
|
|
59
59
|
|
package/package.json
CHANGED
|
@@ -68,7 +68,7 @@ Controls how the action is exposed as an HTTP endpoint:
|
|
|
68
68
|
|
|
69
69
|
### Screen Refresh (automatic)
|
|
70
70
|
|
|
71
|
-
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the
|
|
71
|
+
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the framework emits a change event with `source: "action"` that the client's `useDbSync` picks up and uses to invalidate `["action"]` React Query keys — so `list-*` / `get-*` hooks refetch without a full page reload. In-process calls emit directly; dev-mode `pnpm action ...` calls also write a durable marker so the web server sees child-process action changes.
|
|
72
72
|
|
|
73
73
|
Rules:
|
|
74
74
|
|
|
@@ -68,7 +68,7 @@ Controls how the action is exposed as an HTTP endpoint:
|
|
|
68
68
|
|
|
69
69
|
### Screen Refresh (automatic)
|
|
70
70
|
|
|
71
|
-
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the
|
|
71
|
+
The framework auto-refreshes the UI after any successful mutating action. On completion of a non-`GET` action, the framework emits a change event with `source: "action"` that the client's `useDbSync` picks up and uses to invalidate `["action"]` React Query keys — so `list-*` / `get-*` hooks refetch without a full page reload. In-process calls emit directly; dev-mode `pnpm action ...` calls also write a durable marker so the web server sees child-process action changes.
|
|
72
72
|
|
|
73
73
|
Rules:
|
|
74
74
|
|