@agent-native/core 0.163.4 → 0.164.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/corpus/README.md +1 -1
- package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +29 -0
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -2
- package/corpus/templates/analytics/netlify.toml +2 -0
- package/corpus/templates/assets/netlify.toml +2 -0
- package/corpus/templates/brain/netlify.toml +2 -0
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +2 -1
- package/corpus/templates/calendar/changelog/2026-08-19-calendar-page-loads-stay-fast-after-idle-periods.md +6 -0
- package/corpus/templates/calendar/netlify.toml +2 -0
- package/corpus/templates/chat/netlify.toml +2 -0
- package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -3
- package/corpus/templates/clips/app/components/player/reaction-emojis.ts +12 -0
- package/corpus/templates/clips/app/components/player/reactions-tray.tsx +90 -9
- package/corpus/templates/clips/app/components/player/scrubber.tsx +43 -10
- package/corpus/templates/clips/app/components/player/video-player.tsx +105 -15
- package/corpus/templates/clips/app/routes/_app.settings._index.tsx +1 -2
- package/corpus/templates/clips/app/routes/_index.tsx +10 -2
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +13 -8
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +15 -8
- package/corpus/templates/clips/netlify.toml +2 -0
- package/corpus/templates/clips/server/routes/[...page].head.ts +5 -0
- package/corpus/templates/content/netlify.toml +2 -0
- package/corpus/templates/design/.agents/skills/design-editor-architecture/SKILL.md +103 -0
- package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +2 -1
- package/corpus/templates/design/AGENTS.md +3 -1
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +3 -2
- package/corpus/templates/design/app/components/design/editor/AgentNativeMenuMark.tsx +25 -0
- package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +411 -0
- package/corpus/templates/design/app/components/design/editor/DesignCollaborators.tsx +153 -0
- package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +231 -0
- package/corpus/templates/design/app/components/design/editor/MakeRealDialog.tsx +223 -0
- package/corpus/templates/design/app/components/design/editor/PendingScreenDeletionDialog.tsx +58 -0
- package/corpus/templates/design/app/components/design/editor/PendingVisualStyleWarningDialog.tsx +56 -0
- package/corpus/templates/design/app/components/design/editor/ReadOnlyEditorPanel.tsx +23 -0
- package/corpus/templates/design/app/components/design/editor/SaveTemplateDialog.tsx +161 -0
- package/corpus/templates/design/app/components/design/editor/toolbar-controls.tsx +185 -0
- package/corpus/templates/design/app/pages/DesignEditor.tsx +20913 -0
- package/corpus/templates/design/app/pages/design-editor/command-types.ts +120 -0
- package/corpus/templates/design/app/pages/design-editor/commands/README.md +193 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-auto-layout.ts +416 -0
- package/corpus/templates/design/app/pages/design-editor/commands/add-screen.ts +112 -0
- package/corpus/templates/design/app/pages/design-editor/commands/align-selection.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +243 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +236 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +304 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +376 -0
- package/corpus/templates/design/app/pages/design-editor/commands/apply-to-source.ts +132 -0
- package/corpus/templates/design/app/pages/design-editor/commands/can-move-layer.ts +117 -0
- package/corpus/templates/design/app/pages/design-editor/commands/change-selected-z-index.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-relative-style-delta-to-selected-layers.ts +176 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-styles-to-selected-layers.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +710 -0
- package/corpus/templates/design/app/pages/design-editor/commands/confirm-make-real.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-as-figma-svg.ts +95 -0
- package/corpus/templates/design/app/pages/design-editor/commands/copy-selection.ts +156 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-primitive.ts +291 -0
- package/corpus/templates/design/app/pages/design-editor/commands/create-screen-frame.ts +131 -0
- package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +577 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-files.ts +364 -0
- package/corpus/templates/design/app/pages/design-editor/commands/delete-selection.ts +521 -0
- package/corpus/templates/design/app/pages/design-editor/commands/detach-instance-menu-action.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/distribute-selection.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-all-screens-pdf.ts +116 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-pdf.ts +103 -0
- package/corpus/templates/design/app/pages/design-editor/commands/download-svg.ts +159 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-screen.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/duplicate-selection.ts +279 -0
- package/corpus/templates/design/app/pages/design-editor/commands/editor-paste.ts +81 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-hotkey.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/enter-single-screen.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +212 -0
- package/corpus/templates/design/app/pages/design-editor/commands/frame-selection.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/geometry-commit.ts +169 -0
- package/corpus/templates/design/app/pages/design-editor/commands/get-selected-layer-snapshots.ts +177 -0
- package/corpus/templates/design/app/pages/design-editor/commands/group-selection.ts +127 -0
- package/corpus/templates/design/app/pages/design-editor/commands/iframe-context-menu.ts +121 -0
- package/corpus/templates/design/app/pages/design-editor/commands/import-figma-clipboard-into-design.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +163 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move-to-screen.ts +331 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-move.ts +517 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-rename.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +161 -0
- package/corpus/templates/design/app/pages/design-editor/commands/mode-change.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/nudge-selection.ts +213 -0
- package/corpus/templates/design/app/pages/design-editor/commands/overview-primitive-reparent.ts +318 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-copied-screens.ts +114 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-over-selection.ts +70 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +436 -0
- package/corpus/templates/design/app/pages/design-editor/commands/paste-to-replace.ts +135 -0
- package/corpus/templates/design/app/pages/design-editor/commands/pasted-image-files.ts +209 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-frame-geometry-save.ts +113 -0
- package/corpus/templates/design/app/pages/design-editor/commands/persist-tweak-save.ts +160 -0
- package/corpus/templates/design/app/pages/design-editor/commands/primitive-created.ts +168 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-layer-state-edit.ts +149 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-structure-edit.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-live-text-edit.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/record-pending-visual-style-edit.ts +247 -0
- package/corpus/templates/design/app/pages/design-editor/commands/redo.ts +1086 -0
- package/corpus/templates/design/app/pages/design-editor/commands/render-png-blob.ts +200 -0
- package/corpus/templates/design/app/pages/design-editor/commands/save-file-content.ts +207 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +262 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-text-content-change.ts +216 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-duplicate-change.ts +108 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-structure-change.ts +280 -0
- package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +151 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-overview-annotations.ts +88 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +122 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +143 -0
- package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +115 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-retry-generation.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/style-change.ts +152 -0
- package/corpus/templates/design/app/pages/design-editor/commands/styles-change.ts +155 -0
- package/corpus/templates/design/app/pages/design-editor/commands/suggest-auto-layout.ts +125 -0
- package/corpus/templates/design/app/pages/design-editor/commands/text-content-change.ts +201 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tidy-up.ts +123 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-hidden.ts +167 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-layer-locked.ts +175 -0
- package/corpus/templates/design/app/pages/design-editor/commands/toggle-motion-keyframe.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/commands/tweak-prompt-submit.ts +84 -0
- package/corpus/templates/design/app/pages/design-editor/commands/undo.ts +906 -0
- package/corpus/templates/design/app/pages/design-editor/commands/ungroup-selection.ts +170 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-duplicate-change.ts +119 -0
- package/corpus/templates/design/app/pages/design-editor/commands/visual-structure-change.ts +274 -0
- package/corpus/templates/design/app/pages/design-editor/commands/write-frame-geometry-snapshot.ts +99 -0
- package/corpus/templates/design/app/pages/design-editor/derive/design-breakpoints.ts +56 -0
- package/corpus/templates/design/app/pages/design-editor/derive/overview-screens.ts +146 -0
- package/corpus/templates/design/app/pages/design-editor/domains/use-tweaks.ts +326 -0
- package/corpus/templates/design/app/pages/design-editor/editor-constants.ts +54 -0
- package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +270 -0
- package/corpus/templates/design/app/pages/design-editor/effects/mirror-selection-to-agent-chat.ts +134 -0
- package/corpus/templates/design/app/pages/design-editor/effects/motion-autosave.ts +335 -0
- package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +183 -0
- package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +252 -0
- package/corpus/templates/design/app/pages/design-editor/effects/resume-pending-generation.ts +178 -0
- package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +157 -0
- package/corpus/templates/design/app/pages/design-editor/preview-html.ts +19 -0
- package/corpus/templates/design/netlify.toml +2 -0
- package/corpus/templates/design/shared/board-file.ts +2 -1
- package/corpus/templates/dispatch/netlify.toml +2 -0
- package/corpus/templates/forms/netlify.toml +2 -0
- package/corpus/templates/mail/netlify.toml +2 -0
- package/corpus/templates/plan/netlify.toml +2 -0
- package/corpus/templates/slides/netlify.toml +2 -0
- package/dist/agent/engine/builder-engine.d.ts +6 -4
- package/dist/agent/engine/builder-engine.js +91 -26
- package/dist/agent/engine/registry.js +16 -0
- package/dist/cli/code-agent-agent-tools.d.ts +2 -0
- package/dist/cli/code-agent-agent-tools.js +188 -0
- package/dist/cli/code-agent-collaboration.d.ts +34 -0
- package/dist/cli/code-agent-collaboration.js +104 -0
- package/dist/cli/code-agent-executor.js +6 -0
- package/dist/cli/code-agent-schedules.d.ts +54 -0
- package/dist/cli/code-agent-schedules.js +198 -0
- package/dist/client/AgentPanel.js +1 -1
- package/dist/client/ConnectBuilderCard.js +5 -2
- package/dist/client/EnvironmentBadge.js +6 -5
- package/dist/client/chat/run-recovery.js +3 -2
- package/dist/client/chat/tool-call-display.js +2 -3
- package/dist/client/components/CodeRequiredDialog.js +4 -2
- package/dist/client/i18n.js +5 -4
- package/dist/client/settings/SettingsPanel.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/useBuilderStatus.d.ts +6 -1
- package/dist/client/settings/useBuilderStatus.js +22 -33
- package/dist/client/transcription/BuilderTranscriptionCta.js +1 -1
- package/dist/code-agents/index.d.ts +2 -0
- package/dist/code-agents/index.js +2 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/localization/shared.d.ts +2 -0
- package/dist/localization/shared.js +5 -0
- package/dist/mcp-client/oauth-client.d.ts +1 -0
- package/dist/mcp-client/oauth-client.js +50 -1
- package/dist/observability/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/auth-marketing-locales.d.ts +7 -0
- package/dist/server/auth-marketing-locales.js +1322 -0
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +35 -6
- package/dist/server/auth.js +4 -17
- package/dist/server/builder-browser.d.ts +22 -0
- package/dist/server/builder-browser.js +77 -1
- package/dist/server/builder-oauth.d.ts +50 -0
- package/dist/server/builder-oauth.js +263 -0
- package/dist/server/core-routes-plugin.d.ts +11 -0
- package/dist/server/core-routes-plugin.js +291 -415
- package/dist/server/credential-provider.d.ts +1 -1
- package/dist/server/credential-provider.js +1 -1
- package/dist/server/csrf.js +2 -2
- package/dist/server/onboarding-html.js +52 -120
- package/dist/settings/store.d.ts +9 -0
- package/dist/settings/store.js +19 -0
- package/dist/templates/chat/netlify.toml +2 -0
- package/docs/content/deployment.mdx +2 -0
- package/docs/content/multi-app-workspace.mdx +1 -1
- package/package.json +2 -2
- package/src/templates/chat/netlify.toml +2 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { codeAgentStoreRoot } from "./code-agent-runs.js";
|
|
5
|
+
const SCHEDULE_FILE_NAME = "schedules.json";
|
|
6
|
+
const MIN_INTERVAL_MINUTES = 1;
|
|
7
|
+
const MAX_INTERVAL_MINUTES = 31 * 24 * 60;
|
|
8
|
+
export function codeAgentSchedulesPath() {
|
|
9
|
+
return path.join(codeAgentStoreRoot(), SCHEDULE_FILE_NAME);
|
|
10
|
+
}
|
|
11
|
+
export function listCodeAgentSchedules() {
|
|
12
|
+
const records = readScheduleFile();
|
|
13
|
+
return records.sort((a, b) => {
|
|
14
|
+
if (a.enabled !== b.enabled)
|
|
15
|
+
return a.enabled ? -1 : 1;
|
|
16
|
+
return a.nextRunAt.localeCompare(b.nextRunAt);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export function getCodeAgentSchedule(scheduleId) {
|
|
20
|
+
return (readScheduleFile().find((schedule) => schedule.id === scheduleId) ?? null);
|
|
21
|
+
}
|
|
22
|
+
export function createCodeAgentSchedule(input) {
|
|
23
|
+
const name = normalizeRequiredText(input.name, "Schedule name");
|
|
24
|
+
const prompt = normalizeRequiredText(input.prompt, "Schedule prompt");
|
|
25
|
+
const scope = input.scope ?? "global";
|
|
26
|
+
if (scope !== "global" && scope !== "thread") {
|
|
27
|
+
throw new Error("Schedule scope must be global or thread.");
|
|
28
|
+
}
|
|
29
|
+
const targetRunId = normalizeOptionalText(input.targetRunId);
|
|
30
|
+
if (scope === "thread" && !targetRunId) {
|
|
31
|
+
throw new Error("Thread schedules require a target run.");
|
|
32
|
+
}
|
|
33
|
+
const intervalMinutes = normalizeIntervalMinutes(input.intervalMinutes);
|
|
34
|
+
const now = input.now ?? new Date();
|
|
35
|
+
const nowIso = now.toISOString();
|
|
36
|
+
const record = {
|
|
37
|
+
schemaVersion: 1,
|
|
38
|
+
id: `schedule-${timestampSlug(nowIso)}-${crypto.randomUUID().slice(0, 8)}`,
|
|
39
|
+
name,
|
|
40
|
+
prompt,
|
|
41
|
+
scope,
|
|
42
|
+
...(targetRunId ? { targetRunId } : {}),
|
|
43
|
+
intervalMinutes,
|
|
44
|
+
enabled: input.enabled ?? true,
|
|
45
|
+
createdAt: nowIso,
|
|
46
|
+
updatedAt: nowIso,
|
|
47
|
+
nextRunAt: new Date(now.getTime() + intervalMinutes * 60_000).toISOString(),
|
|
48
|
+
...(input.createdByRunId
|
|
49
|
+
? { createdByRunId: normalizeOptionalText(input.createdByRunId) }
|
|
50
|
+
: {}),
|
|
51
|
+
};
|
|
52
|
+
writeScheduleFile([...readScheduleFile(), record]);
|
|
53
|
+
return record;
|
|
54
|
+
}
|
|
55
|
+
export function updateCodeAgentSchedule(scheduleId, input) {
|
|
56
|
+
const schedules = readScheduleFile();
|
|
57
|
+
const current = schedules.find((schedule) => schedule.id === scheduleId);
|
|
58
|
+
if (!current)
|
|
59
|
+
return null;
|
|
60
|
+
const nextScope = input.scope ?? current.scope;
|
|
61
|
+
if (nextScope !== "global" && nextScope !== "thread") {
|
|
62
|
+
throw new Error("Schedule scope must be global or thread.");
|
|
63
|
+
}
|
|
64
|
+
const nextTargetRunId = input.targetRunId === null
|
|
65
|
+
? undefined
|
|
66
|
+
: normalizeOptionalText(input.targetRunId ?? current.targetRunId);
|
|
67
|
+
if (nextScope === "thread" && !nextTargetRunId) {
|
|
68
|
+
throw new Error("Thread schedules require a target run.");
|
|
69
|
+
}
|
|
70
|
+
const intervalChanged = input.intervalMinutes !== undefined;
|
|
71
|
+
const intervalMinutes = intervalChanged
|
|
72
|
+
? normalizeIntervalMinutes(input.intervalMinutes)
|
|
73
|
+
: current.intervalMinutes;
|
|
74
|
+
const now = new Date();
|
|
75
|
+
const next = {
|
|
76
|
+
...current,
|
|
77
|
+
...(input.name !== undefined
|
|
78
|
+
? { name: normalizeRequiredText(input.name, "Schedule name") }
|
|
79
|
+
: {}),
|
|
80
|
+
...(input.prompt !== undefined
|
|
81
|
+
? { prompt: normalizeRequiredText(input.prompt, "Schedule prompt") }
|
|
82
|
+
: {}),
|
|
83
|
+
scope: nextScope,
|
|
84
|
+
...(nextTargetRunId ? { targetRunId: nextTargetRunId } : {}),
|
|
85
|
+
...(nextTargetRunId ? {} : { targetRunId: undefined }),
|
|
86
|
+
intervalMinutes,
|
|
87
|
+
...(input.enabled !== undefined ? { enabled: input.enabled } : {}),
|
|
88
|
+
updatedAt: now.toISOString(),
|
|
89
|
+
...(intervalChanged
|
|
90
|
+
? {
|
|
91
|
+
nextRunAt: new Date(now.getTime() + intervalMinutes * 60_000).toISOString(),
|
|
92
|
+
}
|
|
93
|
+
: {}),
|
|
94
|
+
};
|
|
95
|
+
writeScheduleFile(schedules.map((schedule) => (schedule.id === scheduleId ? next : schedule)));
|
|
96
|
+
return next;
|
|
97
|
+
}
|
|
98
|
+
export function deleteCodeAgentSchedule(scheduleId) {
|
|
99
|
+
const schedules = readScheduleFile();
|
|
100
|
+
const next = schedules.filter((schedule) => schedule.id !== scheduleId);
|
|
101
|
+
if (next.length === schedules.length)
|
|
102
|
+
return false;
|
|
103
|
+
writeScheduleFile(next);
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
export function markCodeAgentScheduleRun(scheduleId, patch) {
|
|
107
|
+
const schedules = readScheduleFile();
|
|
108
|
+
const current = schedules.find((schedule) => schedule.id === scheduleId);
|
|
109
|
+
if (!current)
|
|
110
|
+
return null;
|
|
111
|
+
const next = {
|
|
112
|
+
...current,
|
|
113
|
+
updatedAt: new Date().toISOString(),
|
|
114
|
+
lastRunAt: patch.lastRunAt,
|
|
115
|
+
lastStatus: patch.lastStatus,
|
|
116
|
+
...(patch.nextRunAt ? { nextRunAt: patch.nextRunAt } : {}),
|
|
117
|
+
...(patch.lastError
|
|
118
|
+
? { lastError: patch.lastError }
|
|
119
|
+
: { lastError: undefined }),
|
|
120
|
+
...(patch.lastTriggeredRunId
|
|
121
|
+
? { lastTriggeredRunId: patch.lastTriggeredRunId }
|
|
122
|
+
: {}),
|
|
123
|
+
};
|
|
124
|
+
writeScheduleFile(schedules.map((schedule) => (schedule.id === scheduleId ? next : schedule)));
|
|
125
|
+
return next;
|
|
126
|
+
}
|
|
127
|
+
export function isCodeAgentScheduleDue(schedule, now = new Date()) {
|
|
128
|
+
return schedule.enabled && Date.parse(schedule.nextRunAt) <= now.getTime();
|
|
129
|
+
}
|
|
130
|
+
export function nextCodeAgentScheduleRunAt(schedule, now = new Date()) {
|
|
131
|
+
const intervalMs = schedule.intervalMinutes * 60_000;
|
|
132
|
+
let next = Date.parse(schedule.nextRunAt);
|
|
133
|
+
if (!Number.isFinite(next))
|
|
134
|
+
next = now.getTime() + intervalMs;
|
|
135
|
+
while (next <= now.getTime())
|
|
136
|
+
next += intervalMs;
|
|
137
|
+
return new Date(next).toISOString();
|
|
138
|
+
}
|
|
139
|
+
function readScheduleFile() {
|
|
140
|
+
try {
|
|
141
|
+
const raw = JSON.parse(fs.readFileSync(codeAgentSchedulesPath(), "utf8"));
|
|
142
|
+
if (!Array.isArray(raw))
|
|
143
|
+
return [];
|
|
144
|
+
return raw.filter(isScheduleRecord);
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function writeScheduleFile(records) {
|
|
151
|
+
const filePath = codeAgentSchedulesPath();
|
|
152
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
153
|
+
const tempPath = `${filePath}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
154
|
+
fs.writeFileSync(tempPath, `${JSON.stringify(records, null, 2)}\n`);
|
|
155
|
+
fs.renameSync(tempPath, filePath);
|
|
156
|
+
}
|
|
157
|
+
function isScheduleRecord(value) {
|
|
158
|
+
if (!value || typeof value !== "object")
|
|
159
|
+
return false;
|
|
160
|
+
const record = value;
|
|
161
|
+
return (record.schemaVersion === 1 &&
|
|
162
|
+
typeof record.id === "string" &&
|
|
163
|
+
typeof record.name === "string" &&
|
|
164
|
+
typeof record.prompt === "string" &&
|
|
165
|
+
(record.scope === "global" || record.scope === "thread") &&
|
|
166
|
+
(record.scope !== "thread" || typeof record.targetRunId === "string") &&
|
|
167
|
+
typeof record.intervalMinutes === "number" &&
|
|
168
|
+
record.intervalMinutes >= MIN_INTERVAL_MINUTES &&
|
|
169
|
+
record.intervalMinutes <= MAX_INTERVAL_MINUTES &&
|
|
170
|
+
typeof record.enabled === "boolean" &&
|
|
171
|
+
typeof record.createdAt === "string" &&
|
|
172
|
+
typeof record.updatedAt === "string" &&
|
|
173
|
+
typeof record.nextRunAt === "string");
|
|
174
|
+
}
|
|
175
|
+
function normalizeRequiredText(value, label) {
|
|
176
|
+
const normalized = typeof value === "string" ? value.trim() : "";
|
|
177
|
+
if (!normalized)
|
|
178
|
+
throw new Error(`${label} is required.`);
|
|
179
|
+
return normalized.slice(0, 8_000);
|
|
180
|
+
}
|
|
181
|
+
function normalizeOptionalText(value) {
|
|
182
|
+
if (typeof value !== "string")
|
|
183
|
+
return undefined;
|
|
184
|
+
const normalized = value.trim();
|
|
185
|
+
return normalized ? normalized.slice(0, 256) : undefined;
|
|
186
|
+
}
|
|
187
|
+
function normalizeIntervalMinutes(value) {
|
|
188
|
+
const interval = Number(value);
|
|
189
|
+
if (!Number.isInteger(interval) ||
|
|
190
|
+
interval < MIN_INTERVAL_MINUTES ||
|
|
191
|
+
interval > MAX_INTERVAL_MINUTES) {
|
|
192
|
+
throw new Error(`Interval must be a whole number between ${MIN_INTERVAL_MINUTES} minute and ${MAX_INTERVAL_MINUTES / (24 * 60)} days.`);
|
|
193
|
+
}
|
|
194
|
+
return interval;
|
|
195
|
+
}
|
|
196
|
+
function timestampSlug(value) {
|
|
197
|
+
return value.replace(/[-:.TZ]/g, "").slice(0, 14);
|
|
198
|
+
}
|
|
@@ -310,7 +310,7 @@ function useBuilderConnectUrl() {
|
|
|
310
310
|
.then((data) => {
|
|
311
311
|
if (cancelled || !data)
|
|
312
312
|
return;
|
|
313
|
-
const nextConnectUrl = data.
|
|
313
|
+
const nextConnectUrl = data.connectUrl;
|
|
314
314
|
if (nextConnectUrl)
|
|
315
315
|
setConnectUrl(nextConnectUrl);
|
|
316
316
|
const nextConfigured = !!data.configured;
|
|
@@ -42,6 +42,9 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
|
|
|
42
42
|
// arrives. A transient status failure must not replace a valid Send CTA with
|
|
43
43
|
// the hook's initial disconnected defaults.
|
|
44
44
|
const configured = flow.statusResolved ? flow.configured : initialConfigured;
|
|
45
|
+
const codeChangeConfigured = flow.statusResolved
|
|
46
|
+
? flow.codeChangeConfigured
|
|
47
|
+
: initialConfigured;
|
|
45
48
|
const builderEnabled = flow.statusResolved
|
|
46
49
|
? flow.builderEnabled
|
|
47
50
|
: initialBuilderEnabled;
|
|
@@ -162,7 +165,7 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
|
|
|
162
165
|
// Combine connect-flow errors, send errors, waitlist errors, and copy errors.
|
|
163
166
|
const err = sendErr ?? waitlistErr ?? copyErr ?? flow.error;
|
|
164
167
|
const hasPrompt = prompt.trim().length > 0;
|
|
165
|
-
const canSend =
|
|
168
|
+
const canSend = codeChangeConfigured && builderEnabled && hasPrompt;
|
|
166
169
|
const showDesktopLocalHandoff = electronShell && hasPrompt;
|
|
167
170
|
const handleDoLocally = useCallback((event) => {
|
|
168
171
|
if (requestDesktopLocalCodeChange(prompt, event.currentTarget)) {
|
|
@@ -191,7 +194,7 @@ export function ConnectBuilderCard({ configured: initialConfigured, builderEnabl
|
|
|
191
194
|
const showWaitlist = !localDevelopment && !builderEnabled && hasPrompt;
|
|
192
195
|
// Title + subtitle depend on which mode we're in. We compute them up front
|
|
193
196
|
// so the render tree below stays flat.
|
|
194
|
-
const connectedCapabilityText = builderEnabled
|
|
197
|
+
const connectedCapabilityText = builderEnabled && codeChangeConfigured
|
|
195
198
|
? "AI credits and cloud code changes are ready to use."
|
|
196
199
|
: `AI credits are ready to use. ${CODE_CHANGE_FALLBACK_TEXT}`;
|
|
197
200
|
let title;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button } from "@agent-native/toolkit/ui/button";
|
|
3
3
|
import { Popover, PopoverContent, PopoverTrigger, } from "@agent-native/toolkit/ui/popover";
|
|
4
|
-
import { IconExternalLink, IconGitBranch } from "@tabler/icons-react";
|
|
5
4
|
import { useEffect, useMemo, useRef } from "react";
|
|
6
5
|
import { trackEvent } from "./analytics.js";
|
|
7
6
|
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
@@ -132,7 +131,7 @@ function consumeBetaOptOutQueryParam(sourceHref, now = Date.now()) {
|
|
|
132
131
|
return active;
|
|
133
132
|
}
|
|
134
133
|
function EnvironmentLink({ label, href }) {
|
|
135
|
-
return (_jsx(Button, { asChild: true, className: "w-full justify-
|
|
134
|
+
return (_jsx(Button, { asChild: true, className: "w-full justify-center", size: "sm", variant: "outline", children: _jsx("a", { href: href, children: label }) }));
|
|
136
135
|
}
|
|
137
136
|
/**
|
|
138
137
|
* Small internal-only lane switcher for first-party hosted Agent-Native apps.
|
|
@@ -159,7 +158,6 @@ export function EnvironmentBadge() {
|
|
|
159
158
|
didAutoRedirect.current) {
|
|
160
159
|
return;
|
|
161
160
|
}
|
|
162
|
-
didAutoRedirect.current = true;
|
|
163
161
|
if (readBetaOptOutUntil() !== null)
|
|
164
162
|
return;
|
|
165
163
|
if (consumeBetaOptOutQueryParam(window.location.href))
|
|
@@ -167,6 +165,7 @@ export function EnvironmentBadge() {
|
|
|
167
165
|
const betaHref = buildEnvironmentUrl(window.location.href, targets.betaHost);
|
|
168
166
|
if (!betaHref || typeof window.location.replace !== "function")
|
|
169
167
|
return;
|
|
168
|
+
didAutoRedirect.current = true;
|
|
170
169
|
trackEvent("environment switched", {
|
|
171
170
|
from_environment: "production",
|
|
172
171
|
to_environment: "beta",
|
|
@@ -186,6 +185,8 @@ export function EnvironmentBadge() {
|
|
|
186
185
|
if (!betaHref || !productionHref)
|
|
187
186
|
return null;
|
|
188
187
|
const label = environment === "beta" ? "beta" : "prod";
|
|
189
|
-
const title = environment === "beta"
|
|
190
|
-
|
|
188
|
+
const title = environment === "beta"
|
|
189
|
+
? "You're on Agent Native Beta"
|
|
190
|
+
: "You're on Agent Native Production";
|
|
191
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { "aria-label": `Open ${title.toLowerCase()} switcher`, className: "fixed bottom-3 right-3 z-[100] h-6 min-w-0 rounded-xl border-border/80 bg-background/95 px-2 text-[11px] font-semibold uppercase tracking-[0.5px] shadow-sm backdrop-blur-sm", size: "sm", variant: environment === "beta" ? "default" : "outline", children: label }) }), _jsxs(PopoverContent, { align: "center", className: "w-[280px] p-5", side: "top", sideOffset: 8, children: [_jsx("div", { className: "mb-1 text-sm font-semibold leading-5", children: title }), _jsx("div", { className: "mb-4 text-sm text-muted-foreground", children: "Choose where you want to continue." }), _jsx("div", { className: "grid gap-2", children: environment === "beta" ? (_jsx(EnvironmentLink, { href: productionHref, label: "Switch to production" })) : (_jsx(EnvironmentLink, { href: betaHref, label: "Go to beta" })) })] })] }));
|
|
191
192
|
}
|
|
@@ -114,7 +114,7 @@ function isConnectionRecoveryRunError(info) {
|
|
|
114
114
|
}
|
|
115
115
|
// ─── BuilderConnectCta ────────────────────────────────────────────────────────
|
|
116
116
|
// Renders a single row with left-aligned copy and a right-aligned action.
|
|
117
|
-
// Click opens the Builder
|
|
117
|
+
// Click opens the Builder OAuth popup via the shared
|
|
118
118
|
// `useBuilderConnectFlow` hook (which owns the synchronous window.open,
|
|
119
119
|
// the 2s status poll, and the focus-refresh). On success the hook broadcasts
|
|
120
120
|
// a config-change event so the chat clears its local `missingApiKey` gate.
|
|
@@ -238,8 +238,9 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
|
|
|
238
238
|
}, [onDismiss]);
|
|
239
239
|
const handleProviderConnected = useCallback(() => {
|
|
240
240
|
onProviderConnected?.();
|
|
241
|
+
onRetry();
|
|
241
242
|
onDismiss();
|
|
242
|
-
}, [onDismiss, onProviderConnected]);
|
|
243
|
+
}, [onDismiss, onProviderConnected, onRetry]);
|
|
243
244
|
const handleFork = useCallback(async () => {
|
|
244
245
|
if (!onFork || forking)
|
|
245
246
|
return;
|
|
@@ -337,9 +337,8 @@ function ToolCallDisplayGeneric({ toolName, toolCallId, argsText, args, result,
|
|
|
337
337
|
const parsed = JSON.parse(result);
|
|
338
338
|
if (parsed?.kind === "connect-builder-card") {
|
|
339
339
|
return (_jsx(ConnectBuilderCard, { configured: !!parsed.configured, builderEnabled: parsed.builderEnabled !== false,
|
|
340
|
-
// Ignore
|
|
341
|
-
//
|
|
342
|
-
// open; the card's hook fetches a fresh signed URL on mount/click.
|
|
340
|
+
// Ignore obsolete direct-auth URLs from older tool results. The
|
|
341
|
+
// card fetches a fresh app-local connect URL on mount and click.
|
|
343
342
|
connectUrl: parsed.connectUrl || "", orgName: parsed.orgName ?? null, prompt: typeof parsed.prompt === "string" ? parsed.prompt : "" }));
|
|
344
343
|
}
|
|
345
344
|
}
|
|
@@ -17,8 +17,10 @@ function useBuilderConnected() {
|
|
|
17
17
|
.then((data) => {
|
|
18
18
|
if (data) {
|
|
19
19
|
setConnected(!!data.configured);
|
|
20
|
-
setCloudAgentsAvailable(!!data.builderEnabled
|
|
21
|
-
|
|
20
|
+
setCloudAgentsAvailable(!!data.builderEnabled &&
|
|
21
|
+
!!data.privateKeyConfigured &&
|
|
22
|
+
!!data.publicKeyConfigured);
|
|
23
|
+
setConnectUrl(data.connectUrl || null);
|
|
22
24
|
}
|
|
23
25
|
})
|
|
24
26
|
.catch(() => { });
|
package/dist/client/i18n.js
CHANGED
|
@@ -7,7 +7,7 @@ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, use
|
|
|
7
7
|
import { I18nextProvider, initReactI18next, useTranslation, } from "react-i18next";
|
|
8
8
|
import { coreMessagesForLocale, englishAgentChatMessages, loadCoreMessagesForLocale, normalizeCoreMessageOverrides, } from "../localization/core-messages.js";
|
|
9
9
|
import defaultEnglishMessages from "../localization/default-messages.js";
|
|
10
|
-
import { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDirection, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, } from "../localization/shared.js";
|
|
10
|
+
import { DEFAULT_LOCALE, LOCALE_HYDRATION_GLOBAL, LOCALE_METADATA, LOCALE_STORAGE_KEY, SUPPORTED_LOCALES, localeDisplayName, localeDirection, normalizeLocalizationPreference, resolveLocaleFromCandidates, resolveLocaleFromPreference, } from "../localization/shared.js";
|
|
11
11
|
import { injectedAgentNativeConfig } from "./app-config.js";
|
|
12
12
|
import { setClientAppState } from "./application-state.js";
|
|
13
13
|
import { callAction } from "./use-action.js";
|
|
@@ -603,20 +603,21 @@ export function LanguagePicker({ className, includeSystem = true, label, variant
|
|
|
603
603
|
const { locale, preference, setPreference, supportedLocales } = useLocale();
|
|
604
604
|
const [open, setOpen] = useState(false);
|
|
605
605
|
const copy = LANGUAGE_PICKER_COPY[locale] ?? LANGUAGE_PICKER_COPY[DEFAULT_LOCALE];
|
|
606
|
+
const systemCopy = LANGUAGE_PICKER_COPY[resolveLocaleFromCandidates(browserLanguageCandidates())] ?? LANGUAGE_PICKER_COPY[DEFAULT_LOCALE];
|
|
606
607
|
const resolvedLabel = label ?? copy.label;
|
|
607
608
|
const options = [
|
|
608
609
|
...(includeSystem
|
|
609
610
|
? [
|
|
610
611
|
{
|
|
611
612
|
value: "system",
|
|
612
|
-
label:
|
|
613
|
-
description:
|
|
613
|
+
label: systemCopy.system,
|
|
614
|
+
description: systemCopy.systemDescription,
|
|
614
615
|
},
|
|
615
616
|
]
|
|
616
617
|
: []),
|
|
617
618
|
...supportedLocales.map((code) => ({
|
|
618
619
|
value: code,
|
|
619
|
-
label:
|
|
620
|
+
label: localeDisplayName(code),
|
|
620
621
|
description: code,
|
|
621
622
|
})),
|
|
622
623
|
];
|
|
@@ -1060,7 +1060,7 @@ function SettingsPanelContent({ isDevMode, initialSection, sectionRequestKey, se
|
|
|
1060
1060
|
enabled: !builderConnectionOwnedExternally,
|
|
1061
1061
|
});
|
|
1062
1062
|
const connected = builder?.configured ?? false;
|
|
1063
|
-
const connectUrl = builder?.
|
|
1063
|
+
const connectUrl = builder?.connectUrl;
|
|
1064
1064
|
const orgName = builder?.orgName;
|
|
1065
1065
|
const envManaged = !!builder?.envManaged;
|
|
1066
1066
|
const credentialSource = builder?.credentialSource;
|
|
@@ -247,7 +247,7 @@ export function VoiceTranscriptionSection({ compact = false, } = {}) {
|
|
|
247
247
|
};
|
|
248
248
|
const openBuilderConnect = () => {
|
|
249
249
|
openBuilderConnectPopup({
|
|
250
|
-
url: builderStatus?.
|
|
250
|
+
url: builderStatus?.connectUrl,
|
|
251
251
|
source: "voice_transcription_settings",
|
|
252
252
|
features: "noopener,noreferrer,width=600,height=700",
|
|
253
253
|
});
|
|
@@ -9,7 +9,6 @@ export interface BuilderStatus {
|
|
|
9
9
|
envManaged?: boolean;
|
|
10
10
|
credentialSource?: "user" | "org" | "workspace" | "env";
|
|
11
11
|
connectUrl: string;
|
|
12
|
-
cliAuthUrl?: string;
|
|
13
12
|
appHost: string;
|
|
14
13
|
apiHost: string;
|
|
15
14
|
branchProjectIdConfigured?: boolean;
|
|
@@ -98,6 +97,12 @@ export interface BuilderConnectFlow {
|
|
|
98
97
|
* Builder account.
|
|
99
98
|
*/
|
|
100
99
|
envManaged: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* True when legacy Builder private/public keys are present. Cloud code-change
|
|
102
|
+
* routes (`/builder/run`, `/builder/agents-run`) still require those keys;
|
|
103
|
+
* OAuth `configured` only covers the chat gateway.
|
|
104
|
+
*/
|
|
105
|
+
codeChangeConfigured: boolean;
|
|
101
106
|
/**
|
|
102
107
|
* True when the server has a Builder branch project configured for this
|
|
103
108
|
* request. When false, the card surfaces a waitlist CTA instead of a Send
|
|
@@ -88,7 +88,6 @@ const STATUS_FETCH_ABORT_MS = 10_000;
|
|
|
88
88
|
const CALLBACK_SUCCESS_STATUS_RETRY_MS = 500;
|
|
89
89
|
const CALLBACK_SUCCESS_STATUS_RETRIES = 10;
|
|
90
90
|
const BUILDER_CONNECT_PARAM = "_an_connect";
|
|
91
|
-
const BUILDER_STATE_PARAM = "_an_state";
|
|
92
91
|
const BUILDER_SIGNUP_SOURCE_PARAM = "signupSource";
|
|
93
92
|
const BUILDER_AGENT_NATIVE_FLOW_PARAM = "agentNativeFlow";
|
|
94
93
|
const BUILDER_AGENT_NATIVE_CONNECT_SOURCE_PARAM = "agentNativeConnectSource";
|
|
@@ -214,22 +213,8 @@ function hasSignedConnectToken(url) {
|
|
|
214
213
|
return false;
|
|
215
214
|
}
|
|
216
215
|
}
|
|
217
|
-
function hasSignedCallbackState(url) {
|
|
218
|
-
if (!url || typeof window === "undefined")
|
|
219
|
-
return false;
|
|
220
|
-
try {
|
|
221
|
-
const parsed = new URL(url, window.location.origin);
|
|
222
|
-
const redirectUrl = parsed.searchParams.get("redirect_url");
|
|
223
|
-
if (!redirectUrl)
|
|
224
|
-
return false;
|
|
225
|
-
return new URL(redirectUrl).searchParams.has(BUILDER_STATE_PARAM);
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
216
|
function isFreshSignedConnectUrl(url, fetchedAt) {
|
|
232
|
-
return (
|
|
217
|
+
return (hasSignedConnectToken(url) &&
|
|
233
218
|
typeof fetchedAt === "number" &&
|
|
234
219
|
Date.now() - fetchedAt < STATUS_CONNECT_URL_TTL_MS);
|
|
235
220
|
}
|
|
@@ -240,6 +225,9 @@ function isCurrentConnectError(error, startedAt) {
|
|
|
240
225
|
return true;
|
|
241
226
|
return typeof error.at !== "number" || error.at >= startedAt - 1000;
|
|
242
227
|
}
|
|
228
|
+
function isCodeChangeConfigured(status) {
|
|
229
|
+
return !!status?.privateKeyConfigured && !!status?.publicKeyConfigured;
|
|
230
|
+
}
|
|
243
231
|
function showBuilderConnectPopupPlaceholder(opened) {
|
|
244
232
|
// Keep opener attached: the Builder callback uses postMessage to notify the
|
|
245
233
|
// settings tab that the popup completed. We still hold the WindowProxy so the
|
|
@@ -379,6 +367,7 @@ export function openBuilderConnectPopup({ url, source = "builder_connect", flow,
|
|
|
379
367
|
export function useBuilderConnectFlow(opts = {}) {
|
|
380
368
|
const { enabled = true, popupUrl, trackingSource = "builder_connect_flow", trackingFlow, onConnected, } = opts;
|
|
381
369
|
const [configured, setConfigured] = useState(false);
|
|
370
|
+
const [codeChangeConfigured, setCodeChangeConfigured] = useState(false);
|
|
382
371
|
const [envManaged, setEnvManaged] = useState(false);
|
|
383
372
|
const [builderEnabled, setBuilderEnabled] = useState(false);
|
|
384
373
|
const [orgName, setOrgName] = useState(null);
|
|
@@ -445,6 +434,7 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
445
434
|
useEffect(() => {
|
|
446
435
|
if (!enabled) {
|
|
447
436
|
setConfigured(false);
|
|
437
|
+
setCodeChangeConfigured(false);
|
|
448
438
|
setEnvManaged(false);
|
|
449
439
|
setBuilderEnabled(false);
|
|
450
440
|
setOrgName(null);
|
|
@@ -470,9 +460,10 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
470
460
|
return;
|
|
471
461
|
setStatusResolved(true);
|
|
472
462
|
setConfigured(!!s.configured);
|
|
463
|
+
setCodeChangeConfigured(isCodeChangeConfigured(s));
|
|
473
464
|
setEnvManaged(!!s.envManaged);
|
|
474
465
|
setBuilderEnabled(!!s.builderEnabled);
|
|
475
|
-
const nextConnectUrl = s.
|
|
466
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
476
467
|
setStatusConnectUrl(nextConnectUrl);
|
|
477
468
|
statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;
|
|
478
469
|
const org = s.orgName ?? null;
|
|
@@ -548,11 +539,8 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
548
539
|
// server/package restart cannot leave the user with a stale signed state.
|
|
549
540
|
// Desktop keeps the direct path because the Electron shell owns the popup.
|
|
550
541
|
const signedPropUrl = hasSignedConnectToken(popupUrl) ? popupUrl : null;
|
|
551
|
-
const signedCliPropUrl = hasSignedCallbackState(popupUrl)
|
|
552
|
-
? popupUrl
|
|
553
|
-
: null;
|
|
554
542
|
const fallbackUrl = new URL(agentNativePath("/_agent-native/builder/connect"), origin).href;
|
|
555
|
-
const directUrl = cachedFreshUrl ??
|
|
543
|
+
const directUrl = cachedFreshUrl ?? signedPropUrl ?? fallbackUrl;
|
|
556
544
|
if (isAgentNativeDesktop()) {
|
|
557
545
|
const opened = openBuilderConnectPopup({
|
|
558
546
|
url: directUrl,
|
|
@@ -586,16 +574,17 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
586
574
|
setHasFetchedStatus(true);
|
|
587
575
|
setStatusResolved(true);
|
|
588
576
|
setConfigured(!!s.configured);
|
|
577
|
+
setCodeChangeConfigured(isCodeChangeConfigured(s));
|
|
589
578
|
setEnvManaged(!!s.envManaged);
|
|
590
579
|
setBuilderEnabled(!!s.builderEnabled);
|
|
591
|
-
const nextConnectUrl = s.
|
|
580
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
592
581
|
setStatusConnectUrl(nextConnectUrl);
|
|
593
582
|
statusConnectUrlAtRef.current = nextConnectUrl
|
|
594
583
|
? Date.now()
|
|
595
584
|
: null;
|
|
596
585
|
setOrgName(s.orgName ?? null);
|
|
597
586
|
}
|
|
598
|
-
const hostUrl = s?.
|
|
587
|
+
const hostUrl = s?.connectUrl ?? cachedFreshUrl ?? directUrl;
|
|
599
588
|
const trackedHostUrl = withBuilderConnectTrackingParams(hostUrl, {
|
|
600
589
|
source: clickTrackingSource,
|
|
601
590
|
flow: clickTrackingFlow,
|
|
@@ -625,9 +614,10 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
625
614
|
setHasFetchedStatus(true);
|
|
626
615
|
setStatusResolved(true);
|
|
627
616
|
setConfigured(!!s.configured);
|
|
617
|
+
setCodeChangeConfigured(isCodeChangeConfigured(s));
|
|
628
618
|
setEnvManaged(!!s.envManaged);
|
|
629
619
|
setBuilderEnabled(!!s.builderEnabled);
|
|
630
|
-
const nextConnectUrl = s.
|
|
620
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
631
621
|
setStatusConnectUrl(nextConnectUrl);
|
|
632
622
|
statusConnectUrlAtRef.current = nextConnectUrl
|
|
633
623
|
? Date.now()
|
|
@@ -638,12 +628,7 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
638
628
|
// already rendered into the CTA as a fallback. This avoids closing
|
|
639
629
|
// the popup when the refresh hits a transient 401/HTML/error
|
|
640
630
|
// response before the status cache has warmed.
|
|
641
|
-
const freshUrl = s?.
|
|
642
|
-
s?.connectUrl ??
|
|
643
|
-
cachedFreshUrl ??
|
|
644
|
-
signedCliPropUrl ??
|
|
645
|
-
signedPropUrl ??
|
|
646
|
-
fallbackUrl;
|
|
631
|
+
const freshUrl = s?.connectUrl ?? cachedFreshUrl ?? signedPropUrl ?? fallbackUrl;
|
|
647
632
|
if (!freshUrl) {
|
|
648
633
|
try {
|
|
649
634
|
opened.close();
|
|
@@ -691,9 +676,10 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
691
676
|
setStatusResolved(true);
|
|
692
677
|
if (s?.configured) {
|
|
693
678
|
setConfigured(true);
|
|
679
|
+
setCodeChangeConfigured(isCodeChangeConfigured(s));
|
|
694
680
|
setEnvManaged(!!s.envManaged);
|
|
695
681
|
setBuilderEnabled(!!s.builderEnabled);
|
|
696
|
-
const nextConnectUrl = s.
|
|
682
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
697
683
|
setStatusConnectUrl(nextConnectUrl);
|
|
698
684
|
statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;
|
|
699
685
|
const org = s.orgName ?? null;
|
|
@@ -775,9 +761,10 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
775
761
|
if (s) {
|
|
776
762
|
setStatusResolved(true);
|
|
777
763
|
setConfigured(false);
|
|
764
|
+
setCodeChangeConfigured(false);
|
|
778
765
|
setEnvManaged(!!s.envManaged);
|
|
779
766
|
setBuilderEnabled(!!s.builderEnabled);
|
|
780
|
-
const nextConnectUrl = s.
|
|
767
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
781
768
|
setStatusConnectUrl(nextConnectUrl);
|
|
782
769
|
statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;
|
|
783
770
|
setOrgName(s.orgName ?? null);
|
|
@@ -792,9 +779,10 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
792
779
|
setHasFetchedStatus(true);
|
|
793
780
|
setStatusResolved(true);
|
|
794
781
|
setConfigured(true);
|
|
782
|
+
setCodeChangeConfigured(isCodeChangeConfigured(s));
|
|
795
783
|
setEnvManaged(!!s.envManaged);
|
|
796
784
|
setBuilderEnabled(!!s.builderEnabled);
|
|
797
|
-
const nextConnectUrl = s.
|
|
785
|
+
const nextConnectUrl = s.connectUrl ?? null;
|
|
798
786
|
setStatusConnectUrl(nextConnectUrl);
|
|
799
787
|
statusConnectUrlAtRef.current = nextConnectUrl ? Date.now() : null;
|
|
800
788
|
const org = s.orgName ?? null;
|
|
@@ -850,6 +838,7 @@ export function useBuilderConnectFlow(opts = {}) {
|
|
|
850
838
|
}, [fetchStatus]);
|
|
851
839
|
return {
|
|
852
840
|
configured,
|
|
841
|
+
codeChangeConfigured,
|
|
853
842
|
statusResolved,
|
|
854
843
|
envManaged,
|
|
855
844
|
builderEnabled,
|
|
@@ -31,7 +31,7 @@ export function BuilderTranscriptionCta() {
|
|
|
31
31
|
// Env-managed mode counts as configured for the CTA — the deploy
|
|
32
32
|
// already routes transcription through Builder, no per-user prompt.
|
|
33
33
|
setConfigured(!!(s?.configured || s?.envManaged));
|
|
34
|
-
setConnectUrl(s?.
|
|
34
|
+
setConnectUrl(s?.connectUrl || null);
|
|
35
35
|
})
|
|
36
36
|
.catch(() => {
|
|
37
37
|
if (mountedRef.current)
|
|
@@ -6,3 +6,5 @@ export { escapePromptAttachmentAttribute, formatPromptWithAttachments, type Agen
|
|
|
6
6
|
export { CODE_AGENT_PERMISSION_MODES, appendCodeAgentTranscriptEvent, codeAgentRunArtifactsDir, codeAgentRunTranscriptPath, codeAgentRunsDir, codeAgentStoreRoot, codeAgentTranscriptsDir, createCodeAgentRunRecord, getCodeAgentRunRecord, getLastCodeAgentRunRecord, isActiveCodeAgentRun, listCodeAgentRunRecords, listCodeAgentTranscriptEvents, normalizeCodeAgentPermissionMode, queueCodeAgentFollowUp, updateCodeAgentRunRecord, type AppendCodeAgentTranscriptEventInput, type CodeAgentPermissionMode, type CodeAgentRunDetail, type CodeAgentRunProgress, type CodeAgentRunRecord, type CodeAgentRunStatus, type CodeAgentTranscriptEvent, type CodeAgentTranscriptEventKind, type CreateCodeAgentRunInput, type CodeAgentFollowUpMode, type QueueCodeAgentFollowUpInput, } from "../cli/code-agent-runs.js";
|
|
7
7
|
export { findProjectSlashCommand, isReservedProjectSlashCommandName, listProjectSkills, listProjectSlashCommands, listVisibleProjectSlashCommands, readProjectCodePack, renderProjectSlashCommandPrompt, type CodeAgentCodePack, type CodeAgentProjectCommand, type CodeAgentProjectSkill, type ReadProjectCodePackOptions, } from "../cli/code-agent-commands.js";
|
|
8
8
|
export { executeCodeAgentRun, executeExistingCodeAgentRun, executePendingCodeAgentApproval, type ExecuteCodeAgentRunOptions, } from "../cli/code-agent-executor.js";
|
|
9
|
+
export { codeAgentSchedulesPath, createCodeAgentSchedule, deleteCodeAgentSchedule, getCodeAgentSchedule, isCodeAgentScheduleDue, listCodeAgentSchedules, markCodeAgentScheduleRun, nextCodeAgentScheduleRunAt, updateCodeAgentSchedule, type CodeAgentScheduleRecord, type CodeAgentScheduleRunPatch, type CodeAgentScheduleScope, type CodeAgentScheduleStatus, type CreateCodeAgentScheduleInput, type UpdateCodeAgentScheduleInput, } from "../cli/code-agent-schedules.js";
|
|
10
|
+
export { createCodeAgentThread, listCodeAgentThreadSummaries, messageCodeAgentThread, type CodeAgentThreadSummary, type CreateCodeAgentThreadInput, type CreateCodeAgentThreadResult, type MessageCodeAgentThreadInput, type MessageCodeAgentThreadResult, } from "../cli/code-agent-collaboration.js";
|
|
@@ -6,3 +6,5 @@ export { escapePromptAttachmentAttribute, formatPromptWithAttachments, } from ".
|
|
|
6
6
|
export { CODE_AGENT_PERMISSION_MODES, appendCodeAgentTranscriptEvent, codeAgentRunArtifactsDir, codeAgentRunTranscriptPath, codeAgentRunsDir, codeAgentStoreRoot, codeAgentTranscriptsDir, createCodeAgentRunRecord, getCodeAgentRunRecord, getLastCodeAgentRunRecord, isActiveCodeAgentRun, listCodeAgentRunRecords, listCodeAgentTranscriptEvents, normalizeCodeAgentPermissionMode, queueCodeAgentFollowUp, updateCodeAgentRunRecord, } from "../cli/code-agent-runs.js";
|
|
7
7
|
export { findProjectSlashCommand, isReservedProjectSlashCommandName, listProjectSkills, listProjectSlashCommands, listVisibleProjectSlashCommands, readProjectCodePack, renderProjectSlashCommandPrompt, } from "../cli/code-agent-commands.js";
|
|
8
8
|
export { executeCodeAgentRun, executeExistingCodeAgentRun, executePendingCodeAgentApproval, } from "../cli/code-agent-executor.js";
|
|
9
|
+
export { codeAgentSchedulesPath, createCodeAgentSchedule, deleteCodeAgentSchedule, getCodeAgentSchedule, isCodeAgentScheduleDue, listCodeAgentSchedules, markCodeAgentScheduleRun, nextCodeAgentScheduleRunAt, updateCodeAgentSchedule, } from "../cli/code-agent-schedules.js";
|
|
10
|
+
export { createCodeAgentThread, listCodeAgentThreadSummaries, messageCodeAgentThread, } from "../cli/code-agent-collaboration.js";
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -29,6 +29,8 @@ export declare const LOCALIZATION_SETTING_KEY = "localization";
|
|
|
29
29
|
export declare const LOCALE_STORAGE_KEY = "agent-native:locale-preference";
|
|
30
30
|
export declare const LOCALE_HYDRATION_GLOBAL = "__AGENT_NATIVE_LOCALE__";
|
|
31
31
|
export declare const LOCALE_METADATA: Record<LocaleCode, LocaleMetadata>;
|
|
32
|
+
/** Return the short native language name used in compact locale pickers. */
|
|
33
|
+
export declare function localeDisplayName(locale: LocaleCode): string;
|
|
32
34
|
export declare function isLocaleCode(value: unknown): value is LocaleCode;
|
|
33
35
|
export declare function normalizeLocaleCode(value: unknown): LocaleCode | null;
|
|
34
36
|
export declare function normalizeLocalePreference(value: unknown): LocalePreference | null;
|
|
@@ -83,6 +83,11 @@ export const LOCALE_METADATA = {
|
|
|
83
83
|
dir: "rtl",
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
|
+
/** Return the short native language name used in compact locale pickers. */
|
|
87
|
+
export function localeDisplayName(locale) {
|
|
88
|
+
const nativeName = LOCALE_METADATA[locale]?.nativeName ?? locale;
|
|
89
|
+
return nativeName.split("(", 1)[0]?.trim() || nativeName;
|
|
90
|
+
}
|
|
86
91
|
const SUPPORTED_LOCALE_SET = new Set(SUPPORTED_LOCALES);
|
|
87
92
|
const CHINESE_LOCALE_ALIASES = {
|
|
88
93
|
"zh-cn": "zh-CN",
|
|
@@ -70,6 +70,7 @@ export declare class McpOAuthClientProvider implements OAuthClientProvider {
|
|
|
70
70
|
get savedCodeVerifierValue(): string | undefined;
|
|
71
71
|
get savedTokensValue(): OAuthTokens | undefined;
|
|
72
72
|
get savedClientInformation(): StoredOAuthClientInformation | undefined;
|
|
73
|
+
validateResourceURL(defaultResource: string | URL, advertised?: string): Promise<URL | undefined>;
|
|
73
74
|
}
|
|
74
75
|
export declare function startMcpOAuthAuthorization(options: McpOAuthProviderOptions & {
|
|
75
76
|
scope?: string;
|