@agent-native/core 0.168.7 → 0.168.9
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/actions/mutate-dashboard.ts +8 -1
- package/corpus/templates/calendar/actions/delete-event.ts +34 -18
- package/corpus/templates/calendar/actions/delete-events.ts +13 -1
- package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +22 -3
- package/corpus/templates/calendar/app/lib/calendar-timezone.ts +19 -0
- package/corpus/templates/calendar/server/lib/google-api.ts +18 -1
- package/corpus/templates/clips/actions/finalize-meeting.ts +16 -0
- package/corpus/templates/clips/actions/list-meetings.ts +1 -0
- package/corpus/templates/clips/actions/sync-calendars.ts +10 -29
- package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +28 -12
- package/corpus/templates/clips/desktop/src/lib/meeting-stop.ts +16 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +19 -9
- package/corpus/templates/factory/.agents/skills/factory-graphs/SKILL.md +5 -0
- package/corpus/templates/factory/AGENTS.md +12 -22
- package/corpus/templates/factory/README.md +11 -8
- package/corpus/templates/factory/actions/approve-factory-item.ts +35 -8
- package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +24 -9
- package/corpus/templates/factory/actions/create-factory.ts +211 -0
- package/corpus/templates/factory/actions/evaluate-triage-item.ts +29 -5
- package/corpus/templates/factory/actions/get-factory-graph.ts +1 -1
- package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -11
- package/corpus/templates/factory/actions/get-triage-config.ts +13 -12
- package/corpus/templates/factory/actions/get-triage-item.ts +28 -6
- package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +33 -17
- package/corpus/templates/factory/actions/ingest-github-observation.ts +10 -4
- package/corpus/templates/factory/actions/list-factory-audit.ts +11 -4
- package/corpus/templates/factory/actions/list-factory-automations.ts +34 -12
- package/corpus/templates/factory/actions/list-triage-items.ts +11 -3
- package/corpus/templates/factory/actions/list-triage-rules.ts +11 -4
- package/corpus/templates/factory/actions/poll-github-sources.ts +24 -10
- package/corpus/templates/factory/actions/poll-sentry-errors.ts +26 -11
- package/corpus/templates/factory/actions/poll-slack-channel.ts +31 -13
- package/corpus/templates/factory/actions/reconcile-triage-run.ts +59 -9
- package/corpus/templates/factory/actions/record-triage-feedback.ts +14 -3
- package/corpus/templates/factory/actions/run-factory-automation.ts +12 -2
- package/corpus/templates/factory/actions/save-factory-automation.ts +82 -21
- package/corpus/templates/factory/actions/save-factory-graph.ts +10 -1
- package/corpus/templates/factory/actions/save-triage-config.ts +90 -36
- package/corpus/templates/factory/actions/save-triage-rule.ts +16 -3
- package/corpus/templates/factory/actions/start-builder-for-item.ts +28 -20
- package/corpus/templates/factory/actions/suggest-factory-rules.ts +11 -4
- package/corpus/templates/factory/actions/view-screen.ts +22 -30
- package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +7 -2
- package/corpus/templates/factory/app/components/factory/FactoryWorkspaceActions.tsx +7 -22
- package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +260 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +2 -1
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -3
- package/corpus/templates/factory/app/i18n/en-US.ts +18 -1
- package/corpus/templates/factory/app/routes/factory.tsx +78 -62
- package/corpus/templates/factory/app/routes/{factory-settings.tsx → new-factory.tsx} +12 -9
- package/corpus/templates/factory/server/db/schema.ts +18 -3
- package/corpus/templates/factory/server/factory-graph/contracts.ts +24 -0
- package/corpus/templates/factory/server/factory-graph/store.ts +16 -9
- package/corpus/templates/factory/server/lib/factory-automation-plan.ts +136 -0
- package/corpus/templates/factory/server/lib/factory-automation-repair.ts +31 -0
- package/corpus/templates/factory/server/lib/factory-scope.ts +416 -0
- package/corpus/templates/factory/server/lib/require-factory-automation.ts +11 -0
- package/corpus/templates/factory/server/plugins/agent-chat.ts +4 -2
- package/corpus/templates/factory/server/plugins/factory-migrations.ts +80 -0
- package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +142 -43
- package/corpus/templates/factory/server/triage/audit.ts +4 -0
- package/corpus/templates/factory/server/triage/ids.ts +4 -0
- package/dist/cli/native-dependencies.js +4 -1
- package/dist/client/AgentPanel.d.ts +5 -1
- package/dist/client/AgentPanel.js +9 -4
- package/dist/client/agent-chat/index.d.ts +1 -1
- package/dist/client/agent-chat/index.js +1 -1
- package/dist/client/chat-first/apps-rail.js +6 -6
- package/dist/client/chat-first/primary-nav.js +14 -6
- package/dist/client/integrations/IntegrationsPanel.d.ts +15 -0
- package/dist/client/integrations/IntegrationsPanel.js +29 -21
- package/dist/client/integrations/index.d.ts +1 -1
- package/dist/client/integrations/index.js +1 -1
- package/dist/client/resources/McpIntegrationDialog.js +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
} from "@/components/factory/FactoryCanvas";
|
|
30
30
|
import { FactoryHistoryView } from "@/components/factory/FactoryHistoryView";
|
|
31
31
|
import { FactoryInspector } from "@/components/factory/FactoryInspector";
|
|
32
|
+
import { FactorySettingsView } from "@/components/factory/FactorySettingsView";
|
|
32
33
|
import { FactoryWorkspaceActions } from "@/components/factory/FactoryWorkspaceActions";
|
|
33
34
|
import { TriageStatusPill } from "@/components/triage/triage-status-pill";
|
|
34
35
|
import { Button } from "@/components/ui/button";
|
|
@@ -106,6 +107,7 @@ type WorkspaceTab =
|
|
|
106
107
|
| "map"
|
|
107
108
|
| "inbox"
|
|
108
109
|
| "rules"
|
|
110
|
+
| "settings"
|
|
109
111
|
| "automations"
|
|
110
112
|
| "agents"
|
|
111
113
|
| "audit"
|
|
@@ -124,6 +126,7 @@ type FactoryAutomationRun = {
|
|
|
124
126
|
type FactoryAutomation = {
|
|
125
127
|
id: string;
|
|
126
128
|
name: string;
|
|
129
|
+
displayName: string;
|
|
127
130
|
prompt?: string | null;
|
|
128
131
|
body?: string | null;
|
|
129
132
|
model?: string | null;
|
|
@@ -151,7 +154,6 @@ export default function FactoryRoute() {
|
|
|
151
154
|
const activeTab = parseWorkspaceTab(searchParams.get("tab"));
|
|
152
155
|
const selectedFactoryId = searchParams.get("factoryId");
|
|
153
156
|
const factoryId = selectedFactoryId ?? DEFAULT_FACTORY_ID;
|
|
154
|
-
const [creating, setCreating] = useState(false);
|
|
155
157
|
const [draftGraph, setDraftGraph] = useState<FactoryCanvasGraph | null>(null);
|
|
156
158
|
const [dirty, setDirty] = useState(false);
|
|
157
159
|
const [saveError, setSaveError] = useState<string | null>(null);
|
|
@@ -183,7 +185,6 @@ export default function FactoryRoute() {
|
|
|
183
185
|
nextFactoryId: string,
|
|
184
186
|
options?: { tab?: WorkspaceTab; replace?: boolean },
|
|
185
187
|
) {
|
|
186
|
-
setCreating(false);
|
|
187
188
|
setDraftGraph(null);
|
|
188
189
|
setDirty(false);
|
|
189
190
|
setSelectedNodeId(null);
|
|
@@ -241,12 +242,12 @@ export default function FactoryRoute() {
|
|
|
241
242
|
const factoryList = (factoryListQuery.data ?? []) as FactorySummary[];
|
|
242
243
|
|
|
243
244
|
useEffect(() => {
|
|
244
|
-
if (!graphData ||
|
|
245
|
+
if (!graphData || dirty) return;
|
|
245
246
|
setDraftGraph(graphData.graph);
|
|
246
247
|
setDirty(false);
|
|
247
248
|
setSelectedNodeId(null);
|
|
248
249
|
setSelectedEdgeId(null);
|
|
249
|
-
}, [
|
|
250
|
+
}, [dirty, graphData]);
|
|
250
251
|
|
|
251
252
|
useEffect(() => {
|
|
252
253
|
setSelectedNodeId(searchParams.get("node"));
|
|
@@ -255,7 +256,6 @@ export default function FactoryRoute() {
|
|
|
255
256
|
|
|
256
257
|
useEffect(() => {
|
|
257
258
|
if (selectedFactoryId) return;
|
|
258
|
-
setCreating(false);
|
|
259
259
|
setDraftGraph(null);
|
|
260
260
|
setDirty(false);
|
|
261
261
|
setSelectedNodeId(null);
|
|
@@ -352,37 +352,6 @@ export default function FactoryRoute() {
|
|
|
352
352
|
});
|
|
353
353
|
}
|
|
354
354
|
|
|
355
|
-
function startNewFactory() {
|
|
356
|
-
const id = `factory-${Date.now().toString(36)}`;
|
|
357
|
-
openFactory(id, { tab: "overview" });
|
|
358
|
-
setCreating(true);
|
|
359
|
-
setDraftGraph({
|
|
360
|
-
version: 1,
|
|
361
|
-
name: t("factoryRoute.newFactory"),
|
|
362
|
-
description: t("factoryRoute.newFactoryDescription"),
|
|
363
|
-
executionMode: "blueprint",
|
|
364
|
-
nodes: [
|
|
365
|
-
{
|
|
366
|
-
id: "start",
|
|
367
|
-
label: t("factoryRoute.newStep"),
|
|
368
|
-
description: t("factoryRoute.newStepDescription"),
|
|
369
|
-
kind: "decision",
|
|
370
|
-
provider: "factory",
|
|
371
|
-
position: { x: 240, y: 220 },
|
|
372
|
-
},
|
|
373
|
-
],
|
|
374
|
-
edges: [],
|
|
375
|
-
});
|
|
376
|
-
setDirty(true);
|
|
377
|
-
setSelectedNodeId(null);
|
|
378
|
-
setSelectedEdgeId(null);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
useEffect(() => {
|
|
382
|
-
if (searchParams.get("new") !== "1") return;
|
|
383
|
-
startNewFactory();
|
|
384
|
-
}, [searchParams]);
|
|
385
|
-
|
|
386
355
|
async function saveGraph() {
|
|
387
356
|
if (!graph || !selectedFactoryId) return;
|
|
388
357
|
const submittedDraftRevision = draftRevisionRef.current;
|
|
@@ -392,15 +361,12 @@ export default function FactoryRoute() {
|
|
|
392
361
|
factoryId: selectedFactoryId,
|
|
393
362
|
name: graph.name,
|
|
394
363
|
description: graph.description,
|
|
395
|
-
prompt:
|
|
364
|
+
prompt: graphData?.factory.prompt ?? "",
|
|
396
365
|
source: "manual",
|
|
397
|
-
changeSummary:
|
|
398
|
-
|
|
399
|
-
: "Updated in the Factory visual editor.",
|
|
400
|
-
expectedGraphVersion: creating ? 0 : graph.version,
|
|
366
|
+
changeSummary: "Updated in the Factory visual editor.",
|
|
367
|
+
expectedGraphVersion: graph.version,
|
|
401
368
|
graph,
|
|
402
369
|
});
|
|
403
|
-
setCreating(false);
|
|
404
370
|
setDirty(draftRevisionRef.current !== submittedDraftRevision);
|
|
405
371
|
setSaveConflictRemoteGraph(null);
|
|
406
372
|
await Promise.all([graphQuery.refetch(), factoryListQuery.refetch()]);
|
|
@@ -445,13 +411,11 @@ export default function FactoryRoute() {
|
|
|
445
411
|
setSaveConflictRemoteGraph(null);
|
|
446
412
|
setSaveError(null);
|
|
447
413
|
setDirty(false);
|
|
448
|
-
setCreating(false);
|
|
449
414
|
setSelectedNodeId(null);
|
|
450
415
|
setSelectedEdgeId(null);
|
|
451
416
|
}
|
|
452
417
|
|
|
453
418
|
async function handleFactoryRestored(result?: { graph: FactoryCanvasGraph }) {
|
|
454
|
-
setCreating(false);
|
|
455
419
|
if (result?.graph) setDraftGraph(result.graph);
|
|
456
420
|
else setDraftGraph(null);
|
|
457
421
|
setDirty(false);
|
|
@@ -468,9 +432,10 @@ export default function FactoryRoute() {
|
|
|
468
432
|
}
|
|
469
433
|
}
|
|
470
434
|
|
|
471
|
-
if (searchParams.get("
|
|
472
|
-
return <Navigate to="/factory
|
|
435
|
+
if (searchParams.get("new") === "1") {
|
|
436
|
+
return <Navigate to="/new-factory" replace />;
|
|
473
437
|
}
|
|
438
|
+
|
|
474
439
|
if (selectedFactoryId && searchParams.get("tab") === "agents") {
|
|
475
440
|
return <Navigate to="/factory?tab=agents" replace />;
|
|
476
441
|
}
|
|
@@ -488,7 +453,7 @@ export default function FactoryRoute() {
|
|
|
488
453
|
{t("factoryRoute.agentsTitle")}
|
|
489
454
|
</h1>
|
|
490
455
|
<div className="ms-auto">
|
|
491
|
-
<FactoryWorkspaceActions
|
|
456
|
+
<FactoryWorkspaceActions />
|
|
492
457
|
</div>
|
|
493
458
|
</div>
|
|
494
459
|
<FactoryAgentsView />
|
|
@@ -502,7 +467,7 @@ export default function FactoryRoute() {
|
|
|
502
467
|
<section className="mx-auto flex w-full max-w-6xl flex-1 flex-col gap-6 p-4 lg:p-6">
|
|
503
468
|
<div className="flex flex-wrap items-end justify-between gap-4">
|
|
504
469
|
<h1 className="text-2xl font-semibold tracking-tight">Factories</h1>
|
|
505
|
-
<FactoryWorkspaceActions
|
|
470
|
+
<FactoryWorkspaceActions />
|
|
506
471
|
</div>
|
|
507
472
|
|
|
508
473
|
{factoryListQuery.isError ? (
|
|
@@ -598,7 +563,7 @@ export default function FactoryRoute() {
|
|
|
598
563
|
</Button>
|
|
599
564
|
<div className="h-5 w-48 animate-pulse rounded bg-muted" />
|
|
600
565
|
</div>
|
|
601
|
-
<FactoryWorkspaceActions
|
|
566
|
+
<FactoryWorkspaceActions />
|
|
602
567
|
</div>
|
|
603
568
|
</header>
|
|
604
569
|
<main className="flex flex-1 items-center justify-center p-6">
|
|
@@ -645,7 +610,7 @@ export default function FactoryRoute() {
|
|
|
645
610
|
</span>
|
|
646
611
|
</div>
|
|
647
612
|
<div className="flex items-center gap-2">
|
|
648
|
-
<FactoryWorkspaceActions
|
|
613
|
+
<FactoryWorkspaceActions />
|
|
649
614
|
</div>
|
|
650
615
|
</div>
|
|
651
616
|
<div className="flex items-center gap-2 overflow-x-auto px-2 py-2 sm:px-4 lg:px-6">
|
|
@@ -695,6 +660,12 @@ export default function FactoryRoute() {
|
|
|
695
660
|
>
|
|
696
661
|
{t("factoryRoute.historyTab")}
|
|
697
662
|
</TabButton>
|
|
663
|
+
<TabButton
|
|
664
|
+
active={activeTab === "settings"}
|
|
665
|
+
onClick={() => setActiveTab("settings")}
|
|
666
|
+
>
|
|
667
|
+
{t("factoryRoute.factorySettings")}
|
|
668
|
+
</TabButton>
|
|
698
669
|
</nav>
|
|
699
670
|
{activeTab === "audit" && (
|
|
700
671
|
<Button
|
|
@@ -723,6 +694,7 @@ export default function FactoryRoute() {
|
|
|
723
694
|
onOpenAutomations={() => setActiveTab("automations")}
|
|
724
695
|
onOpenActivity={() => setActiveTab("audit")}
|
|
725
696
|
onOpenFlow={() => setActiveTab("map")}
|
|
697
|
+
onOpenSettings={() => setActiveTab("settings")}
|
|
726
698
|
/>
|
|
727
699
|
) : activeTab === "map" ? (
|
|
728
700
|
<div className="grid min-h-full gap-4 p-4 lg:p-6 xl:grid-cols-[minmax(0,1fr)_360px]">
|
|
@@ -769,9 +741,11 @@ export default function FactoryRoute() {
|
|
|
769
741
|
/>
|
|
770
742
|
</div>
|
|
771
743
|
) : activeTab === "inbox" ? (
|
|
772
|
-
<InboxView t={t} />
|
|
744
|
+
<InboxView factoryId={factoryId} t={t} />
|
|
773
745
|
) : activeTab === "rules" ? (
|
|
774
|
-
<RulesView t={t} />
|
|
746
|
+
<RulesView factoryId={factoryId} t={t} />
|
|
747
|
+
) : activeTab === "settings" ? (
|
|
748
|
+
<FactorySettingsView factoryId={factoryId} />
|
|
775
749
|
) : activeTab === "automations" ? (
|
|
776
750
|
<AutomationsView factoryId={factoryId} t={t} />
|
|
777
751
|
) : activeTab === "audit" ? (
|
|
@@ -817,6 +791,7 @@ function parseWorkspaceTab(value: string | null): WorkspaceTab {
|
|
|
817
791
|
return value === "map" ||
|
|
818
792
|
value === "inbox" ||
|
|
819
793
|
value === "rules" ||
|
|
794
|
+
value === "settings" ||
|
|
820
795
|
value === "automations" ||
|
|
821
796
|
value === "agents" ||
|
|
822
797
|
value === "audit" ||
|
|
@@ -834,6 +809,7 @@ function OverviewView({
|
|
|
834
809
|
onOpenAutomations,
|
|
835
810
|
onOpenActivity,
|
|
836
811
|
onOpenFlow,
|
|
812
|
+
onOpenSettings,
|
|
837
813
|
}: {
|
|
838
814
|
graph: FactoryCanvasGraph;
|
|
839
815
|
t: ReturnType<typeof useT>;
|
|
@@ -843,6 +819,7 @@ function OverviewView({
|
|
|
843
819
|
onOpenAutomations: () => void;
|
|
844
820
|
onOpenActivity: () => void;
|
|
845
821
|
onOpenFlow: () => void;
|
|
822
|
+
onOpenSettings: () => void;
|
|
846
823
|
}) {
|
|
847
824
|
return (
|
|
848
825
|
<div className="mx-auto flex w-full max-w-5xl flex-col gap-4 p-4 lg:p-6">
|
|
@@ -919,10 +896,12 @@ function OverviewView({
|
|
|
919
896
|
<Button type="button" variant="outline" onClick={onOpenActivity}>
|
|
920
897
|
Activity
|
|
921
898
|
</Button>
|
|
922
|
-
<Button
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
899
|
+
<Button
|
|
900
|
+
type="button"
|
|
901
|
+
variant="outline"
|
|
902
|
+
onClick={() => onOpenSettings?.()}
|
|
903
|
+
>
|
|
904
|
+
{t("factoryRoute.factorySettings")}
|
|
926
905
|
</Button>
|
|
927
906
|
<Button type="button" onClick={onOpenFlow}>
|
|
928
907
|
{t("factoryRoute.editFlow")}
|
|
@@ -1015,6 +994,7 @@ function AutomationsView({
|
|
|
1015
994
|
current &&
|
|
1016
995
|
current.id === nextDraft.id &&
|
|
1017
996
|
current.name === nextDraft.name &&
|
|
997
|
+
current.displayName === nextDraft.displayName &&
|
|
1018
998
|
current.prompt === nextDraft.prompt &&
|
|
1019
999
|
current.body === nextDraft.body &&
|
|
1020
1000
|
current.model === nextDraft.model &&
|
|
@@ -1035,6 +1015,7 @@ function AutomationsView({
|
|
|
1035
1015
|
factoryId,
|
|
1036
1016
|
automationId: draft.id,
|
|
1037
1017
|
name: draft.name,
|
|
1018
|
+
displayName: draft.displayName,
|
|
1038
1019
|
prompt: draft.prompt ?? draft.body ?? "",
|
|
1039
1020
|
model: draft.model ?? "",
|
|
1040
1021
|
schedule: draft.schedule ?? "",
|
|
@@ -1101,8 +1082,11 @@ function AutomationsView({
|
|
|
1101
1082
|
}`}
|
|
1102
1083
|
onClick={() => selectAutomation(automation.id)}
|
|
1103
1084
|
>
|
|
1104
|
-
<span
|
|
1105
|
-
|
|
1085
|
+
<span
|
|
1086
|
+
className="block truncate text-sm font-medium"
|
|
1087
|
+
title={automation.name}
|
|
1088
|
+
>
|
|
1089
|
+
{automation.displayName}
|
|
1106
1090
|
</span>
|
|
1107
1091
|
<span className="mt-1 block truncate text-xs text-muted-foreground">
|
|
1108
1092
|
{automation.enabled
|
|
@@ -1171,6 +1155,22 @@ function AutomationsView({
|
|
|
1171
1155
|
</p>
|
|
1172
1156
|
) : (
|
|
1173
1157
|
<>
|
|
1158
|
+
<div className="grid gap-1.5">
|
|
1159
|
+
<Label htmlFor="factory-automation-display-name">
|
|
1160
|
+
{t("factoryRoute.automationDisplayName")}
|
|
1161
|
+
</Label>
|
|
1162
|
+
<Input
|
|
1163
|
+
id="factory-automation-display-name"
|
|
1164
|
+
value={draft.displayName}
|
|
1165
|
+
onChange={(event) =>
|
|
1166
|
+
setDraft({ ...draft, displayName: event.target.value })
|
|
1167
|
+
}
|
|
1168
|
+
placeholder={t(
|
|
1169
|
+
"factoryRoute.automationDisplayNamePlaceholder",
|
|
1170
|
+
)}
|
|
1171
|
+
disabled={draft.canUpdate === false}
|
|
1172
|
+
/>
|
|
1173
|
+
</div>
|
|
1174
1174
|
<div className="grid gap-4 md:grid-cols-2">
|
|
1175
1175
|
<div className="grid gap-1.5">
|
|
1176
1176
|
<Label htmlFor="factory-automation-model">
|
|
@@ -1407,7 +1407,13 @@ function formatModelName(model: string | null | undefined) {
|
|
|
1407
1407
|
.join(" ");
|
|
1408
1408
|
}
|
|
1409
1409
|
|
|
1410
|
-
function InboxView({
|
|
1410
|
+
function InboxView({
|
|
1411
|
+
factoryId,
|
|
1412
|
+
t,
|
|
1413
|
+
}: {
|
|
1414
|
+
factoryId: string;
|
|
1415
|
+
t: ReturnType<typeof useT>;
|
|
1416
|
+
}) {
|
|
1411
1417
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
1412
1418
|
const [status, setStatus] = useState("");
|
|
1413
1419
|
const [selectedId, setSelectedId] = useState<string | null>(
|
|
@@ -1417,6 +1423,7 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1417
1423
|
const [verdict, setVerdict] = useState<Verdict | null>(null);
|
|
1418
1424
|
const selectedRowRef = useRef<HTMLButtonElement | null>(null);
|
|
1419
1425
|
const listQuery = useActionQuery("list-triage-items", {
|
|
1426
|
+
factoryId,
|
|
1420
1427
|
limit: 50,
|
|
1421
1428
|
...(status.trim()
|
|
1422
1429
|
? {
|
|
@@ -1434,7 +1441,7 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1434
1441
|
});
|
|
1435
1442
|
const detailQuery = useActionQuery(
|
|
1436
1443
|
"get-triage-item",
|
|
1437
|
-
selectedId ? { itemId: selectedId } : undefined,
|
|
1444
|
+
selectedId ? { factoryId, itemId: selectedId } : undefined,
|
|
1438
1445
|
{ enabled: Boolean(selectedId) },
|
|
1439
1446
|
);
|
|
1440
1447
|
const feedbackMutation = useActionMutation("record-triage-feedback");
|
|
@@ -1657,6 +1664,7 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1657
1664
|
];
|
|
1658
1665
|
if (!decision) return;
|
|
1659
1666
|
approveMutation.mutate({
|
|
1667
|
+
factoryId,
|
|
1660
1668
|
itemId: selectedItem.itemId ?? selectedItem.id ?? "",
|
|
1661
1669
|
decisionId: decision.decisionId,
|
|
1662
1670
|
confirm: true,
|
|
@@ -1711,6 +1719,7 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1711
1719
|
onClick={() => {
|
|
1712
1720
|
if (verdict)
|
|
1713
1721
|
feedbackMutation.mutate({
|
|
1722
|
+
factoryId,
|
|
1714
1723
|
decisionId: decision.decisionId,
|
|
1715
1724
|
verdict,
|
|
1716
1725
|
...(feedbackNote.trim()
|
|
@@ -1738,11 +1747,17 @@ function InboxView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1738
1747
|
);
|
|
1739
1748
|
}
|
|
1740
1749
|
|
|
1741
|
-
function RulesView({
|
|
1750
|
+
function RulesView({
|
|
1751
|
+
factoryId,
|
|
1752
|
+
t,
|
|
1753
|
+
}: {
|
|
1754
|
+
factoryId: string;
|
|
1755
|
+
t: ReturnType<typeof useT>;
|
|
1756
|
+
}) {
|
|
1742
1757
|
const [editingId, setEditingId] = useState<string | null>(null);
|
|
1743
1758
|
const [name, setName] = useState("");
|
|
1744
1759
|
const [prompt, setPrompt] = useState("");
|
|
1745
|
-
const rulesQuery = useActionQuery("list-triage-rules", {});
|
|
1760
|
+
const rulesQuery = useActionQuery("list-triage-rules", { factoryId });
|
|
1746
1761
|
const saveMutation = useActionMutation("save-triage-rule");
|
|
1747
1762
|
const rules = (rulesQuery.data ?? []) as TriageRule[];
|
|
1748
1763
|
function selectRule(rule: TriageRule) {
|
|
@@ -1828,6 +1843,7 @@ function RulesView({ t }: { t: ReturnType<typeof useT> }) {
|
|
|
1828
1843
|
onClick={() => {
|
|
1829
1844
|
if (!name.trim() || !prompt.trim()) return;
|
|
1830
1845
|
saveMutation.mutate({
|
|
1846
|
+
factoryId,
|
|
1831
1847
|
...(editingId ? { id: editingId } : {}),
|
|
1832
1848
|
name,
|
|
1833
1849
|
description: "",
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import { useT } from "@agent-native/core/client/i18n";
|
|
2
2
|
import { IconArrowLeft } from "@tabler/icons-react";
|
|
3
|
-
import { Link } from "react-router";
|
|
3
|
+
import { Link, useNavigate } from "react-router";
|
|
4
4
|
|
|
5
|
-
import { FactorySettingsView } from "@/components/factory/FactorySettingsView";
|
|
6
5
|
import { FactoryWorkspaceActions } from "@/components/factory/FactoryWorkspaceActions";
|
|
6
|
+
import { NewFactoryForm } from "@/components/factory/NewFactoryForm";
|
|
7
7
|
import { Button } from "@/components/ui/button";
|
|
8
8
|
|
|
9
|
-
export function
|
|
10
|
-
return [{ title: "Factory" }];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export default function FactorySettingsRoute() {
|
|
9
|
+
export default function NewFactoryRoute() {
|
|
14
10
|
const t = useT();
|
|
11
|
+
const navigate = useNavigate();
|
|
15
12
|
|
|
16
13
|
return (
|
|
17
14
|
<div className="flex h-full min-h-0 flex-col overflow-y-auto bg-background">
|
|
@@ -22,13 +19,19 @@ export default function FactorySettingsRoute() {
|
|
|
22
19
|
</Link>
|
|
23
20
|
</Button>
|
|
24
21
|
<h1 className="text-sm font-medium sm:text-base">
|
|
25
|
-
{t("factoryRoute.
|
|
22
|
+
{t("factoryRoute.createFactoryTitle")}
|
|
26
23
|
</h1>
|
|
27
24
|
<div className="ms-auto">
|
|
28
25
|
<FactoryWorkspaceActions />
|
|
29
26
|
</div>
|
|
30
27
|
</div>
|
|
31
|
-
<
|
|
28
|
+
<section className="flex flex-1 flex-col px-4 pb-8 lg:px-6">
|
|
29
|
+
<NewFactoryForm
|
|
30
|
+
onCreated={(factoryId) =>
|
|
31
|
+
navigate(`/factory?factoryId=${encodeURIComponent(factoryId)}`)
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
</section>
|
|
32
35
|
</div>
|
|
33
36
|
);
|
|
34
37
|
}
|
|
@@ -31,14 +31,20 @@ export const triageItems = table(
|
|
|
31
31
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
32
32
|
ownerEmail: text("owner_email").notNull(),
|
|
33
33
|
orgId: text("org_id"),
|
|
34
|
+
factoryId: text("factory_id"),
|
|
34
35
|
},
|
|
35
36
|
(item) => ({
|
|
36
|
-
|
|
37
|
+
orgFactoryDedupeUnique: uniqueIndex(
|
|
38
|
+
"factory_items_org_factory_dedupe_idx",
|
|
39
|
+
).on(item.orgId, item.factoryId, item.dedupeKey),
|
|
40
|
+
orgStatusIdx: index("factory_items_org_status_idx").on(
|
|
37
41
|
item.orgId,
|
|
38
|
-
item.
|
|
42
|
+
item.status,
|
|
43
|
+
item.updatedAt,
|
|
39
44
|
),
|
|
40
|
-
|
|
45
|
+
orgFactoryStatusIdx: index("factory_items_org_factory_status_idx").on(
|
|
41
46
|
item.orgId,
|
|
47
|
+
item.factoryId,
|
|
42
48
|
item.status,
|
|
43
49
|
item.updatedAt,
|
|
44
50
|
),
|
|
@@ -58,6 +64,7 @@ export const triageRules = table("factory_rules", {
|
|
|
58
64
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
59
65
|
ownerEmail: text("owner_email").notNull(),
|
|
60
66
|
orgId: text("org_id"),
|
|
67
|
+
factoryId: text("factory_id"),
|
|
61
68
|
});
|
|
62
69
|
|
|
63
70
|
export const triageDecisions = table("factory_decisions", {
|
|
@@ -73,6 +80,7 @@ export const triageDecisions = table("factory_decisions", {
|
|
|
73
80
|
createdAt: text("created_at").notNull().default(now()),
|
|
74
81
|
ownerEmail: text("owner_email").notNull(),
|
|
75
82
|
orgId: text("org_id"),
|
|
83
|
+
factoryId: text("factory_id"),
|
|
76
84
|
});
|
|
77
85
|
|
|
78
86
|
export const triageRuns = table("factory_runs", {
|
|
@@ -93,6 +101,7 @@ export const triageRuns = table("factory_runs", {
|
|
|
93
101
|
error: text("error"),
|
|
94
102
|
ownerEmail: text("owner_email").notNull(),
|
|
95
103
|
orgId: text("org_id"),
|
|
104
|
+
factoryId: text("factory_id"),
|
|
96
105
|
});
|
|
97
106
|
|
|
98
107
|
export const triageFeedback = table("factory_feedback", {
|
|
@@ -103,6 +112,7 @@ export const triageFeedback = table("factory_feedback", {
|
|
|
103
112
|
createdAt: text("created_at").notNull().default(now()),
|
|
104
113
|
ownerEmail: text("owner_email").notNull(),
|
|
105
114
|
orgId: text("org_id"),
|
|
115
|
+
factoryId: text("factory_id"),
|
|
106
116
|
});
|
|
107
117
|
|
|
108
118
|
export const triageConfig = table("factory_config", {
|
|
@@ -131,6 +141,7 @@ export const triageConfig = table("factory_config", {
|
|
|
131
141
|
updatedAt: text("updated_at").notNull().default(now()),
|
|
132
142
|
ownerEmail: text("owner_email").notNull(),
|
|
133
143
|
orgId: text("org_id"),
|
|
144
|
+
factoryId: text("factory_id"),
|
|
134
145
|
});
|
|
135
146
|
|
|
136
147
|
export const factoryAuditEvents = table(
|
|
@@ -151,12 +162,16 @@ export const factoryAuditEvents = table(
|
|
|
151
162
|
createdAt: text("created_at").notNull().default(now()),
|
|
152
163
|
ownerEmail: text("owner_email").notNull(),
|
|
153
164
|
orgId: text("org_id"),
|
|
165
|
+
factoryId: text("factory_id"),
|
|
154
166
|
},
|
|
155
167
|
(event) => ({
|
|
156
168
|
orgCreatedIdx: index("factory_audit_events_org_created_idx").on(
|
|
157
169
|
event.orgId,
|
|
158
170
|
event.createdAt,
|
|
159
171
|
),
|
|
172
|
+
orgFactoryCreatedIdx: index(
|
|
173
|
+
"factory_audit_events_org_factory_created_idx",
|
|
174
|
+
).on(event.orgId, event.factoryId, event.createdAt),
|
|
160
175
|
runCreatedIdx: index("factory_audit_events_run_created_idx").on(
|
|
161
176
|
event.orgId,
|
|
162
177
|
event.automationRunId,
|
|
@@ -91,6 +91,30 @@ export function normalizeFactoryGraph(value: unknown): FactoryGraph {
|
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
export function minimalFactoryGraph(
|
|
95
|
+
name: string,
|
|
96
|
+
description = "",
|
|
97
|
+
): FactoryGraph {
|
|
98
|
+
return {
|
|
99
|
+
version: 1,
|
|
100
|
+
name,
|
|
101
|
+
description,
|
|
102
|
+
executionMode: "blueprint",
|
|
103
|
+
nodes: [
|
|
104
|
+
{
|
|
105
|
+
id: "start",
|
|
106
|
+
label: "Start",
|
|
107
|
+
description:
|
|
108
|
+
"Add sources and rules to route work through this factory.",
|
|
109
|
+
kind: "decision",
|
|
110
|
+
provider: "factory",
|
|
111
|
+
position: { x: 240, y: 220 },
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
edges: [],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
94
118
|
export function defaultFactoryGraph(): FactoryGraph {
|
|
95
119
|
return {
|
|
96
120
|
version: 1,
|
|
@@ -62,6 +62,7 @@ export async function readFactoryDefinition(orgId: string, factoryId: string) {
|
|
|
62
62
|
|
|
63
63
|
export async function readFactoryMetrics(
|
|
64
64
|
orgId: string,
|
|
65
|
+
factoryId: string,
|
|
65
66
|
): Promise<FactoryMetricSummary> {
|
|
66
67
|
const [
|
|
67
68
|
totalItems,
|
|
@@ -72,13 +73,18 @@ export async function readFactoryMetrics(
|
|
|
72
73
|
runs,
|
|
73
74
|
completedRuns,
|
|
74
75
|
] = await Promise.all([
|
|
75
|
-
countRows(triageItems, orgId),
|
|
76
|
-
countRows(triageItems, orgId, eq(triageItems.source, "slack")),
|
|
77
|
-
countRows(triageItems, orgId, eq(triageItems.source, "github")),
|
|
78
|
-
countRows(triageDecisions, orgId),
|
|
79
|
-
countRows(
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
countRows(triageItems, orgId, factoryId),
|
|
77
|
+
countRows(triageItems, orgId, factoryId, eq(triageItems.source, "slack")),
|
|
78
|
+
countRows(triageItems, orgId, factoryId, eq(triageItems.source, "github")),
|
|
79
|
+
countRows(triageDecisions, orgId, factoryId),
|
|
80
|
+
countRows(
|
|
81
|
+
triageItems,
|
|
82
|
+
orgId,
|
|
83
|
+
factoryId,
|
|
84
|
+
eq(triageItems.status, "needs_manual"),
|
|
85
|
+
),
|
|
86
|
+
countRows(triageRuns, orgId, factoryId),
|
|
87
|
+
countRows(triageRuns, orgId, factoryId, eq(triageRuns.status, "completed")),
|
|
82
88
|
]);
|
|
83
89
|
|
|
84
90
|
return {
|
|
@@ -95,11 +101,12 @@ export async function readFactoryMetrics(
|
|
|
95
101
|
async function countRows(
|
|
96
102
|
table: typeof triageItems | typeof triageDecisions | typeof triageRuns,
|
|
97
103
|
orgId: string,
|
|
104
|
+
factoryId: string,
|
|
98
105
|
extra?: SQL,
|
|
99
106
|
) {
|
|
100
107
|
const where = extra
|
|
101
|
-
? and(eq(table.orgId, orgId), extra)
|
|
102
|
-
: eq(table.orgId, orgId);
|
|
108
|
+
? and(eq(table.orgId, orgId), eq(table.factoryId, factoryId), extra)
|
|
109
|
+
: and(eq(table.orgId, orgId), eq(table.factoryId, factoryId));
|
|
103
110
|
const row = (
|
|
104
111
|
await getDb().select({ value: count() }).from(table).where(where)
|
|
105
112
|
)[0];
|