@agent-native/core 0.149.6 → 0.151.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.
Files changed (173) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  3. package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +83 -45
  4. package/corpus/templates/analytics/changelog/2026-08-11-analytics-dashboards-keep-the-selected-tab-when-reopened.md +6 -0
  5. package/corpus/templates/assets/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  6. package/corpus/templates/brain/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  7. package/corpus/templates/calendar/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  8. package/corpus/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  9. package/corpus/templates/clips/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  10. package/corpus/templates/clips/changelog/2026-08-11-clips-recovers-from-transient-updates-and-avoids-macos-priva.md +6 -0
  11. package/corpus/templates/clips/desktop/src/app.tsx +32 -176
  12. package/corpus/templates/clips/desktop/src/lib/updater.ts +52 -37
  13. package/corpus/templates/clips/desktop/src/styles.css +1 -166
  14. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +2 -0
  15. package/corpus/templates/clips/desktop/src-tauri/Info.plist +4 -0
  16. package/corpus/templates/clips/desktop/src-tauri/src/eventkit.rs +28 -1
  17. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +2 -0
  18. package/corpus/templates/clips/desktop/src-tauri/src/native_speech.rs +48 -1
  19. package/corpus/templates/clips/desktop/src-tauri/src/permission_status.rs +3 -0
  20. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +5 -0
  21. package/corpus/templates/clips/server/plugins/auth.ts +3 -0
  22. package/corpus/templates/content/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  23. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +2 -1
  24. package/corpus/templates/design/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  25. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -1
  26. package/corpus/templates/design/changelog/2026-08-11-design-agent-prompts-copy-successfully-in-the-desktop-app.md +6 -0
  27. package/corpus/templates/dispatch/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  28. package/corpus/templates/dispatch/app/global.css +2 -2
  29. package/corpus/templates/dispatch/changelog/2026-08-10-desktop-workspace-sign-in.md +6 -0
  30. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-shows-the-generic-chat-starter-among-defa.md +6 -0
  31. package/corpus/templates/dispatch/changelog/2026-08-11-integrations-and-scheduled-work-open-as-first-class-electron-pages.md +6 -0
  32. package/corpus/templates/dispatch/changelog/2026-08-11-sidebar-text-is-slightly-easier-to-read-in-light-and-dark-mo.md +6 -0
  33. package/corpus/templates/dispatch/server/lib/identity-sso.ts +57 -31
  34. package/corpus/templates/dispatch/server/plugins/feature-flags.ts +5 -0
  35. package/corpus/templates/dispatch/server/plugins/identity-sso.ts +82 -33
  36. package/corpus/templates/dispatch/server/plugins/org-apps-directory.ts +7 -15
  37. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +9 -1
  38. package/corpus/templates/dispatch/shared/feature-flags.ts +15 -0
  39. package/corpus/templates/factory/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  40. package/corpus/templates/forms/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  41. package/corpus/templates/forms/.agents/skills/form-responses/SKILL.md +8 -7
  42. package/corpus/templates/forms/app/hooks/use-forms.ts +8 -1
  43. package/corpus/templates/forms/changelog/2026-08-11-fixed-public-forms-so-conditional-questions-stay-hidden-unti.md +6 -0
  44. package/corpus/templates/forms/server/handlers/submissions.ts +2 -1
  45. package/corpus/templates/forms/server/lib/public-form-ssr.ts +37 -2
  46. package/corpus/templates/forms/shared/page-url.ts +54 -0
  47. package/corpus/templates/forms/shared/types.ts +4 -4
  48. package/corpus/templates/mail/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  49. package/corpus/templates/plan/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  50. package/corpus/templates/slides/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  51. package/corpus/templates/slides/actions/add-slide.ts +0 -27
  52. package/corpus/templates/slides/actions/import-file.ts +28 -9
  53. package/corpus/templates/slides/actions/view-screen.ts +4 -4
  54. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +8 -1
  55. package/corpus/templates/slides/app/components/editor/AiEditingMarker.tsx +25 -0
  56. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +43 -48
  57. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +9 -6
  58. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -9
  59. package/corpus/templates/slides/app/components/editor/ImageDropPromptPopover.tsx +2 -0
  60. package/corpus/templates/slides/app/components/editor/ImageOverlay.tsx +0 -26
  61. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +904 -217
  62. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  63. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +11 -0
  64. package/corpus/templates/slides/app/components/editor/inline-edit-session.ts +16 -0
  65. package/corpus/templates/slides/app/components/editor/slide-object-interactions.ts +22 -6
  66. package/corpus/templates/slides/app/components/editor/style-clipboard.ts +61 -0
  67. package/corpus/templates/slides/app/components/layout/Layout.tsx +26 -2
  68. package/corpus/templates/slides/app/components/ui/context-menu.tsx +1 -0
  69. package/corpus/templates/slides/app/context/DeckContext.tsx +75 -25
  70. package/corpus/templates/slides/app/global.css +1 -1
  71. package/corpus/templates/slides/app/i18n/en-US.ts +6 -1
  72. package/corpus/templates/slides/app/lib/create-deck-generation.ts +1 -1
  73. package/corpus/templates/slides/app/lib/image-drop-to-agent.ts +12 -12
  74. package/corpus/templates/slides/app/lib/slide-agent-context.ts +52 -0
  75. package/corpus/templates/slides/app/lib/slide-image-replacement.ts +61 -0
  76. package/corpus/templates/slides/app/pages/DeckEditor.tsx +55 -116
  77. package/corpus/templates/slides/app/pages/Index.tsx +28 -3
  78. package/corpus/templates/slides/changelog/2026-08-11-agent-chat-now-follows-the-current-slide-and-selection.md +6 -0
  79. package/corpus/templates/slides/changelog/2026-08-11-deck-titles-now-use-slide-content-instead-of-placeholder-filenames.md +6 -0
  80. package/corpus/templates/slides/changelog/2026-08-11-history-now-opens-from-the-deck-overflow-menu.md +6 -0
  81. package/corpus/templates/slides/changelog/2026-08-11-images-can-be-dropped-directly-onto-slides-and-resized-or-re.md +6 -0
  82. package/corpus/templates/slides/changelog/2026-08-11-new-decks-now-transition-directly-to-a-full-page-editor-load.md +6 -0
  83. package/corpus/templates/slides/changelog/2026-08-11-selected-slide-layers-can-be-nudged-precisely-with-arrow-key.md +6 -0
  84. package/corpus/templates/slides/changelog/2026-08-11-slides-can-copy-and-paste-element-styles-with-cmd-option-c-v.md +6 -0
  85. package/corpus/templates/slides/changelog/2026-08-11-slides-shows-one-compact-ai-marker-and-keeps-your-current-sl.md +6 -0
  86. package/corpus/templates/slides/changelog/2026-08-11-text-edits-preserve-slide-layout-when-no-changes-are-made.md +6 -0
  87. package/corpus/templates/slides/changelog/2026-08-11-the-style-toolbar-now-uses-the-full-available-width.md +6 -0
  88. package/corpus/templates/slides/changelog/2026-08-11-undo-and-redo-now-move-one-visible-slide-state-at-a-time.md +6 -0
  89. package/corpus/templates/slides/server/lib/chat-attachments.ts +6 -2
  90. package/corpus/templates/slides/shared/deck-title.ts +56 -0
  91. package/corpus/templates/tasks/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  92. package/dist/agent/run-store.js +6 -1
  93. package/dist/agent/thread-data-builder.js +19 -44
  94. package/dist/agent/types.d.ts +13 -0
  95. package/dist/catalog.json +1 -0
  96. package/dist/cli/create.js +1 -1
  97. package/dist/client/AssistantChat.js +58 -10
  98. package/dist/client/FileStorageSetupCard.d.ts +6 -0
  99. package/dist/client/FileStorageSetupCard.js +18 -0
  100. package/dist/client/NewWorkspaceAppFlow.js +10 -0
  101. package/dist/client/agent-chat-adapter.js +87 -11
  102. package/dist/client/agent-chat.d.ts +1 -1
  103. package/dist/client/agent-chat.js +8 -3
  104. package/dist/client/chat/attachment-adapters.js +10 -0
  105. package/dist/client/chat/message-components.d.ts +4 -1
  106. package/dist/client/chat/message-components.js +37 -13
  107. package/dist/client/chat/tool-call-display.js +14 -0
  108. package/dist/client/chat-first/apps-rail.d.ts +1 -1
  109. package/dist/client/chat-first/apps-rail.js +6 -6
  110. package/dist/client/chat-first/copy.js +1 -0
  111. package/dist/client/chat-first/types.d.ts +1 -0
  112. package/dist/client/extensions/EmbeddedExtension.js +1 -1
  113. package/dist/client/extensions/ExtensionViewer.js +1 -1
  114. package/dist/client/extensions/InlineExtensionFrame.js +1 -1
  115. package/dist/client/onboarding/FirstRunOnboarding.js +17 -2
  116. package/dist/client/settings/FileStorageSettingsForm.d.ts +2 -0
  117. package/dist/client/settings/FileStorageSettingsForm.js +113 -0
  118. package/dist/client/settings/SettingsPanel.js +2 -1
  119. package/dist/client/sse-event-processor.js +21 -0
  120. package/dist/collab/struct-routes.d.ts +1 -1
  121. package/dist/extensions/actions.js +2 -2
  122. package/dist/extensions/html-shell.js +3 -1
  123. package/dist/file-upload/pre-upload-attachments.d.ts +15 -10
  124. package/dist/file-upload/pre-upload-attachments.js +68 -24
  125. package/dist/file-upload/registry.d.ts +4 -5
  126. package/dist/file-upload/registry.js +7 -14
  127. package/dist/file-upload/s3.d.ts +9 -0
  128. package/dist/file-upload/s3.js +168 -0
  129. package/dist/file-upload/types.d.ts +3 -3
  130. package/dist/file-upload/types.js +2 -2
  131. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  132. package/dist/notifications/routes.d.ts +3 -3
  133. package/dist/onboarding/app-profile.js +23 -1
  134. package/dist/onboarding/default-steps.js +69 -0
  135. package/dist/onboarding/types.d.ts +2 -0
  136. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  137. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  138. package/dist/secrets/routes.d.ts +3 -3
  139. package/dist/server/agent-chat/browser-team-tools.js +20 -0
  140. package/dist/server/agent-chat-plugin.js +12 -3
  141. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  142. package/dist/server/auth.js +45 -21
  143. package/dist/server/better-auth-instance.d.ts +2 -0
  144. package/dist/server/better-auth-instance.js +2 -2
  145. package/dist/server/core-routes-plugin.d.ts +1 -0
  146. package/dist/server/core-routes-plugin.js +26 -16
  147. package/dist/server/identity-sso-store.d.ts +3 -0
  148. package/dist/server/identity-sso-store.js +45 -0
  149. package/dist/server/identity-sso.d.ts +20 -10
  150. package/dist/server/identity-sso.js +79 -31
  151. package/dist/server/index.d.ts +1 -1
  152. package/dist/server/index.js +1 -1
  153. package/dist/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  154. package/dist/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  155. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  156. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  157. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  158. package/dist/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  159. package/dist/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
  160. package/docs/content/authentication.mdx +27 -0
  161. package/docs/content/cross-app-sso.mdx +38 -8
  162. package/docs/content/extensions.mdx +15 -15
  163. package/docs/content/file-uploads.mdx +10 -12
  164. package/docs/content/generative-ui.mdx +6 -1
  165. package/docs/content/key-concepts.mdx +141 -83
  166. package/package.json +2 -2
  167. package/src/templates/chat/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  168. package/src/templates/default/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  169. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +24 -1
  170. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +28 -0
  171. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +6 -2
  172. package/src/templates/workspace-core/.agents/skills/extensions/references/api.md +1 -1
  173. package/src/templates/workspace-core/.agents/skills/generative-ui/SKILL.md +3 -1
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -168,10 +168,33 @@ Set `A2A_SECRET` (same value) on all apps that must verify each other's identity
168
168
  Each hosted `*.agent-native.com` app has its **own user store**, so "sign in once" is identity federation, not a shared cookie. **Dispatch is the identity authority.**
169
169
 
170
170
  - **Opt-in per app via one env var:** set `AGENT_NATIVE_IDENTITY_HUB_URL=https://dispatch.agent-native.com` and the app shows a "Sign in with Agent-Native" option. **Unset = zero behavior change** — the whole path is dormant. Reversible at any time.
171
- - **Flow:** app → `GET <hub>/_agent-native/identity/authorize?app=&redirect_uri=&state=` → user logs in at Dispatch → 302 back with a short-lived (`≤5min`) `A2A_SECRET`-signed identity JWT (`sub`/`email`/`name`/`org_domain`/`scope:"identity"`). Strict `redirect_uri` allowlist (`*.agent-native.com` + localhost). App verifies the token, **JIT-links strictly by verified email** (existing same-email user → reused unchanged; new email → created), then mints a normal local session.
171
+ - **Flow:** app → `GET <hub>/_agent-native/identity/authorize?app=&redirect_uri=&state=` → user logs in at Dispatch → 302 back with a short-lived (`≤5min`) `A2A_SECRET`-signed identity JWT (`sub`/`email`/`name`/`org_domain`/`scope:"identity"`). Canonical clients require an exact registered app ID, origin, and callback path; localhost remains available for development. App verifies the token, **JIT-links strictly by verified email** (existing same-email user → reused unchanged; new email → created), then mints a normal local session.
172
172
  - **Invariant (do not break):** identity rows are only ever **added** — never modified, renamed, or deleted. Enabling SSO logs users out, but they always log back into the **same email-matched account with data intact**. Email is the only thing that crosses the trust boundary; the app never trusts a user id, role, or org from the wire.
173
173
  - **Canary rollout:** deploy with the env unset everywhere (no-op) → set it on **one** app (mail) only → verify (logout → SSO → Dispatch → back to the same pre-existing account, data intact, direct logins still work) → expand app-by-app → rollback = unset the env on that app's deploy (instant, no data change).
174
174
 
175
+ ### Packaged Desktop workspace sign-in
176
+
177
+ For canonical first-party hosted apps, the packaged Desktop SSO Canary may compose the same
178
+ federation into one workspace sign-in. Dispatch owns the default-off
179
+ `desktop.workspace-sso` availability flag; every app still owns its local
180
+ session. The flag is never an auth or authorization boundary. Keep nonce,
181
+ signature, exact origin/callback, authenticated-session, app-binding, cookie
182
+ allowlist, revocation, and credential-custody checks unconditional. When the
183
+ flag is Off or unreadable, Desktop must leave ordinary per-app sign-in, sign-out,
184
+ and Settings unchanged. Never extend the broker to custom or third-party apps,
185
+ and never expose cookies, identity tokens, or provider credentials through IPC.
186
+ Canonical hosted apps recognize packaged Desktop requests without per-app
187
+ identity-hub environment configuration. Ordinary browsers and self-hosted apps
188
+ still require `AGENT_NATIVE_IDENTITY_HUB_URL`.
189
+ Stable Desktop builds must not initialize the broker until a later release is
190
+ separately approved.
191
+ Treat the Canary user-agent marker only as an availability hint, never as
192
+ remote attestation or an authentication boundary. Bind supervised acceptance
193
+ to exact signed-artifact provenance.
194
+ The Canary must not intercept anonymous app sign-in navigation. The user
195
+ explicitly chooses workspace sign-in in Desktop Settings for the active
196
+ registered app; ordinary app sign-in remains the default path.
197
+
175
198
  Full runbook + flow detail: [Cross-App SSO doc](/docs/cross-app-sso).
176
199
 
177
200
  ## Builder Browser Access
@@ -49,6 +49,34 @@ sendToAgentChat({
49
49
  });
50
50
  ```
51
51
 
52
+ ### Keep user text separate from injected context
53
+
54
+ Treat the visible `message` as the user's request or the shortest clear
55
+ description of an app-initiated operation. Put context the user did not type —
56
+ IDs, URLs, filenames, current selection or screen state, serialized records,
57
+ upload instructions, and bounded source excerpts — in the `context` field.
58
+ `context` is model input carried through the agent turn; it is stripped from
59
+ the rendered user message, so do not concatenate it into `message` with labels,
60
+ blank-line sections, or `<context>` tags yourself.
61
+
62
+ Use the related surface for each kind of supporting input:
63
+
64
+ | Surface | Use for |
65
+ | --- | --- |
66
+ | `message` | User-authored intent or a concise app action description |
67
+ | `context` | Derived metadata and bounded text needed to carry out that intent |
68
+ | `setAgentChatContextItem` | Context staged for a later user-submitted prompt; keep it keyed so updates replace stale context |
69
+ | `images`, `referenceImagePaths`, attachments | Binary or visual inputs; describe only the handling instructions in `context` |
70
+
71
+ If an app builds a prompt from a form, selection, upload, or editor state, keep
72
+ the visible message short and pass the assembled details as `context`. Preserve
73
+ the user's actual freeform text in `message` when it is the request; do not
74
+ restate it as metadata in `context` unless the agent needs a structured copy.
75
+
76
+ This boundary applies to auto-submitted turns and prefills. A hidden context
77
+ field is not a license to send unbounded records or secrets: cap excerpts,
78
+ prefer stable IDs and URLs, and use an action or resource lookup for full data.
79
+
52
80
  **From the UI, in the background:**
53
81
 
54
82
  ```ts
@@ -129,8 +129,12 @@ Extensions have full access to app data via helpers injected into the iframe
129
129
  in chat, record passive control/selection output at
130
130
  `inline-ui:<extensionId>:output` in application state so the agent can read it
131
131
  later with `readAppState`.
132
- - `agentNative.chat.send(message, opts?)` — send a visible prompt or selected
133
- value back into the current agent chat.
132
+ - `agentNative.chat.send(message, opts?)` - send a visible prompt or selected
133
+ value back into the current agent chat. The extension bridge keeps messages
134
+ draft-only unless `opts.submit === true`; pass `{ submit: true }` only from a
135
+ user-triggered Apply or Submit action. Never call it from polling, refresh, or
136
+ error handlers; use application state or `agentNative.ui.output` for passive
137
+ results.
134
138
 
135
139
  For transient inline generative UI, `extensionData` is host-browser
136
140
  `localStorage`: the agent cannot read it, it does not sync across devices, it
@@ -137,7 +137,7 @@ await dbExec("UPDATE notes SET title = 'Updated Title' WHERE id = 'abc'");
137
137
  | `extensionData.get(collection, id, opts?)` | Get a single item by id | `extensionData.get('todos', 'todo-1')` |
138
138
  | `extensionData.remove(collection, id, opts?)` | Delete an item | `extensionData.remove('todos', 'todo-1')` |
139
139
  | `agentNative.ui.output(value, opts?)` | Record passive inline UI output in application state | `agentNative.ui.output({ threshold })` |
140
- | `agentNative.chat.send(message, opts?)` | Send a visible prompt or selected value back to chat | `agentNative.chat.send('Use Q2', { context: { q: 2 } })` |
140
+ | `agentNative.chat.send(message, opts?)` | Send a visible prompt or selected value back to chat | `agentNative.chat.send('Use Q2', { submit: true, context: { q: 2 } })` |
141
141
 
142
142
  ## Persisting Custom Data
143
143
 
@@ -76,7 +76,9 @@ The stored payload includes `value`, `updatedAt`, `extensionId`, and
76
76
 
77
77
  Use `agentNative.chat.send(message, opts?)` or `sendToAgentChat(message, opts?)`
78
78
  for a visible Apply/Submit button that should send a prompt or selected value
79
- into the chat.
79
+ into the chat. Pass `{ submit: true }` explicitly for that user-triggered
80
+ action; extension messages are draft-only otherwise. Never call these helpers
81
+ from polling, refresh, or error handlers.
80
82
 
81
83
  ## App Data And State
82
84