@agent-native/core 0.72.4 → 0.74.0
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/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +67 -0
- package/corpus/core/docs/content/skills-guide.md +14 -0
- package/corpus/core/docs/content/template-clips.md +7 -1
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/durable-background.ts +35 -12
- package/corpus/core/src/agent/production-agent.ts +55 -8
- package/corpus/core/src/cli/create.ts +1 -1
- package/corpus/core/src/cli/skills.ts +450 -19
- package/corpus/core/src/client/ConnectBuilderCard.tsx +7 -7
- package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +1 -1
- package/corpus/core/src/client/blocks/library/AnnotatedCodeBlock.tsx +33 -18
- package/corpus/core/src/client/blocks/library/annotation-rail.tsx +3 -4
- package/corpus/core/src/client/components/CodeRequiredDialog.tsx +5 -8
- package/corpus/core/src/server/agent-chat-plugin.ts +7 -7
- package/corpus/core/src/server/auth.ts +7 -0
- package/corpus/core/src/server/onboarding-html.ts +95 -9
- package/corpus/core/src/server/self-dispatch.ts +8 -1
- package/corpus/core/src/templates/default/AGENTS.md +4 -0
- package/corpus/core/src/templates/default/package.json +2 -1
- package/corpus/core/src/templates/headless/AGENTS.md +4 -0
- package/corpus/core/src/templates/headless/package.json +1 -0
- package/corpus/core/src/templates/workspace-root/AGENTS.md +4 -0
- package/corpus/core/src/templates/workspace-root/README.md +4 -0
- package/corpus/core/src/templates/workspace-root/package.json +1 -0
- package/corpus/templates/analytics/actions/compose-dashboard.ts +34 -0
- package/corpus/templates/analytics/actions/install-dashboard-template.ts +51 -3
- package/corpus/templates/analytics/actions/update-dashboard.ts +3 -4
- package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +175 -48
- package/corpus/templates/analytics/app/global.css +15 -13
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +9 -32
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +0 -26
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +0 -23
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +65 -2
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +3 -4
- package/corpus/templates/analytics/changelog/2026-06-24-dashboard-charts-now-fill-sparse-template-time-series-suppor.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-dashboard-filters-now-apply-consistently-to-first-party-traf.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-dashboard-rows-now-auto-fit-panels-so-one-two-or-three-chart.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-dashboard-traffic-tables-now-show-top-urls-and-shared-clips-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-first-party-signup-and-pageview-panels-now-honor-dashboard-filters.md +5 -0
- package/corpus/templates/analytics/changelog/2026-06-24-first-party-template-dashboards-now-include-repeat-users-ret.md +6 -0
- package/corpus/templates/analytics/changelog/2026-06-24-retention-charts-now-break-out-1-day-and-7-day-return-rates-.md +6 -0
- package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +330 -49
- package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +7 -2
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +35 -8
- package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +337 -45
- package/corpus/templates/calendar/changelog/2026-06-23-added-a-heads-up-explaining-google-s-app-not-verified-screen.md +1 -1
- package/corpus/templates/calendar/server/plugins/auth.ts +12 -0
- package/corpus/templates/clips/.agents/skills/recording/SKILL.md +7 -7
- package/corpus/templates/clips/AGENTS.md +6 -2
- package/corpus/templates/clips/app/components/capture-install-options.tsx +20 -4
- package/corpus/templates/clips/app/components/library/library-layout.tsx +7 -0
- package/corpus/templates/clips/app/components/player/player-controls.tsx +62 -32
- package/corpus/templates/clips/app/lib/capture-install-options.ts +39 -5
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +786 -323
- package/corpus/templates/clips/app/routes/download.tsx +2 -2
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +1 -1
- package/corpus/templates/clips/changelog/2026-06-24-inline-slack-playback-controls-no-longer-shift-when-adjustin.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-settings-now-puts-what-s-new-in-a-compact-sidebar-prioritize.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-shared-clips-now-expose-their-full-console-log-stream-all-le.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-shared-clips-now-expose-their-full-fetch-xhr-network-request.md +6 -0
- package/corpus/templates/clips/changelog/2026-06-24-the-chrome-extension-option-now-only-appears-on-supported-hosts.md +5 -0
- package/corpus/templates/clips/chrome-extension/STORE_DRAFT.md +13 -8
- package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
- package/corpus/templates/clips/chrome-extension/scripts/package.ts +15 -2
- package/corpus/templates/clips/chrome-extension/src/overlay.css +4 -25
- package/corpus/templates/clips/chrome-extension/src/overlay.ts +1 -3
- package/corpus/templates/clips/server/lib/public-agent-context.ts +67 -24
- package/corpus/templates/mail/server/plugins/auth.ts +4 -1
- package/corpus/templates/plan/app/pages/PlansPage.tsx +271 -197
- package/corpus/templates/plan/changelog/2026-06-24-annotated-code-callouts-now-use-numbered-gutter-markers-that.md +6 -0
- package/corpus/templates/plan/server/plan-content.ts +45 -2
- package/dist/agent/durable-background.d.ts +9 -4
- package/dist/agent/durable-background.d.ts.map +1 -1
- package/dist/agent/durable-background.js +34 -11
- package/dist/agent/durable-background.js.map +1 -1
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +52 -8
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/cli/create.js +1 -1
- package/dist/cli/create.js.map +1 -1
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +361 -19
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
- package/dist/client/ConnectBuilderCard.js +6 -6
- package/dist/client/ConnectBuilderCard.js.map +1 -1
- package/dist/client/NewWorkspaceAppFlow.js +1 -1
- package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +14 -10
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +3 -4
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +3 -4
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
- package/dist/client/components/CodeRequiredDialog.js +2 -1
- package/dist/client/components/CodeRequiredDialog.js.map +1 -1
- package/dist/server/agent-chat-plugin.js +7 -7
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/auth.d.ts +7 -0
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +1 -0
- package/dist/server/auth.js.map +1 -1
- package/dist/server/onboarding-html.d.ts +15 -0
- package/dist/server/onboarding-html.d.ts.map +1 -1
- package/dist/server/onboarding-html.js +73 -9
- package/dist/server/onboarding-html.js.map +1 -1
- package/dist/server/self-dispatch.d.ts.map +1 -1
- package/dist/server/self-dispatch.js +5 -1
- package/dist/server/self-dispatch.js.map +1 -1
- package/dist/templates/default/AGENTS.md +4 -0
- package/dist/templates/default/package.json +2 -1
- package/dist/templates/headless/AGENTS.md +4 -0
- package/dist/templates/headless/package.json +1 -0
- package/dist/templates/workspace-root/AGENTS.md +4 -0
- package/dist/templates/workspace-root/README.md +4 -0
- package/dist/templates/workspace-root/package.json +1 -0
- package/docs/content/skills-guide.md +14 -0
- package/docs/content/template-clips.md +7 -1
- package/package.json +1 -1
- package/src/templates/default/AGENTS.md +4 -0
- package/src/templates/default/package.json +2 -1
- package/src/templates/headless/AGENTS.md +4 -0
- package/src/templates/headless/package.json +1 -0
- package/src/templates/workspace-root/AGENTS.md +4 -0
- package/src/templates/workspace-root/README.md +4 -0
- package/src/templates/workspace-root/package.json +1 -0
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.74.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 4a0d3c4: Durable background agent runs are robust again, and **on by default** for hosted apps.
|
|
8
|
+
- **Graceful inline fallback (the safety fix).** When the foreground turn can't
|
|
9
|
+
hand off to a background worker — the HMAC self-dispatch self-POST fails fast,
|
|
10
|
+
e.g. a connection error or a non-2xx returned within the settle window — the
|
|
11
|
+
agent-chat handler no longer breaks the chat with
|
|
12
|
+
`Failed to dispatch background run`. It now degrades to a normal synchronous
|
|
13
|
+
(inline) run, reusing the already-inserted run row. The run is claimed
|
|
14
|
+
atomically (`claimBackgroundRun`, a conditional `dispatch_mode: background →
|
|
15
|
+
background-processing` UPDATE) before running inline, so the SQL atomic claim
|
|
16
|
+
is the single owner — a delayed background delivery that arrives afterward
|
|
17
|
+
loses the claim and no-ops, and the run can never double-execute. A dispatch
|
|
18
|
+
that _did_ land (so a worker already owns the run) still streams the worker's
|
|
19
|
+
events instead of running a second copy.
|
|
20
|
+
- **Default-on, safely.** `AGENT_CHAT_DURABLE_BACKGROUND` is now opt-out for
|
|
21
|
+
hosted apps: unset/empty/unknown counts as enabled; opt a specific app back
|
|
22
|
+
out with an explicit falsy value (`false`/`0`/`no`/`off`). The gate still
|
|
23
|
+
composes with the existing guards, so a run only goes durable when the runtime
|
|
24
|
+
is hosted/serverless **and** `A2A_SECRET` is configured — local dev and
|
|
25
|
+
unconfigured apps stay on the synchronous inline path unchanged. Default-on is
|
|
26
|
+
safe precisely because a failed dispatch degrades to a working inline run. The
|
|
27
|
+
Netlify 15-min `-background` function emit (`isDurableBackgroundDeployEnabled`)
|
|
28
|
+
remains opt-in until its path is separately verified; with it off, the
|
|
29
|
+
default-on baseline runs the worker through the standard function and
|
|
30
|
+
server-chains continuations.
|
|
31
|
+
- **More diagnosable dispatch errors.** Self-dispatch failures now log the
|
|
32
|
+
resolved base URL so a failure tied to which host the self-POST targets
|
|
33
|
+
(custom domain vs deploy URL) is visible in logs. The URL resolution order is
|
|
34
|
+
unchanged (it matches the working A2A/agent-teams self-dispatch paths).
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- 4a0d3c4: Show numbered annotation markers in the annotated-code gutter, matching the diff
|
|
39
|
+
annotation affordance while preserving the hover popover behavior.
|
|
40
|
+
- 4a0d3c4: Clarify Builder code-change handoff fallbacks when cloud agents are unavailable.
|
|
41
|
+
|
|
42
|
+
## 0.73.0
|
|
43
|
+
|
|
44
|
+
### Minor Changes
|
|
45
|
+
|
|
46
|
+
- d684bbf: Durable background agent runs are now **on by default** for hosted apps. Previously the `AGENT_CHAT_DURABLE_BACKGROUND` flag was opt-in (off unless set truthy); it is now opt-out — unset means enabled, and an app disables it with an explicit falsy value (`AGENT_CHAT_DURABLE_BACKGROUND=false`).
|
|
47
|
+
|
|
48
|
+
The gate still composes with the existing guards, so a run only goes durable when the runtime is hosted/serverless **and** `A2A_SECRET` is configured — local dev and unconfigured apps stay on the synchronous inline path unchanged. Default-on uses the server-driven agnostic continuation path (verified in prod: long multi-step runs complete past the 40s soft-timeout with no thrash and no int4 overflow). The Netlify 15-min `-background` function emit (`isDurableBackgroundDeployEnabled`) remains opt-in until its path is separately verified.
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- d684bbf: Clarify the Clips "agent-readable clips" docs so the "see and hear" promise is
|
|
53
|
+
accurate: frame-viewing works in any image-capable agent (ChatGPT, Claude Code,
|
|
54
|
+
Cursor, Codex, MCP-connected agents), while text-only web chats fall back to the
|
|
55
|
+
transcript and can take an uploaded frame. Verified empirically — ChatGPT fetches
|
|
56
|
+
the JPEG frame URLs and describes the screen; claude.ai's web chat reads the
|
|
57
|
+
transcript only. Docs-only copy change; the agent-context/frame APIs are
|
|
58
|
+
unchanged.
|
|
59
|
+
- d684bbf: Add scaffold skill refresh commands for generated Agent Native apps and workspaces, plus public `@agent-native/skills` status/update forwarding.
|
|
60
|
+
- d684bbf: Redesign the Google sign-in preflight notice on the onboarding/sign-in screen
|
|
61
|
+
to match the in-app connect popover: an amber warning-icon chip beside a bold
|
|
62
|
+
heading and muted body copy, with the close affordance moved to the top-right.
|
|
63
|
+
The `googleSignInNotice.body` already accepts a string array, so reassurance
|
|
64
|
+
like "It's safe to continue." now renders on its own line. The Continue /
|
|
65
|
+
Run-locally action buttons no longer wrap their labels (`white-space: nowrap`).
|
|
66
|
+
Purely presentational — the host-gating, Continue, and Run-locally behaviors are
|
|
67
|
+
unchanged.
|
|
68
|
+
- d684bbf: Add a secondary hosted-app signup notice linking to the Agent-Native Terms and Privacy Policy.
|
|
69
|
+
|
|
3
70
|
## 0.72.4
|
|
4
71
|
|
|
5
72
|
### Patch Changes
|
|
@@ -264,3 +264,17 @@ npx @agent-native/core@latest skills update visual-plan
|
|
|
264
264
|
the copied folder hash to the latest bundled skill, and rewrites stale folders in
|
|
265
265
|
place. Newly copied Agent Native skills include an `agent-native-skill.json`
|
|
266
266
|
marker so future status output can identify the source and hash.
|
|
267
|
+
|
|
268
|
+
Generated Agent Native apps and workspaces also include framework-provided
|
|
269
|
+
skills under `.agents/skills` (or `packages/shared/.agents/skills` in a
|
|
270
|
+
workspace). Refresh those scaffolded skills from the current/latest CLI with:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npm run skills:update
|
|
274
|
+
# or, without relying on the local package script:
|
|
275
|
+
npx @agent-native/core@latest skills update scaffold --project
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`AGENTS.md` and `.agents/skills` stay canonical. The update command also repairs
|
|
279
|
+
Claude compatibility links (`CLAUDE.md` and `.claude/skills`) so Claude Code sees
|
|
280
|
+
the same instructions without maintaining a second copy.
|
|
@@ -15,7 +15,7 @@ A capture-everything app: screen recordings, meeting notes from your calendar, a
|
|
|
15
15
|
}
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Think along the lines of Loom + Granola + Wispr Flow rolled into one app — but the agent is a first-class editor across every surface, and the recordings, meetings, and dictations are yours, not a SaaS vendor's. Clips also makes shared recordings agent-readable: paste a normal Clips share link into an agent
|
|
18
|
+
Think along the lines of Loom + Granola + Wispr Flow rolled into one app — but the agent is a first-class editor across every surface, and the recordings, meetings, and dictations are yours, not a SaaS vendor's. Clips also makes shared recordings agent-readable: paste a normal Clips share link into an agent and it can "hear" the transcript as text and "see" timestamped screen frames as images — no raw video needed. Frame-viewing works in any image-capable agent (ChatGPT, Claude Code, Cursor, Codex); text-only web chats still get the full transcript and can take a frame you upload.
|
|
19
19
|
|
|
20
20
|
```an-diagram title="Capture, transcribe, reuse" summary="Three capture types land in one library; the agent transcribes, titles, and summarizes, then every transcript is searchable and shareable."
|
|
21
21
|
{
|
|
@@ -69,6 +69,12 @@ a compact agent context URL, and that context points to the transcript and frame
|
|
|
69
69
|
APIs, so models that only accept text or still images can still understand what
|
|
70
70
|
happened in the recording.
|
|
71
71
|
|
|
72
|
+
Any agent that can fetch an image URL into its vision — ChatGPT, Claude Code,
|
|
73
|
+
Cursor, Codex, and MCP-connected agents — reads the transcript and sees the
|
|
74
|
+
frames. A few text-only web chats read the transcript but won't pull frame images
|
|
75
|
+
in on their own; there, upload a key frame or open the clip in an image-capable
|
|
76
|
+
agent.
|
|
77
|
+
|
|
72
78
|
| Endpoint | What agents get |
|
|
73
79
|
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
74
80
|
| `/api/agent-context.json?id=<recordingId>` | Clip metadata, transcript status, chapters, CTAs, recommended frames, and links to the transcript/frame APIs |
|
package/corpus/core/package.json
CHANGED
|
@@ -17,12 +17,22 @@
|
|
|
17
17
|
*
|
|
18
18
|
* GUARDRAIL: when `isAgentChatDurableBackgroundEnabled()` returns false, the
|
|
19
19
|
* agent-chat handler must behave byte-for-byte like the current synchronous
|
|
20
|
-
* path. The
|
|
21
|
-
* 1. `AGENT_CHAT_DURABLE_BACKGROUND` env is
|
|
20
|
+
* path. The gate is true only when ALL of these hold:
|
|
21
|
+
* 1. `AGENT_CHAT_DURABLE_BACKGROUND` env is not explicitly disabled. It is
|
|
22
|
+
* DEFAULT-ON: unset/empty/unknown counts as enabled; set it to a falsy
|
|
23
|
+
* value (`false`/`0`/`no`/`off`) to opt a specific app back out.
|
|
22
24
|
* 2. The runtime is hosted/serverless (local dev keeps the inline path so SSE
|
|
23
25
|
* stays a single live stream and no second function is needed).
|
|
24
26
|
* 3. `A2A_SECRET` is configured (the HMAC handoff is required to authenticate
|
|
25
27
|
* the background dispatch; without it the dispatch can't be trusted).
|
|
28
|
+
*
|
|
29
|
+
* Default-on is safe because a *dispatch failure degrades to an inline run*: if
|
|
30
|
+
* the self-dispatch self-POST can't be delivered (fast connection error or
|
|
31
|
+
* fast non-2xx), the foreground handler runs the turn synchronously instead of
|
|
32
|
+
* erroring (see `production-agent.ts` — the inline fallback claims the run row
|
|
33
|
+
* atomically so a delayed delivery can never double-execute). So an app where
|
|
34
|
+
* durable dispatch happens to fail still gets a working chat, just without the
|
|
35
|
+
* 15-min budget.
|
|
26
36
|
*/
|
|
27
37
|
import {
|
|
28
38
|
hasConfiguredA2ASecret,
|
|
@@ -41,7 +51,10 @@ import {
|
|
|
41
51
|
export const AGENT_CHAT_PROCESS_RUN_PATH =
|
|
42
52
|
"/_agent-native/agent-chat/_process-run";
|
|
43
53
|
|
|
44
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Env flag for durable background runs. DEFAULT-ON: unset means enabled; an app
|
|
56
|
+
* opts OUT with an explicit falsy value (`false`/`0`/`no`/`off`).
|
|
57
|
+
*/
|
|
45
58
|
export const AGENT_CHAT_DURABLE_BACKGROUND_ENV =
|
|
46
59
|
"AGENT_CHAT_DURABLE_BACKGROUND";
|
|
47
60
|
|
|
@@ -87,21 +100,31 @@ function isFlagEnabled(): boolean {
|
|
|
87
100
|
// Read the literal key (not `process.env[CONST]`) so guard:no-env-credentials
|
|
88
101
|
// can statically verify it against the allowlisted `AGENT_*` prefix. Keep this
|
|
89
102
|
// in sync with AGENT_CHAT_DURABLE_BACKGROUND_ENV.
|
|
103
|
+
//
|
|
104
|
+
// DEFAULT-ON: durable background runs are the desired behavior for every
|
|
105
|
+
// hosted app. So an unset/empty/unknown flag means ON; an app opts OUT only
|
|
106
|
+
// with an explicit falsy value. This still composes with the hosted +
|
|
107
|
+
// A2A_SECRET gates below, so non-hosted / unconfigured apps stay synchronous.
|
|
108
|
+
// Safety net: a failed dispatch degrades to a synchronous inline run (see
|
|
109
|
+
// production-agent.ts), so default-on cannot break chat even if the
|
|
110
|
+
// self-dispatch can't be delivered on a given app.
|
|
90
111
|
const raw = process.env.AGENT_CHAT_DURABLE_BACKGROUND;
|
|
91
|
-
if (raw == null) return
|
|
112
|
+
if (raw == null) return true;
|
|
92
113
|
const normalized = raw.trim().toLowerCase();
|
|
93
|
-
return (
|
|
94
|
-
normalized === "
|
|
95
|
-
normalized === "
|
|
96
|
-
normalized === "
|
|
97
|
-
normalized === "
|
|
114
|
+
return !(
|
|
115
|
+
normalized === "0" ||
|
|
116
|
+
normalized === "false" ||
|
|
117
|
+
normalized === "no" ||
|
|
118
|
+
normalized === "off"
|
|
98
119
|
);
|
|
99
120
|
}
|
|
100
121
|
|
|
101
122
|
/**
|
|
102
|
-
* The single gate. True
|
|
103
|
-
* A2A_SECRET is configured. False otherwise — and
|
|
104
|
-
* synchronous behavior is used, unchanged.
|
|
123
|
+
* The single gate. True when the flag is not explicitly disabled (default-on)
|
|
124
|
+
* AND the runtime is hosted AND A2A_SECRET is configured. False otherwise — and
|
|
125
|
+
* false means the current synchronous behavior is used, unchanged. So a local /
|
|
126
|
+
* non-hosted / unconfigured app stays synchronous even with the flag defaulting
|
|
127
|
+
* on; durable only engages where the runtime actually supports it.
|
|
105
128
|
*/
|
|
106
129
|
export function isAgentChatDurableBackgroundEnabled(): boolean {
|
|
107
130
|
return (
|
|
@@ -4363,6 +4363,7 @@ export function createProductionAgentHandler(
|
|
|
4363
4363
|
// change. With the flag OFF this whole branch is skipped and the inline
|
|
4364
4364
|
// `startRun` path below runs exactly as before (byte-for-byte).
|
|
4365
4365
|
if (dispatchToBackground) {
|
|
4366
|
+
let backgroundRowInserted = false;
|
|
4366
4367
|
try {
|
|
4367
4368
|
// Insert the run row up front so /runs/active sees it immediately and
|
|
4368
4369
|
// the slot stays held while the background function cold-starts. Mark
|
|
@@ -4370,6 +4371,7 @@ export function createProductionAgentHandler(
|
|
|
4370
4371
|
await insertRun(runId, effectiveThreadId, effectiveTurnId, {
|
|
4371
4372
|
dispatchMode: "background",
|
|
4372
4373
|
});
|
|
4374
|
+
backgroundRowInserted = true;
|
|
4373
4375
|
} catch (err) {
|
|
4374
4376
|
// A duplicate-PK collision means the row already exists (retried POST);
|
|
4375
4377
|
// any other failure means we can't safely hand off — fall back to the
|
|
@@ -4418,14 +4420,59 @@ export function createProductionAgentHandler(
|
|
|
4418
4420
|
setResponseStatus(event, 500);
|
|
4419
4421
|
return { error: "Failed to subscribe to background run" };
|
|
4420
4422
|
}
|
|
4421
|
-
|
|
4422
|
-
//
|
|
4423
|
-
//
|
|
4424
|
-
//
|
|
4425
|
-
//
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4423
|
+
|
|
4424
|
+
// ─── Dispatch failed → degrade to a normal synchronous (inline) run ────
|
|
4425
|
+
// `fireInternalDispatch` throws ONLY when the self-POST failed *fast*
|
|
4426
|
+
// (rejected the connection, or returned a non-2xx within the ~250ms settle
|
|
4427
|
+
// race). The `_process-run` route verifies the HMAC token and validates
|
|
4428
|
+
// the body BEFORE it ever reaches the SQL atomic claim, so a fast throw
|
|
4429
|
+
// means NO background worker claimed this run — there is nothing to
|
|
4430
|
+
// double-execute. Rather than break the chat with "Failed to dispatch
|
|
4431
|
+
// background run", we run the turn inline (the same synchronous path the
|
|
4432
|
+
// flag-off branch below takes), reusing the already-inserted run row.
|
|
4433
|
+
//
|
|
4434
|
+
// Safety against a (very improbable) delayed background delivery: claim the
|
|
4435
|
+
// run atomically here via `claimBackgroundRun`, which flips the row's
|
|
4436
|
+
// dispatch_mode `background → background-processing` in one conditional
|
|
4437
|
+
// UPDATE. If a delayed dispatch DID land and a worker already won the
|
|
4438
|
+
// claim, our claim returns false and we must NOT run inline (that would
|
|
4439
|
+
// double-execute) — fall back to subscribing to the worker's run instead.
|
|
4440
|
+
// The SQL atomic claim is the single source of truth for ownership, so at
|
|
4441
|
+
// most one of {inline fallback, background worker} ever executes this run.
|
|
4442
|
+
if (backgroundRowInserted) {
|
|
4443
|
+
let claimedInline = false;
|
|
4444
|
+
try {
|
|
4445
|
+
claimedInline = await claimBackgroundRun(runId);
|
|
4446
|
+
} catch (err) {
|
|
4447
|
+
console.error(
|
|
4448
|
+
"[agent-chat] inline-fallback claim failed:",
|
|
4449
|
+
err instanceof Error ? err.message : err,
|
|
4450
|
+
);
|
|
4451
|
+
}
|
|
4452
|
+
if (!claimedInline) {
|
|
4453
|
+
// A background worker already owns this run (a delayed delivery landed
|
|
4454
|
+
// after our fast throw). Stream its events instead of running a second
|
|
4455
|
+
// copy. If we somehow can't subscribe, surface an error rather than
|
|
4456
|
+
// risk a double-run.
|
|
4457
|
+
const stream = subscribeToRun(runId, 0);
|
|
4458
|
+
if (stream) {
|
|
4459
|
+
setResponseHeader(event, "Content-Type", "text/event-stream");
|
|
4460
|
+
setResponseHeader(event, "Cache-Control", "no-cache");
|
|
4461
|
+
setResponseHeader(event, "Connection", "keep-alive");
|
|
4462
|
+
setResponseHeader(event, "X-Run-Id", runId);
|
|
4463
|
+
return stream;
|
|
4464
|
+
}
|
|
4465
|
+
await updateRunStatusIfRunning(runId, "errored").catch(() => {});
|
|
4466
|
+
setResponseStatus(event, 500);
|
|
4467
|
+
return { error: "Failed to dispatch background run" };
|
|
4468
|
+
}
|
|
4469
|
+
// We own the run. `startRun` (below) calls `insertRun` again, but its
|
|
4470
|
+
// duplicate-PK collision is swallowed (`insertRun(...).catch(() => {})`),
|
|
4471
|
+
// so the existing `background-processing` row is reused — no double row.
|
|
4472
|
+
}
|
|
4473
|
+
// Fall through to the inline `startRun` path below (the same one the
|
|
4474
|
+
// flag-off branch uses). If the row was never inserted, `startRun` inserts
|
|
4475
|
+
// it fresh; if it was, the claim above made us the sole owner.
|
|
4429
4476
|
}
|
|
4430
4477
|
|
|
4431
4478
|
const trackedProgressOwner =
|
|
@@ -1893,7 +1893,7 @@ function copyDir(src: string, dest: string, root?: string): void {
|
|
|
1893
1893
|
|
|
1894
1894
|
function shouldSkipScaffoldEntry(name: string, srcPath?: string): boolean {
|
|
1895
1895
|
if (
|
|
1896
|
-
|
|
1896
|
+
/^settings(?:\..*)?\.json$/.test(name) &&
|
|
1897
1897
|
srcPath?.split(path.sep).includes(".claude")
|
|
1898
1898
|
) {
|
|
1899
1899
|
return true;
|