@agent-native/core 0.120.0 → 0.120.2
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 +2 -2
- package/corpus/core/CHANGELOG.md +16 -0
- package/corpus/core/docs/content/extensions.mdx +23 -4
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/production-agent.ts +4 -0
- package/corpus/core/src/agent/run-manager.ts +36 -10
- package/corpus/core/src/agent/types.ts +2 -0
- package/corpus/core/src/client/MultiTabAssistantChat.tsx +45 -0
- package/corpus/core/src/client/extensions/ExtensionsListPage.tsx +16 -3
- package/corpus/core/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
- package/corpus/core/src/client/settings/SettingsPanel.tsx +10 -0
- package/corpus/core/src/client/use-chat-models.ts +45 -0
- package/corpus/core/src/deploy/build.ts +3 -0
- package/corpus/core/src/server/analytics.ts +164 -20
- package/corpus/core/src/server/auth.ts +17 -13
- package/corpus/core/src/server/better-auth-instance.ts +13 -1
- package/corpus/core/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/corpus/core/src/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/corpus/core/src/templates/chat/netlify.toml +1 -0
- package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/corpus/core/src/vite/client.ts +6 -0
- package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +27 -43
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +19 -8
- package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +2 -2
- package/corpus/templates/analytics/AGENTS.md +20 -8
- package/corpus/templates/analytics/actions/get-explorer-dashboard.ts +3 -0
- package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +140 -46
- package/corpus/templates/analytics/actions/migrate-analytics-artifacts.ts +48 -0
- package/corpus/templates/analytics/actions/save-analysis.ts +2 -3
- package/corpus/templates/analytics/actions/view-screen.ts +1 -1
- package/corpus/templates/analytics/app/components/dashboard/DashboardMetadata.tsx +77 -0
- package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +7 -1
- package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +1 -0
- package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +103 -502
- package/corpus/templates/analytics/app/global.css +30 -0
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +2 -2
- package/corpus/templates/analytics/app/i18n-data.ts +80 -0
- package/corpus/templates/analytics/app/pages/Agents.tsx +49 -2
- package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +54 -11
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +3 -53
- package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +23 -25
- package/corpus/templates/analytics/app/pages/analyses/AnalysisDetail.tsx +2 -2
- package/corpus/templates/analytics/app/routes/analyses._index.tsx +3 -2
- package/corpus/templates/analytics/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/analytics/changelog/2026-07-23-analytics-now-groups-saved-analyses-and-embedded-extensions-.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-dashboard-menus-show-who-created-and-last-updated-each-dashb.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-dashboard-usage-now-loads-reliably-for-organizations-with-ma.md +6 -0
- package/corpus/templates/analytics/changelog/2026-07-23-long-dashboard-building-requests-now-continue-without-stoppi.md +6 -0
- package/corpus/templates/analytics/netlify.toml +4 -0
- package/corpus/templates/analytics/server/db/schema.ts +4 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +0 -1
- package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +1 -0
- package/corpus/templates/analytics/server/lib/migrate-analytics-artifacts.ts +1062 -0
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +6 -52
- package/corpus/templates/analytics/server/plugins/core-routes.ts +1 -1
- package/corpus/templates/analytics/server/plugins/db.ts +10 -0
- package/corpus/templates/assets/actions/generate-image-batch.ts +36 -1
- package/corpus/templates/assets/actions/generate-image.ts +28 -1
- package/corpus/templates/assets/app/components/layout/Sidebar.tsx +47 -9
- package/corpus/templates/assets/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/assets/changelog/2026-07-23-assets-image-generation-now-recovers-after-a-completed-tool-.md +6 -0
- package/corpus/templates/assets/changelog/2026-07-23-new-chat-aligns-with-sidebar-controls.md +6 -0
- package/corpus/templates/assets/netlify.toml +1 -0
- package/corpus/templates/brain/app/components/layout/Sidebar.tsx +38 -8
- package/corpus/templates/brain/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/brain/netlify.toml +1 -0
- package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +43 -5
- package/corpus/templates/calendar/app/routes/_app.extensions._index.tsx +2 -16
- package/corpus/templates/calendar/netlify.toml +1 -0
- package/corpus/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/corpus/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/chat/netlify.toml +1 -0
- package/corpus/templates/clips/app/components/library/library-layout.tsx +52 -6
- package/corpus/templates/clips/app/routes/_app.extensions._index.tsx +2 -16
- package/corpus/templates/clips/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-23-meeting-recording-meters-and-dismissed-prompts.md +6 -0
- package/corpus/templates/clips/desktop/src/hooks/useMicMeter.ts +1 -1
- package/corpus/templates/clips/desktop/src/lib/meeting-notification-dismissal.ts +2 -0
- package/corpus/templates/clips/desktop/src/lib/voice-dictation.ts +1 -3
- package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +86 -0
- package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +24 -0
- package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +5 -69
- package/corpus/templates/clips/desktop/src/styles.css +35 -3
- package/corpus/templates/clips/desktop/src-tauri/src/adhoc_meetings_watcher.rs +13 -44
- package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +119 -17
- package/corpus/templates/clips/netlify.toml +1 -0
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +3 -7
- package/corpus/templates/content/app/routes/_app.extensions._index.tsx +2 -2
- package/corpus/templates/content/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/content/netlify.toml +1 -0
- package/corpus/templates/design/app/components/layout/Sidebar.tsx +55 -17
- package/corpus/templates/design/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/design/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/design/netlify.toml +1 -0
- package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -1
- package/corpus/templates/dispatch/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/dispatch/netlify.toml +1 -0
- package/corpus/templates/forms/.agents/skills/form-publishing/SKILL.md +9 -3
- package/corpus/templates/forms/AGENTS.md +11 -1
- package/corpus/templates/forms/README.md +24 -1
- package/corpus/templates/forms/actions/update-form.ts +12 -5
- package/corpus/templates/forms/app/components/builder/FieldPropertiesPanel.tsx +199 -1
- package/corpus/templates/forms/app/components/layout/Sidebar.tsx +41 -45
- package/corpus/templates/forms/app/i18n/en-US.ts +13 -1
- package/corpus/templates/forms/app/pages/FormBuilderPage.tsx +35 -4
- package/corpus/templates/forms/app/pages/FormFillPage.tsx +7 -16
- package/corpus/templates/forms/app/routes/_app.extensions._index.tsx +2 -2
- package/corpus/templates/forms/changelog/2026-07-23-agent-settings-are-clearly-labeled-manage-agent-in-the-sideb.md +6 -0
- package/corpus/templates/forms/changelog/2026-07-23-forms-can-branch-into-follow-up-questions-and-route-response.md +6 -0
- package/corpus/templates/forms/netlify.toml +1 -0
- package/corpus/templates/forms/server/handlers/submissions.ts +22 -31
- package/corpus/templates/forms/server/lib/integrations.ts +11 -2
- package/corpus/templates/forms/server/lib/public-form-ssr.ts +26 -5
- package/corpus/templates/forms/server/lib/validate-fields.ts +48 -11
- package/corpus/templates/forms/server/plugins/agent-chat.ts +1 -0
- package/corpus/templates/forms/shared/conditional.ts +67 -0
- package/corpus/templates/macros/app/components/layout/AppLayout.tsx +36 -5
- package/corpus/templates/macros/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/macros/netlify.toml +1 -0
- package/corpus/templates/mail/app/components/layout/AppLayout.tsx +0 -9
- package/corpus/templates/mail/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/mail/netlify.toml +1 -0
- package/corpus/templates/plan/app/components/layout/Sidebar.tsx +38 -5
- package/corpus/templates/plan/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/plan/netlify.toml +1 -0
- package/corpus/templates/slides/app/components/layout/Sidebar.tsx +47 -4
- package/corpus/templates/slides/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/slides/netlify.toml +1 -0
- package/corpus/templates/tasks/app/components/layout/Sidebar.tsx +37 -6
- package/corpus/templates/tasks/app/routes/extensions._index.tsx +2 -2
- package/corpus/templates/tasks/app/routes/settings.tsx +31 -0
- package/corpus/templates/tasks/netlify.toml +1 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +4 -0
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/run-manager.d.ts +9 -0
- package/dist/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +25 -10
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/agent/types.d.ts +2 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +35 -0
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts +5 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +5 -3
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/settings/ExtensionsSettingsContent.d.ts +2 -0
- package/dist/client/settings/ExtensionsSettingsContent.d.ts.map +1 -0
- package/dist/client/settings/ExtensionsSettingsContent.js +10 -0
- package/dist/client/settings/ExtensionsSettingsContent.js.map +1 -0
- package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
- package/dist/client/settings/SettingsPanel.js +10 -1
- package/dist/client/settings/SettingsPanel.js.map +1 -1
- package/dist/client/use-chat-models.d.ts +1 -0
- package/dist/client/use-chat-models.d.ts.map +1 -1
- package/dist/client/use-chat-models.js +33 -0
- package/dist/client/use-chat-models.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/deploy/build.js +1 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
- package/dist/provider-api/actions/provider-api.d.ts +2 -2
- package/dist/server/analytics.d.ts +17 -4
- package/dist/server/analytics.d.ts.map +1 -1
- package/dist/server/analytics.js +122 -17
- package/dist/server/analytics.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +5 -4
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts +8 -0
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +10 -1
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/dist/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/dist/templates/chat/netlify.toml +1 -0
- package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +2 -0
- package/dist/vite/client.js.map +1 -1
- package/docs/content/extensions.mdx +23 -4
- package/package.json +1 -1
- package/src/agent/production-agent.ts +4 -0
- package/src/agent/run-manager.ts +36 -10
- package/src/agent/types.ts +2 -0
- package/src/client/MultiTabAssistantChat.tsx +45 -0
- package/src/client/extensions/ExtensionsListPage.tsx +16 -3
- package/src/client/settings/ExtensionsSettingsContent.tsx +24 -0
- package/src/client/settings/SettingsPanel.tsx +10 -0
- package/src/client/use-chat-models.ts +45 -0
- package/src/deploy/build.ts +3 -0
- package/src/server/analytics.ts +164 -20
- package/src/server/auth.ts +17 -13
- package/src/server/better-auth-instance.ts +13 -1
- package/src/templates/chat/app/components/layout/Sidebar.tsx +35 -6
- package/src/templates/chat/app/routes/extensions._index.tsx +2 -2
- package/src/templates/chat/netlify.toml +1 -0
- package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +16 -0
- package/src/vite/client.ts +6 -0
- package/corpus/templates/analytics/app/components/layout/NewAnalysisDialog.tsx +0 -165
- package/corpus/templates/analytics/app/pages/analyses/AnalysesList.tsx +0 -175
|
@@ -510,19 +510,40 @@ function renderFormPage(
|
|
|
510
510
|
var condVal = el.dataset.condVal;
|
|
511
511
|
var depVal = getFieldValue(depId);
|
|
512
512
|
var show = true;
|
|
513
|
-
if (
|
|
513
|
+
if (Array.isArray(depVal)) {
|
|
514
|
+
if (op === "equals") show = depVal.length === 1 && depVal[0] === condVal;
|
|
515
|
+
else if (op === "not_equals") show = depVal.indexOf(condVal) < 0;
|
|
516
|
+
else if (op === "contains") show = depVal.indexOf(condVal) >= 0;
|
|
517
|
+
} else if (op === "equals") show = depVal === condVal;
|
|
514
518
|
else if (op === "not_equals") show = depVal !== condVal;
|
|
515
519
|
else if (op === "contains") show = depVal.indexOf(condVal) >= 0;
|
|
516
520
|
el.style.display = show ? "" : "none";
|
|
517
521
|
el.dataset.hidden = show ? "" : "1";
|
|
522
|
+
el.querySelectorAll("input, textarea, select, button").forEach(function(control) {
|
|
523
|
+
control.disabled = !show;
|
|
524
|
+
});
|
|
518
525
|
});
|
|
519
526
|
}
|
|
520
527
|
|
|
521
528
|
function getFieldValue(id) {
|
|
522
|
-
var
|
|
523
|
-
if (!
|
|
524
|
-
|
|
525
|
-
|
|
529
|
+
var controls = document.getElementsByName(id);
|
|
530
|
+
if (!controls.length) return "";
|
|
531
|
+
var first = controls[0];
|
|
532
|
+
if (first.type === "checkbox") {
|
|
533
|
+
if (controls.length > 1) {
|
|
534
|
+
return Array.prototype.map.call(controls, function(control) {
|
|
535
|
+
return control.checked ? control.value : "";
|
|
536
|
+
}).filter(Boolean);
|
|
537
|
+
}
|
|
538
|
+
return first.checked ? "true" : "false";
|
|
539
|
+
}
|
|
540
|
+
if (first.type === "radio") {
|
|
541
|
+
for (var i = 0; i < controls.length; i++) {
|
|
542
|
+
if (controls[i].checked) return controls[i].value || "";
|
|
543
|
+
}
|
|
544
|
+
return "";
|
|
545
|
+
}
|
|
546
|
+
return first.value || "";
|
|
526
547
|
}
|
|
527
548
|
|
|
528
549
|
document.getElementById("mainForm").addEventListener("input", updateVisibility);
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// runtime — an unrestricted id like `x" onfocus="alert(1)` would otherwise
|
|
5
5
|
// stored-XSS every anonymous submitter of a published form.
|
|
6
6
|
export const FIELD_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
7
|
+
const CONDITIONAL_OPERATORS = new Set(["equals", "not_equals", "contains"]);
|
|
7
8
|
|
|
8
9
|
export function assertValidFields(fields: unknown): void {
|
|
9
10
|
if (!Array.isArray(fields)) {
|
|
@@ -28,17 +29,30 @@ export function assertValidFields(fields: unknown): void {
|
|
|
28
29
|
seenIds.add(id);
|
|
29
30
|
|
|
30
31
|
const cond = f.conditional;
|
|
31
|
-
if (cond
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
if (cond !== undefined) {
|
|
33
|
+
if (cond == null || typeof cond !== "object") {
|
|
34
|
+
throw new Error(`field #${idx + 1} conditional must be an object`);
|
|
35
|
+
}
|
|
36
|
+
const condition = cond as Record<string, unknown>;
|
|
37
|
+
const condFieldId = condition.fieldId;
|
|
38
|
+
if (
|
|
39
|
+
typeof condFieldId !== "string" ||
|
|
40
|
+
!FIELD_ID_PATTERN.test(condFieldId)
|
|
41
|
+
) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`field #${idx + 1} conditional.fieldId ${JSON.stringify(condFieldId)} is invalid — must match ${FIELD_ID_PATTERN.source}`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (
|
|
47
|
+
typeof condition.operator !== "string" ||
|
|
48
|
+
!CONDITIONAL_OPERATORS.has(condition.operator)
|
|
49
|
+
) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`field #${idx + 1} conditional.operator must be equals, not_equals, or contains`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
if (typeof condition.value !== "string") {
|
|
55
|
+
throw new Error(`field #${idx + 1} conditional.value must be a string`);
|
|
42
56
|
}
|
|
43
57
|
}
|
|
44
58
|
|
|
@@ -69,4 +83,27 @@ export function assertValidFields(fields: unknown): void {
|
|
|
69
83
|
}
|
|
70
84
|
}
|
|
71
85
|
}
|
|
86
|
+
|
|
87
|
+
const fieldIndexes = new Map(
|
|
88
|
+
fields.map((field, index) => [
|
|
89
|
+
(field as Record<string, unknown>).id,
|
|
90
|
+
index,
|
|
91
|
+
]),
|
|
92
|
+
);
|
|
93
|
+
for (const [idx, field] of fields.entries()) {
|
|
94
|
+
const condition = (field as Record<string, unknown>).conditional;
|
|
95
|
+
if (!condition || typeof condition !== "object") continue;
|
|
96
|
+
const condFieldId = (condition as Record<string, unknown>).fieldId;
|
|
97
|
+
const sourceIndex = fieldIndexes.get(condFieldId);
|
|
98
|
+
if (sourceIndex === undefined) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`field #${idx + 1} conditional.fieldId ${JSON.stringify(condFieldId)} does not reference a field in this form`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (sourceIndex >= idx) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
`field #${idx + 1} conditional.fieldId must reference an earlier field`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
72
109
|
}
|
|
@@ -18,6 +18,7 @@ Core rules:
|
|
|
18
18
|
- When the user asks for an anonymous feedback form or survey, create the complete form atomically with \`status: "published"\`, then return the exact public response URL from the successful action result. Do not return only the private editor link, and do not claim it is live without verifying the saved status and fields.
|
|
19
19
|
- Use \`preview-form\` when the user asks about a form's setup, fields, configuration, publish state, or response count. It renders a native chat summary.
|
|
20
20
|
- When the user wants email notifications for new responses, set \`settings.emailOnNewResponses: true\` with \`create-form\` or \`update-form\`; notifications go to the form owner's account email.
|
|
21
|
+
- When the user wants Slack, Discord, Google Sheets, or webhook notifications, explain that Forms already supports them from the form builder's Integrations tab and navigate there with \`tab: "integrations"\`. Slack uses an Incoming Webhook URL; Google Sheets uses a deployed Apps Script \`/exec\` URL that parses \`e.postData.contents\`. Do not redirect users to the managed Messaging integration for these form destinations.
|
|
21
22
|
- Use \`response-insights\` for response analytics. Do not invent SQL or fake chart data. Pass \`displayMode: "chart"\` for chart-only requests, \`displayMode: "table"\` only when the user asks for a table/rows, and \`displayMode: "insights"\` only for combined dashboards or reports.
|
|
22
23
|
- Use \`list-responses\` and \`export-responses\` for response data review and export. When the user asks to see, open, or view all responses for a form, call \`navigate\` with \`view: "responses"\` instead of listing rows in chat.
|
|
23
24
|
- Use \`navigate\` to open focused workspace views such as the forms list, builder, published preview, responses, response insights, extensions, or team/settings views. For builder sub-tabs, pass \`view=form\`, the form ID, and \`tab=edit|responses|settings|integrations\`.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { FormField } from "./types.js";
|
|
2
|
+
|
|
3
|
+
export function conditionalValue(value: unknown): string {
|
|
4
|
+
if (Array.isArray(value)) return value.map(conditionalValue).join(",");
|
|
5
|
+
if (value === true) return "true";
|
|
6
|
+
if (value === false) return "false";
|
|
7
|
+
if (value == null) return "";
|
|
8
|
+
return String(value);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function isConditionalFieldVisible(
|
|
12
|
+
field: Pick<FormField, "conditional">,
|
|
13
|
+
values: Record<string, unknown>,
|
|
14
|
+
): boolean {
|
|
15
|
+
const condition = field.conditional;
|
|
16
|
+
if (!condition) return true;
|
|
17
|
+
|
|
18
|
+
if (
|
|
19
|
+
typeof condition.fieldId !== "string" ||
|
|
20
|
+
typeof condition.value !== "string"
|
|
21
|
+
) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const rawValue = values[condition.fieldId];
|
|
26
|
+
if (Array.isArray(rawValue)) {
|
|
27
|
+
const selectedValues = rawValue.map(conditionalValue);
|
|
28
|
+
switch (condition.operator) {
|
|
29
|
+
case "equals":
|
|
30
|
+
return (
|
|
31
|
+
selectedValues.length === 1 && selectedValues[0] === condition.value
|
|
32
|
+
);
|
|
33
|
+
case "not_equals":
|
|
34
|
+
return !selectedValues.includes(condition.value);
|
|
35
|
+
case "contains":
|
|
36
|
+
return selectedValues.includes(condition.value);
|
|
37
|
+
default:
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const currentValue = conditionalValue(rawValue);
|
|
43
|
+
switch (condition.operator) {
|
|
44
|
+
case "equals":
|
|
45
|
+
return currentValue === condition.value;
|
|
46
|
+
case "not_equals":
|
|
47
|
+
return currentValue !== condition.value;
|
|
48
|
+
case "contains":
|
|
49
|
+
return currentValue.includes(condition.value);
|
|
50
|
+
default:
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function sanitizeConditionalValues(
|
|
56
|
+
fields: FormField[],
|
|
57
|
+
values: Record<string, unknown>,
|
|
58
|
+
): Record<string, unknown> {
|
|
59
|
+
const visibleValues: Record<string, unknown> = {};
|
|
60
|
+
for (const field of fields) {
|
|
61
|
+
if (!isConditionalFieldVisible(field, visibleValues)) continue;
|
|
62
|
+
if (Object.prototype.hasOwnProperty.call(values, field.id)) {
|
|
63
|
+
visibleValues[field.id] = values[field.id];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return visibleValues;
|
|
67
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { AgentSidebar } from "@agent-native/core/client/agent-chat";
|
|
2
2
|
import { agentNativePath, appPath } from "@agent-native/core/client/api-path";
|
|
3
3
|
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
4
|
-
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
5
4
|
import { useT } from "@agent-native/core/client/i18n";
|
|
6
5
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
7
6
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
@@ -39,6 +38,9 @@ import { Header } from "./Header";
|
|
|
39
38
|
const navItems = [
|
|
40
39
|
{ icon: IconFlame, labelKey: "navigation.entry", href: "/" },
|
|
41
40
|
{ icon: IconChartBar, labelKey: "navigation.analytics", href: "/analytics" },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
const bottomNavItems = [
|
|
42
44
|
{ icon: IconHierarchy2, labelKey: "settings.agentTitle", href: "/agent" },
|
|
43
45
|
{ icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
|
|
44
46
|
];
|
|
@@ -287,12 +289,41 @@ function SidebarContent({
|
|
|
287
289
|
})}
|
|
288
290
|
</nav>
|
|
289
291
|
|
|
292
|
+
<nav className="grid shrink-0 gap-1 px-2 py-1">
|
|
293
|
+
{bottomNavItems.map((item) => {
|
|
294
|
+
const Icon = item.icon;
|
|
295
|
+
const label = t(item.labelKey);
|
|
296
|
+
const isActive = pathname.startsWith(item.href);
|
|
297
|
+
const link = (
|
|
298
|
+
<Link
|
|
299
|
+
key={item.href}
|
|
300
|
+
to={item.href}
|
|
301
|
+
aria-label={collapsed ? label : undefined}
|
|
302
|
+
className={cn(
|
|
303
|
+
"flex h-9 items-center rounded-lg text-sm transition-colors",
|
|
304
|
+
collapsed ? "justify-center px-0" : "gap-3 px-3",
|
|
305
|
+
isActive
|
|
306
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
307
|
+
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
308
|
+
)}
|
|
309
|
+
>
|
|
310
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
311
|
+
{!collapsed && label}
|
|
312
|
+
</Link>
|
|
313
|
+
);
|
|
314
|
+
return collapsed ? (
|
|
315
|
+
<Tooltip key={item.href}>
|
|
316
|
+
<TooltipTrigger asChild>{link}</TooltipTrigger>
|
|
317
|
+
<TooltipContent side="right">{label}</TooltipContent>
|
|
318
|
+
</Tooltip>
|
|
319
|
+
) : (
|
|
320
|
+
link
|
|
321
|
+
);
|
|
322
|
+
})}
|
|
323
|
+
</nav>
|
|
324
|
+
|
|
290
325
|
{!collapsed && (
|
|
291
326
|
<>
|
|
292
|
-
<div className="px-2 py-2">
|
|
293
|
-
<ExtensionsSidebarSection />
|
|
294
|
-
</div>
|
|
295
|
-
|
|
296
327
|
<div className="space-y-2 px-3 py-2">
|
|
297
328
|
<DevDatabaseLink />
|
|
298
329
|
<FeedbackButton />
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Navigate } from "react-router";
|
|
2
2
|
|
|
3
3
|
import messages from "@/i18n/en-US";
|
|
4
4
|
|
|
@@ -7,5 +7,5 @@ export function meta() {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export default function ExtensionsRoute() {
|
|
10
|
-
return <
|
|
10
|
+
return <Navigate to="/settings#extensions" replace />;
|
|
11
11
|
}
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
import { agentNativePath } from "@agent-native/core/client/api-path";
|
|
6
6
|
import { appApiPath } from "@agent-native/core/client/api-path";
|
|
7
7
|
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
8
|
-
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
9
8
|
import { useT } from "@agent-native/core/client/i18n";
|
|
10
9
|
import { InvitationBanner, OrgSwitcher } from "@agent-native/core/client/org";
|
|
11
10
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
@@ -1740,10 +1739,6 @@ function AppLayoutInner({ children }: AppLayoutProps) {
|
|
|
1740
1739
|
</div>
|
|
1741
1740
|
|
|
1742
1741
|
<div className="shrink-0">
|
|
1743
|
-
<div className="px-2 py-1">
|
|
1744
|
-
<ExtensionsSidebarSection />
|
|
1745
|
-
</div>
|
|
1746
|
-
|
|
1747
1742
|
<div className="px-3 py-2">
|
|
1748
1743
|
<OrgSwitcher />
|
|
1749
1744
|
</div>
|
|
@@ -2112,10 +2107,6 @@ function StandardLayout({ children }: AppLayoutProps) {
|
|
|
2112
2107
|
</div>
|
|
2113
2108
|
|
|
2114
2109
|
<div className="shrink-0">
|
|
2115
|
-
<div className="px-2 py-1">
|
|
2116
|
-
<ExtensionsSidebarSection />
|
|
2117
|
-
</div>
|
|
2118
|
-
|
|
2119
2110
|
<div className="px-3 py-2">
|
|
2120
2111
|
<OrgSwitcher />
|
|
2121
2112
|
</div>
|
|
@@ -9,7 +9,6 @@ import { useCodeMode } from "@agent-native/core/client/agent-chat";
|
|
|
9
9
|
import { agentNativePath, appPath } from "@agent-native/core/client/api-path";
|
|
10
10
|
import { PromptComposer } from "@agent-native/core/client/composer";
|
|
11
11
|
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
12
|
-
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
13
12
|
import { useSession } from "@agent-native/core/client/hooks";
|
|
14
13
|
import { useT } from "@agent-native/core/client/i18n";
|
|
15
14
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
@@ -73,6 +72,9 @@ function buildBrandingCustomizationMessage(request: string) {
|
|
|
73
72
|
const navItems = [
|
|
74
73
|
{ icon: IconMessageCircle, labelKey: "navigation.ask", href: "/" },
|
|
75
74
|
{ icon: IconClipboardCheck, labelKey: "navigation.plan", href: "/plans" },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
const bottomNavItems = [
|
|
76
78
|
{ icon: IconHierarchy2, labelKey: "settings.agentTitle", href: "/agent" },
|
|
77
79
|
{ icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
|
|
78
80
|
];
|
|
@@ -638,12 +640,43 @@ export function Sidebar({
|
|
|
638
640
|
})}
|
|
639
641
|
</nav>
|
|
640
642
|
|
|
643
|
+
<nav className="grid shrink-0 gap-1 px-2 py-1">
|
|
644
|
+
{bottomNavItems.map((item) => {
|
|
645
|
+
const Icon = item.icon;
|
|
646
|
+
const isActive = location.pathname.startsWith(item.href);
|
|
647
|
+
const link = (
|
|
648
|
+
<Link
|
|
649
|
+
to={item.href}
|
|
650
|
+
className={cn(
|
|
651
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm transition-colors",
|
|
652
|
+
isActive
|
|
653
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
654
|
+
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
655
|
+
collapsed && "justify-center gap-0 px-0",
|
|
656
|
+
)}
|
|
657
|
+
aria-label={collapsed ? t(item.labelKey) : undefined}
|
|
658
|
+
>
|
|
659
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
660
|
+
{collapsed ? (
|
|
661
|
+
<span className="sr-only">{t(item.labelKey)}</span>
|
|
662
|
+
) : (
|
|
663
|
+
t(item.labelKey)
|
|
664
|
+
)}
|
|
665
|
+
</Link>
|
|
666
|
+
);
|
|
667
|
+
return collapsed ? (
|
|
668
|
+
<Tooltip key={item.href}>
|
|
669
|
+
<TooltipTrigger asChild>{link}</TooltipTrigger>
|
|
670
|
+
<TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
|
|
671
|
+
</Tooltip>
|
|
672
|
+
) : (
|
|
673
|
+
<div key={item.href}>{link}</div>
|
|
674
|
+
);
|
|
675
|
+
})}
|
|
676
|
+
</nav>
|
|
677
|
+
|
|
641
678
|
{!collapsed && session ? (
|
|
642
679
|
<>
|
|
643
|
-
<div className="px-2 py-2">
|
|
644
|
-
<ExtensionsSidebarSection />
|
|
645
|
-
</div>
|
|
646
|
-
|
|
647
680
|
<div className="space-y-2 px-3 py-2">
|
|
648
681
|
<DevDatabaseLink />
|
|
649
682
|
<div className="flex items-center justify-end gap-1">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Navigate } from "react-router";
|
|
2
2
|
|
|
3
3
|
import { APP_TITLE } from "@/lib/app-config";
|
|
4
4
|
|
|
@@ -7,5 +7,5 @@ export function meta() {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export default function ExtensionsRoute() {
|
|
10
|
-
return <
|
|
10
|
+
return <Navigate to="/settings#extensions" replace />;
|
|
11
11
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { appPath } from "@agent-native/core/client/api-path";
|
|
2
2
|
import { DevDatabaseLink } from "@agent-native/core/client/db-admin";
|
|
3
|
-
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
4
3
|
import { useT } from "@agent-native/core/client/i18n";
|
|
5
4
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
6
5
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
@@ -28,6 +27,9 @@ const navItems = [
|
|
|
28
27
|
labelKey: "navigation.designSystems",
|
|
29
28
|
href: "/design-systems",
|
|
30
29
|
},
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const bottomNavItems = [
|
|
31
33
|
{ icon: IconHierarchy2, labelKey: "settings.agentTitle", href: "/agent" },
|
|
32
34
|
{ icon: IconSettings, labelKey: "navigation.settings", href: "/settings" },
|
|
33
35
|
];
|
|
@@ -92,6 +94,29 @@ export function Sidebar({ collapsed, onToggleCollapsed }: SidebarProps) {
|
|
|
92
94
|
);
|
|
93
95
|
})}
|
|
94
96
|
</nav>
|
|
97
|
+
<nav className="flex shrink-0 flex-col items-center gap-1 py-1">
|
|
98
|
+
{bottomNavItems.map((item) => {
|
|
99
|
+
const Icon = item.icon;
|
|
100
|
+
return (
|
|
101
|
+
<Tooltip key={item.href} delayDuration={0}>
|
|
102
|
+
<TooltipTrigger asChild>
|
|
103
|
+
<Link
|
|
104
|
+
to={item.href}
|
|
105
|
+
aria-label={t(item.labelKey)}
|
|
106
|
+
className={cn(
|
|
107
|
+
"flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
108
|
+
isItemActive(item.href) &&
|
|
109
|
+
"bg-sidebar-accent text-sidebar-accent-foreground",
|
|
110
|
+
)}
|
|
111
|
+
>
|
|
112
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
113
|
+
</Link>
|
|
114
|
+
</TooltipTrigger>
|
|
115
|
+
<TooltipContent side="right">{t(item.labelKey)}</TooltipContent>
|
|
116
|
+
</Tooltip>
|
|
117
|
+
);
|
|
118
|
+
})}
|
|
119
|
+
</nav>
|
|
95
120
|
</aside>
|
|
96
121
|
);
|
|
97
122
|
}
|
|
@@ -156,9 +181,27 @@ export function Sidebar({ collapsed, onToggleCollapsed }: SidebarProps) {
|
|
|
156
181
|
</nav>
|
|
157
182
|
|
|
158
183
|
<div className="mt-auto shrink-0">
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
184
|
+
<nav className="space-y-1 px-2 py-1">
|
|
185
|
+
{bottomNavItems.map((item) => {
|
|
186
|
+
const Icon = item.icon;
|
|
187
|
+
const isActive = isItemActive(item.href);
|
|
188
|
+
return (
|
|
189
|
+
<Link
|
|
190
|
+
key={item.href}
|
|
191
|
+
to={item.href}
|
|
192
|
+
className={cn(
|
|
193
|
+
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm",
|
|
194
|
+
isActive
|
|
195
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
196
|
+
: "text-muted-foreground hover:bg-sidebar-accent/50 hover:text-foreground",
|
|
197
|
+
)}
|
|
198
|
+
>
|
|
199
|
+
<Icon className="h-4 w-4 shrink-0" />
|
|
200
|
+
{t(item.labelKey)}
|
|
201
|
+
</Link>
|
|
202
|
+
);
|
|
203
|
+
})}
|
|
204
|
+
</nav>
|
|
162
205
|
|
|
163
206
|
<div className="px-3 py-2">
|
|
164
207
|
<OrgSwitcher />
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { appPath } from "@agent-native/core/client/api-path";
|
|
2
|
-
import { ExtensionsSidebarSection } from "@agent-native/core/client/extensions";
|
|
3
2
|
import { useT } from "@agent-native/core/client/i18n";
|
|
4
3
|
import { OrgSwitcher } from "@agent-native/core/client/org";
|
|
5
4
|
import { FeedbackButton } from "@agent-native/core/client/ui";
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
IconInbox,
|
|
10
9
|
IconLayoutSidebarLeftCollapse,
|
|
11
10
|
IconLayoutSidebarLeftExpand,
|
|
11
|
+
IconSettings,
|
|
12
12
|
} from "@tabler/icons-react";
|
|
13
13
|
import { Link, useLocation } from "react-router";
|
|
14
14
|
|
|
@@ -26,6 +26,10 @@ const NAV_ITEMS = [
|
|
|
26
26
|
{ icon: IconForms, labelKey: "sidebar.navFields", href: "/fields" },
|
|
27
27
|
];
|
|
28
28
|
|
|
29
|
+
const BOTTOM_NAV_ITEMS = [
|
|
30
|
+
{ icon: IconSettings, labelKey: "header.pageSettings", href: "/settings" },
|
|
31
|
+
];
|
|
32
|
+
|
|
29
33
|
interface SidebarProps {
|
|
30
34
|
collapsed?: boolean;
|
|
31
35
|
collapsible?: boolean;
|
|
@@ -165,11 +169,38 @@ export function Sidebar({
|
|
|
165
169
|
collapsed && "border-t border-sidebar-border py-2",
|
|
166
170
|
)}
|
|
167
171
|
>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
<nav
|
|
173
|
+
className={cn(
|
|
174
|
+
"grid gap-1",
|
|
175
|
+
collapsed
|
|
176
|
+
? "px-1 py-1"
|
|
177
|
+
: "border-t border-sidebar-border px-3 py-2",
|
|
178
|
+
)}
|
|
179
|
+
>
|
|
180
|
+
{BOTTOM_NAV_ITEMS.map((item) => {
|
|
181
|
+
const Icon = item.icon;
|
|
182
|
+
const isActive = location.pathname.startsWith(item.href);
|
|
183
|
+
return (
|
|
184
|
+
<Link
|
|
185
|
+
key={item.href}
|
|
186
|
+
to={item.href}
|
|
187
|
+
aria-label={collapsed ? t(item.labelKey) : undefined}
|
|
188
|
+
className={cn(
|
|
189
|
+
"flex items-center rounded-md text-sm",
|
|
190
|
+
collapsed ? "h-9 justify-center px-0" : "gap-3 px-3 py-2",
|
|
191
|
+
isActive
|
|
192
|
+
? "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
193
|
+
: "text-sidebar-foreground hover:bg-sidebar-accent/65 hover:text-sidebar-accent-foreground",
|
|
194
|
+
)}
|
|
195
|
+
>
|
|
196
|
+
<Icon className="size-4 shrink-0" />
|
|
197
|
+
<span className={collapsed ? "sr-only" : "truncate"}>
|
|
198
|
+
{t(item.labelKey)}
|
|
199
|
+
</span>
|
|
200
|
+
</Link>
|
|
201
|
+
);
|
|
202
|
+
})}
|
|
203
|
+
</nav>
|
|
173
204
|
|
|
174
205
|
<div
|
|
175
206
|
className={cn(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Navigate } from "react-router";
|
|
2
2
|
|
|
3
3
|
import messages from "@/i18n/en-US";
|
|
4
4
|
import { APP_TITLE } from "@/lib/app-config";
|
|
@@ -8,5 +8,5 @@ export function meta() {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export default function ExtensionsRoute() {
|
|
11
|
-
return <
|
|
11
|
+
return <Navigate to="/settings#extensions" replace />;
|
|
12
12
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import {
|
|
3
|
+
SettingsTabsPage,
|
|
4
|
+
useAgentSettingsTabs,
|
|
5
|
+
} from "@agent-native/core/client/settings";
|
|
6
|
+
import { useSetPageTitle } from "@agent-native/toolkit/app-shell";
|
|
7
|
+
|
|
8
|
+
import { APP_TITLE } from "@/lib/app-config";
|
|
9
|
+
|
|
10
|
+
export function meta() {
|
|
11
|
+
return [{ title: `Settings - ${APP_TITLE}` }];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default function SettingsRoute() {
|
|
15
|
+
const t = useT();
|
|
16
|
+
const agentSettingsTabs = useAgentSettingsTabs();
|
|
17
|
+
useSetPageTitle(t("header.pageSettings"));
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<SettingsTabsPage
|
|
21
|
+
extraTabs={agentSettingsTabs}
|
|
22
|
+
general={
|
|
23
|
+
<div className="mx-auto w-full max-w-2xl">
|
|
24
|
+
<p className="text-sm leading-6 text-muted-foreground">
|
|
25
|
+
{t("header.pageSettings")}
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|