@agent-native/core 0.147.0 → 0.148.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/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/analytics/DEVELOPING.md +50 -3
- package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
- package/corpus/templates/analytics/app/i18n/index.ts +14 -29
- package/corpus/templates/analytics/app/i18n-data.ts +10 -10
- package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
- package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
- package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
- package/corpus/templates/analytics/server/db/schema.ts +23 -0
- package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
- package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
- package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
- package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
- package/corpus/templates/analytics/server/plugins/db.ts +42 -0
- package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/assets/app/i18n/index.ts +14 -29
- package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/brain/app/i18n/index.ts +14 -29
- package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/chat/app/i18n/index.ts +14 -29
- package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
- package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
- package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
- package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
- package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
- package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
- package/corpus/templates/clips/desktop/src/app.tsx +1 -1
- package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/content/app/i18n/index.ts +14 -29
- package/corpus/templates/crm/app/i18n/index.ts +14 -29
- package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/design/actions/import-code.ts +2 -43
- package/corpus/templates/design/app/i18n/index.ts +14 -29
- package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
- package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/factory/AGENTS.md +40 -49
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
- package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
- package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
- package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
- package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
- package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
- package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
- package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
- package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
- package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
- package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
- package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
- package/corpus/templates/factory/app/routes/factory.tsx +95 -42
- package/corpus/templates/factory/server/db/schema.ts +37 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
- package/corpus/templates/factory/server/triage/audit.ts +79 -0
- package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/forms/app/i18n/index.ts +14 -29
- package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/macros/app/i18n/index.ts +14 -29
- package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/mail/app/i18n/index.ts +14 -29
- package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
- package/corpus/templates/plan/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
- package/corpus/templates/slides/actions/import-code.ts +2 -43
- package/corpus/templates/slides/app/i18n/index.ts +14 -29
- package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
- package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
- package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
- package/corpus/templates/tasks/app/i18n/index.ts +14 -29
- package/dist/agent/engine/ai-sdk-engine.js +2 -1
- package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
- package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
- package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
- package/dist/agent/engine/provider-endpoint-validation.js +26 -0
- package/dist/agent/engine/provider-env-vars.d.ts +1 -1
- package/dist/agent/engine/provider-env-vars.js +1 -1
- package/dist/agent/engine/registry.d.ts +8 -6
- package/dist/agent/engine/registry.js +37 -24
- package/dist/agent/tool-search.d.ts +1 -0
- package/dist/agent/tool-search.js +17 -1
- package/dist/automations/service.js +4 -10
- package/dist/brand-kit/brand-signals.d.ts +13 -0
- package/dist/brand-kit/brand-signals.js +15 -0
- package/dist/brand-kit/index.d.ts +2 -2
- package/dist/brand-kit/index.js +1 -1
- package/dist/cli/plan-blocks.d.ts +3 -18
- package/dist/cli/plan-blocks.js +2 -95
- package/dist/cli/plan-publish-store.d.ts +2 -61
- package/dist/cli/plan-publish-store.js +2 -127
- package/dist/cli/skills-content/connection.d.ts +1 -1
- package/dist/cli/skills-content/connection.js +1 -52
- package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
- package/dist/cli/skills-content/visual-recap-skill.js +1 -553
- package/dist/client/agent-engine-key.d.ts +14 -4
- package/dist/client/agent-engine-key.js +51 -5
- package/dist/client/agent-provider-catalog.d.ts +20 -0
- package/dist/client/agent-provider-catalog.js +100 -0
- package/dist/client/blocks/index.d.ts +1 -0
- package/dist/client/blocks/index.js +1 -0
- package/dist/client/chat/run-recovery.js +4 -48
- package/dist/client/chat-first.js +4 -3
- package/dist/client/i18n.d.ts +14 -0
- package/dist/client/i18n.js +18 -0
- package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
- package/dist/client/settings/ProviderSetupForm.js +145 -0
- package/dist/client/settings/SettingsPanel.js +52 -49
- package/dist/client/settings/index.d.ts +2 -0
- package/dist/client/settings/index.js +2 -0
- package/dist/coding-tools/run-code.d.ts +5 -0
- package/dist/coding-tools/run-code.js +196 -36
- package/dist/coding-tools/tool-orchestration.d.ts +10 -0
- package/dist/coding-tools/tool-orchestration.js +107 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/jobs/frontmatter.d.ts +9 -0
- package/dist/jobs/frontmatter.js +16 -0
- package/dist/jobs/scheduler.js +8 -8
- package/dist/jobs/tools.d.ts +1 -1
- package/dist/jobs/tools.js +2 -7
- package/dist/localization/default-messages.d.ts +20 -0
- package/dist/localization/default-messages.js +25 -5
- package/dist/observability/routes.d.ts +3 -3
- package/dist/onboarding/app-profile.js +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
- package/dist/server/agent-chat/run-code-tools.js +3 -1
- package/dist/server/agent-chat-plugin.js +6 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.js +43 -12
- package/dist/server/agents-bundle.js +2 -1
- package/dist/server/auth.js +21 -5
- package/dist/server/credential-provider.js +1 -0
- package/dist/server/design-token-utils.d.ts +18 -0
- package/dist/server/design-token-utils.js +31 -0
- package/dist/server/onboarding-html.js +22 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/chat/app/i18n/index.ts +14 -29
- package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/templates/default/app/i18n/index.ts +14 -29
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/dist/triggers/dispatcher.js +1 -8
- package/docs/content/environment-variables.mdx +39 -38
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/chat/app/i18n/index.ts +14 -29
- package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
- package/src/templates/default/app/i18n/index.ts +14 -29
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
- package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
- package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
|
@@ -154,6 +154,31 @@ const messages = {
|
|
|
154
154
|
metricRuns: "Runs",
|
|
155
155
|
rulesTab: "Rules",
|
|
156
156
|
automationsTab: "Automations",
|
|
157
|
+
auditTab: "Audit",
|
|
158
|
+
auditTitle: "Run audit",
|
|
159
|
+
auditDescription:
|
|
160
|
+
"See exactly which sources the agent inspected, what it decided, and which actions it took.",
|
|
161
|
+
auditRefresh: "Refresh",
|
|
162
|
+
auditLoadError: "Could not load the run audit.",
|
|
163
|
+
auditEmpty: "No automation runs have been recorded yet.",
|
|
164
|
+
auditRuns: "Recent runs",
|
|
165
|
+
auditEventsShort: "events",
|
|
166
|
+
auditActionsShort: "actions",
|
|
167
|
+
auditRunDetail: "Evidence and decisions recorded for this run.",
|
|
168
|
+
auditStarted: "Started",
|
|
169
|
+
auditFinished: "Finished",
|
|
170
|
+
auditItems: "Items",
|
|
171
|
+
auditRunError: "Run error",
|
|
172
|
+
auditEvidence: "Evidence and decisions",
|
|
173
|
+
auditNoEvents:
|
|
174
|
+
"No item-level audit events were recorded. Open the agent thread for the full trace.",
|
|
175
|
+
auditOpenThread: "Open thread",
|
|
176
|
+
auditOpenItem: "Open item",
|
|
177
|
+
auditOpenSource: "Open source",
|
|
178
|
+
auditInternal: "Factory",
|
|
179
|
+
auditClearBug: "Clear bug",
|
|
180
|
+
auditUxImpact: "UX impact",
|
|
181
|
+
auditOwnerArea: "Owner area",
|
|
157
182
|
automationsTitle: "Automations",
|
|
158
183
|
automationsDescription: "Schedule and run Factory prompts.",
|
|
159
184
|
automationsLoading: "Loading automations...",
|
|
@@ -10,10 +10,12 @@ import {
|
|
|
10
10
|
IconLoader2,
|
|
11
11
|
IconPlayerPlay,
|
|
12
12
|
IconPlus,
|
|
13
|
+
IconRefresh,
|
|
13
14
|
} from "@tabler/icons-react";
|
|
14
15
|
import { useEffect, useMemo, useState } from "react";
|
|
15
16
|
import { useSearchParams } from "react-router";
|
|
16
17
|
|
|
18
|
+
import { FactoryAuditView } from "@/components/factory/FactoryAuditView";
|
|
17
19
|
import {
|
|
18
20
|
FactoryCanvas,
|
|
19
21
|
type FactoryCanvasEdge,
|
|
@@ -111,7 +113,13 @@ type TriageConfig = {
|
|
|
111
113
|
};
|
|
112
114
|
|
|
113
115
|
type Verdict = "correct" | "incorrect" | "uncertain";
|
|
114
|
-
type WorkspaceTab =
|
|
116
|
+
type WorkspaceTab =
|
|
117
|
+
| "map"
|
|
118
|
+
| "inbox"
|
|
119
|
+
| "rules"
|
|
120
|
+
| "automations"
|
|
121
|
+
| "audit"
|
|
122
|
+
| "settings";
|
|
115
123
|
|
|
116
124
|
type FactoryAutomationRun = {
|
|
117
125
|
id?: string;
|
|
@@ -164,6 +172,7 @@ export default function FactoryRoute() {
|
|
|
164
172
|
const [dirty, setDirty] = useState(false);
|
|
165
173
|
const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
|
|
166
174
|
const [selectedEdgeId, setSelectedEdgeId] = useState<string | null>(null);
|
|
175
|
+
const [auditRefreshToken, setAuditRefreshToken] = useState(0);
|
|
167
176
|
|
|
168
177
|
function setActiveTab(tab: WorkspaceTab) {
|
|
169
178
|
setSearchParams(
|
|
@@ -418,41 +427,62 @@ export default function FactoryRoute() {
|
|
|
418
427
|
</Button>
|
|
419
428
|
</div>
|
|
420
429
|
</div>
|
|
421
|
-
<
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
<TabButton
|
|
426
|
-
active={activeTab === "map"}
|
|
427
|
-
onClick={() => setActiveTab("map")}
|
|
428
|
-
>
|
|
429
|
-
Map
|
|
430
|
-
</TabButton>
|
|
431
|
-
<TabButton
|
|
432
|
-
active={activeTab === "inbox"}
|
|
433
|
-
onClick={() => setActiveTab("inbox")}
|
|
434
|
-
>
|
|
435
|
-
Inbox
|
|
436
|
-
</TabButton>
|
|
437
|
-
<TabButton
|
|
438
|
-
active={activeTab === "rules"}
|
|
439
|
-
onClick={() => setActiveTab("rules")}
|
|
440
|
-
>
|
|
441
|
-
{t("factoryRoute.rulesTab")}
|
|
442
|
-
</TabButton>
|
|
443
|
-
<TabButton
|
|
444
|
-
active={activeTab === "automations"}
|
|
445
|
-
onClick={() => setActiveTab("automations")}
|
|
430
|
+
<div className="mt-4 flex items-center gap-2">
|
|
431
|
+
<nav
|
|
432
|
+
className="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto"
|
|
433
|
+
aria-label={t("factoryRoute.factoryViews")}
|
|
446
434
|
>
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
435
|
+
<TabButton
|
|
436
|
+
active={activeTab === "map"}
|
|
437
|
+
onClick={() => setActiveTab("map")}
|
|
438
|
+
>
|
|
439
|
+
Map
|
|
440
|
+
</TabButton>
|
|
441
|
+
<TabButton
|
|
442
|
+
active={activeTab === "inbox"}
|
|
443
|
+
onClick={() => setActiveTab("inbox")}
|
|
444
|
+
>
|
|
445
|
+
Inbox
|
|
446
|
+
</TabButton>
|
|
447
|
+
<TabButton
|
|
448
|
+
active={activeTab === "rules"}
|
|
449
|
+
onClick={() => setActiveTab("rules")}
|
|
450
|
+
>
|
|
451
|
+
{t("factoryRoute.rulesTab")}
|
|
452
|
+
</TabButton>
|
|
453
|
+
<TabButton
|
|
454
|
+
active={activeTab === "automations"}
|
|
455
|
+
onClick={() => setActiveTab("automations")}
|
|
456
|
+
>
|
|
457
|
+
{t("factoryRoute.automationsTab")}
|
|
458
|
+
</TabButton>
|
|
459
|
+
<TabButton
|
|
460
|
+
active={activeTab === "audit"}
|
|
461
|
+
onClick={() => setActiveTab("audit")}
|
|
462
|
+
>
|
|
463
|
+
{t("factoryRoute.auditTab")}
|
|
464
|
+
</TabButton>
|
|
465
|
+
<TabButton
|
|
466
|
+
active={activeTab === "settings"}
|
|
467
|
+
onClick={() => setActiveTab("settings")}
|
|
468
|
+
>
|
|
469
|
+
Settings
|
|
470
|
+
</TabButton>
|
|
471
|
+
</nav>
|
|
472
|
+
{activeTab === "audit" && (
|
|
473
|
+
<Button
|
|
474
|
+
type="button"
|
|
475
|
+
variant="ghost"
|
|
476
|
+
size="icon"
|
|
477
|
+
className="size-8 shrink-0 text-muted-foreground hover:text-foreground"
|
|
478
|
+
aria-label={t("factoryRoute.auditRefresh")}
|
|
479
|
+
title={t("factoryRoute.auditRefresh")}
|
|
480
|
+
onClick={() => setAuditRefreshToken((current) => current + 1)}
|
|
481
|
+
>
|
|
482
|
+
<IconRefresh className="size-4" />
|
|
483
|
+
</Button>
|
|
484
|
+
)}
|
|
485
|
+
</div>
|
|
456
486
|
</header>
|
|
457
487
|
|
|
458
488
|
<main className="min-h-0 flex-1 overflow-y-auto">
|
|
@@ -526,6 +556,11 @@ export default function FactoryRoute() {
|
|
|
526
556
|
<RulesView t={t} />
|
|
527
557
|
) : activeTab === "automations" ? (
|
|
528
558
|
<AutomationsView factoryId={factoryId} t={t} />
|
|
559
|
+
) : activeTab === "audit" ? (
|
|
560
|
+
<FactoryAuditView
|
|
561
|
+
factoryId={factoryId}
|
|
562
|
+
refreshToken={auditRefreshToken}
|
|
563
|
+
/>
|
|
529
564
|
) : (
|
|
530
565
|
<SettingsView t={t} />
|
|
531
566
|
)}
|
|
@@ -559,6 +594,7 @@ function parseWorkspaceTab(value: string | null): WorkspaceTab {
|
|
|
559
594
|
return value === "inbox" ||
|
|
560
595
|
value === "rules" ||
|
|
561
596
|
value === "automations" ||
|
|
597
|
+
value === "audit" ||
|
|
562
598
|
value === "settings"
|
|
563
599
|
? value
|
|
564
600
|
: "map";
|
|
@@ -729,7 +765,7 @@ function AutomationsView({
|
|
|
729
765
|
<span className="block truncate text-sm font-medium">
|
|
730
766
|
{automation.name}
|
|
731
767
|
</span>
|
|
732
|
-
<span className="mt-1 block text-xs text-muted-foreground">
|
|
768
|
+
<span className="mt-1 block truncate text-xs text-muted-foreground">
|
|
733
769
|
{automation.enabled
|
|
734
770
|
? t("factoryRoute.automationEnabled")
|
|
735
771
|
: t("factoryRoute.automationDisabled")}
|
|
@@ -956,8 +992,11 @@ function formatModelName(model: string | null | undefined) {
|
|
|
956
992
|
}
|
|
957
993
|
|
|
958
994
|
function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
995
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
959
996
|
const [status, setStatus] = useState("");
|
|
960
|
-
const [selectedId, setSelectedId] = useState<string | null>(
|
|
997
|
+
const [selectedId, setSelectedId] = useState<string | null>(
|
|
998
|
+
searchParams.get("itemId"),
|
|
999
|
+
);
|
|
961
1000
|
const [feedbackNote, setFeedbackNote] = useState("");
|
|
962
1001
|
const [verdict, setVerdict] = useState<Verdict | null>(null);
|
|
963
1002
|
const listQuery = useActionQuery("list-triage-items", {
|
|
@@ -989,6 +1028,24 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
989
1028
|
const normalizedItems = Array.isArray(items) ? items : (items.items ?? []);
|
|
990
1029
|
const selectedItem = detailQuery.data as TriageItem | undefined;
|
|
991
1030
|
|
|
1031
|
+
useEffect(() => {
|
|
1032
|
+
setSelectedId(searchParams.get("itemId"));
|
|
1033
|
+
}, [searchParams]);
|
|
1034
|
+
|
|
1035
|
+
function selectItem(itemId: string) {
|
|
1036
|
+
setSelectedId(itemId);
|
|
1037
|
+
setVerdict(null);
|
|
1038
|
+
setFeedbackNote("");
|
|
1039
|
+
setSearchParams(
|
|
1040
|
+
(current) => {
|
|
1041
|
+
const next = new URLSearchParams(current);
|
|
1042
|
+
next.set("itemId", itemId);
|
|
1043
|
+
return next;
|
|
1044
|
+
},
|
|
1045
|
+
{ replace: true },
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
992
1049
|
return (
|
|
993
1050
|
<div className="grid gap-4 p-4 lg:grid-cols-[minmax(0,1.3fr)_minmax(320px,.7fr)] lg:p-6">
|
|
994
1051
|
<Card>
|
|
@@ -1046,11 +1103,7 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1046
1103
|
key={id}
|
|
1047
1104
|
type="button"
|
|
1048
1105
|
className={`grid w-full gap-3 p-4 text-left transition-colors hover:bg-muted/50 sm:grid-cols-[1.1fr_.7fr_.9fr_1.6fr] ${selectedId === id ? "bg-muted/60" : ""}`}
|
|
1049
|
-
onClick={() =>
|
|
1050
|
-
setSelectedId(id);
|
|
1051
|
-
setVerdict(null);
|
|
1052
|
-
setFeedbackNote("");
|
|
1053
|
-
}}
|
|
1106
|
+
onClick={() => selectItem(id)}
|
|
1054
1107
|
>
|
|
1055
1108
|
<span className="min-w-0">
|
|
1056
1109
|
<span className="block truncate text-sm font-medium">
|
|
@@ -132,6 +132,43 @@ export const triageConfig = table("factory_config", {
|
|
|
132
132
|
orgId: text("org_id"),
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
+
export const factoryAuditEvents = table(
|
|
136
|
+
"factory_audit_events",
|
|
137
|
+
{
|
|
138
|
+
id: text("id").primaryKey(),
|
|
139
|
+
automationRunId: text("automation_run_id"),
|
|
140
|
+
automationThreadId: text("automation_thread_id"),
|
|
141
|
+
automationName: text("automation_name"),
|
|
142
|
+
itemId: text("item_id"),
|
|
143
|
+
source: text("source"),
|
|
144
|
+
sourceUrl: text("source_url"),
|
|
145
|
+
action: text("action").notNull(),
|
|
146
|
+
kind: text("kind").notNull(),
|
|
147
|
+
status: text("status").notNull(),
|
|
148
|
+
summary: text("summary").notNull(),
|
|
149
|
+
detailsJson: text("details_json").notNull().default("{}"),
|
|
150
|
+
createdAt: text("created_at").notNull().default(now()),
|
|
151
|
+
ownerEmail: text("owner_email").notNull(),
|
|
152
|
+
orgId: text("org_id"),
|
|
153
|
+
},
|
|
154
|
+
(event) => ({
|
|
155
|
+
orgCreatedIdx: index("factory_audit_events_org_created_idx").on(
|
|
156
|
+
event.orgId,
|
|
157
|
+
event.createdAt,
|
|
158
|
+
),
|
|
159
|
+
runCreatedIdx: index("factory_audit_events_run_created_idx").on(
|
|
160
|
+
event.orgId,
|
|
161
|
+
event.automationRunId,
|
|
162
|
+
event.createdAt,
|
|
163
|
+
),
|
|
164
|
+
itemCreatedIdx: index("factory_audit_events_item_created_idx").on(
|
|
165
|
+
event.orgId,
|
|
166
|
+
event.itemId,
|
|
167
|
+
event.createdAt,
|
|
168
|
+
),
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
|
|
135
172
|
export const factoryDefinitions = table(
|
|
136
173
|
"factory_definitions",
|
|
137
174
|
{
|
|
@@ -45,7 +45,11 @@ export async function requireFactoryAutomation(
|
|
|
45
45
|
|
|
46
46
|
const definition = (
|
|
47
47
|
await listAutomationDefinitions(
|
|
48
|
-
{
|
|
48
|
+
{
|
|
49
|
+
userEmail: identity.userEmail,
|
|
50
|
+
orgId: identity.orgId,
|
|
51
|
+
appId: "factory",
|
|
52
|
+
},
|
|
49
53
|
"organization",
|
|
50
54
|
)
|
|
51
55
|
).find((entry) => entry.resource.id === lineage.triggerId);
|
|
@@ -258,6 +258,35 @@ const migrations = [
|
|
|
258
258
|
ALTER TABLE factory_config ADD COLUMN last_automation_failure_alert_at TEXT;
|
|
259
259
|
`,
|
|
260
260
|
},
|
|
261
|
+
{
|
|
262
|
+
version: 18,
|
|
263
|
+
name: "factory-audit-events-table",
|
|
264
|
+
sql: `
|
|
265
|
+
CREATE TABLE IF NOT EXISTS factory_audit_events (
|
|
266
|
+
id TEXT PRIMARY KEY,
|
|
267
|
+
automation_run_id TEXT,
|
|
268
|
+
automation_thread_id TEXT,
|
|
269
|
+
automation_name TEXT,
|
|
270
|
+
item_id TEXT,
|
|
271
|
+
source TEXT,
|
|
272
|
+
source_url TEXT,
|
|
273
|
+
action TEXT NOT NULL,
|
|
274
|
+
kind TEXT NOT NULL,
|
|
275
|
+
status TEXT NOT NULL,
|
|
276
|
+
summary TEXT NOT NULL,
|
|
277
|
+
details_json TEXT NOT NULL DEFAULT '{}',
|
|
278
|
+
created_at TEXT NOT NULL,
|
|
279
|
+
owner_email TEXT NOT NULL,
|
|
280
|
+
org_id TEXT
|
|
281
|
+
);
|
|
282
|
+
CREATE INDEX IF NOT EXISTS factory_audit_events_org_created_idx
|
|
283
|
+
ON factory_audit_events (org_id, created_at);
|
|
284
|
+
CREATE INDEX IF NOT EXISTS factory_audit_events_run_created_idx
|
|
285
|
+
ON factory_audit_events (org_id, automation_run_id, created_at);
|
|
286
|
+
CREATE INDEX IF NOT EXISTS factory_audit_events_item_created_idx
|
|
287
|
+
ON factory_audit_events (org_id, item_id, created_at);
|
|
288
|
+
`,
|
|
289
|
+
},
|
|
261
290
|
];
|
|
262
291
|
|
|
263
292
|
export const runFactoryMigrations = runMigrations(migrations, {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import type { ActionRunContext } from "@agent-native/core/action";
|
|
4
|
+
|
|
5
|
+
import { getDb } from "../db/index.js";
|
|
6
|
+
import { factoryAuditEvents } from "../db/schema.js";
|
|
7
|
+
|
|
8
|
+
const MAX_SUMMARY_LENGTH = 500;
|
|
9
|
+
const MAX_DETAILS_LENGTH = 4_000;
|
|
10
|
+
|
|
11
|
+
export type FactoryAuditKind =
|
|
12
|
+
| "observed"
|
|
13
|
+
| "read"
|
|
14
|
+
| "decision"
|
|
15
|
+
| "external_action"
|
|
16
|
+
| "governance";
|
|
17
|
+
|
|
18
|
+
export type FactoryAuditStatus = "success" | "error" | "skipped";
|
|
19
|
+
|
|
20
|
+
export interface FactoryAuditInput {
|
|
21
|
+
action: string;
|
|
22
|
+
kind: FactoryAuditKind;
|
|
23
|
+
status?: FactoryAuditStatus;
|
|
24
|
+
itemId?: string | null;
|
|
25
|
+
source?: string | null;
|
|
26
|
+
sourceUrl?: string | null;
|
|
27
|
+
summary: string;
|
|
28
|
+
details?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function boundedText(value: string, max: number): string {
|
|
32
|
+
const compact = value.replace(/\s+/g, " ").trim();
|
|
33
|
+
return compact.length > max ? `${compact.slice(0, max - 1)}…` : compact;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function boundedDetails(value: Record<string, unknown> | undefined): string {
|
|
37
|
+
if (!value) return "{}";
|
|
38
|
+
let serialized: string;
|
|
39
|
+
try {
|
|
40
|
+
serialized = JSON.stringify(value);
|
|
41
|
+
} catch {
|
|
42
|
+
throw new Error("Factory audit details are not serializable.");
|
|
43
|
+
}
|
|
44
|
+
return serialized.length > MAX_DETAILS_LENGTH
|
|
45
|
+
? JSON.stringify({ truncated: true })
|
|
46
|
+
: serialized;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Persist a bounded, source-linked explanation of an automation action. The
|
|
51
|
+
* agent run id is the join key to core's automation history; no raw provider
|
|
52
|
+
* payload is copied into this table.
|
|
53
|
+
*/
|
|
54
|
+
export async function recordFactoryAudit(
|
|
55
|
+
context: ActionRunContext | undefined,
|
|
56
|
+
identity: { userEmail: string; orgId: string },
|
|
57
|
+
input: FactoryAuditInput,
|
|
58
|
+
): Promise<void> {
|
|
59
|
+
if (context?.caller !== "automation" || !context.runId) return;
|
|
60
|
+
await getDb()
|
|
61
|
+
.insert(factoryAuditEvents)
|
|
62
|
+
.values({
|
|
63
|
+
id: randomUUID(),
|
|
64
|
+
automationRunId: context.runId,
|
|
65
|
+
automationThreadId: context.threadId ?? null,
|
|
66
|
+
automationName: context.automation?.triggerName ?? null,
|
|
67
|
+
itemId: input.itemId ?? null,
|
|
68
|
+
source: input.source ?? null,
|
|
69
|
+
sourceUrl: input.sourceUrl ?? null,
|
|
70
|
+
action: boundedText(input.action, 120),
|
|
71
|
+
kind: input.kind,
|
|
72
|
+
status: input.status ?? "success",
|
|
73
|
+
summary: boundedText(input.summary, MAX_SUMMARY_LENGTH),
|
|
74
|
+
detailsJson: boundedDetails(input.details),
|
|
75
|
+
createdAt: new Date().toISOString(),
|
|
76
|
+
ownerEmail: identity.userEmail,
|
|
77
|
+
orgId: identity.orgId,
|
|
78
|
+
});
|
|
79
|
+
}
|