@agent-native/dispatch 0.2.20 → 0.4.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/dist/actions/archive-workspace-app.d.ts +3 -0
- package/dist/actions/archive-workspace-app.d.ts.map +1 -0
- package/dist/actions/archive-workspace-app.js +15 -0
- package/dist/actions/archive-workspace-app.js.map +1 -0
- package/dist/actions/get-agent-thread-debug.d.ts +3 -0
- package/dist/actions/get-agent-thread-debug.d.ts.map +1 -0
- package/dist/actions/get-agent-thread-debug.js +24 -0
- package/dist/actions/get-agent-thread-debug.js.map +1 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-agent-thread-sources.d.ts +3 -0
- package/dist/actions/list-agent-thread-sources.d.ts.map +1 -0
- package/dist/actions/list-agent-thread-sources.js +11 -0
- package/dist/actions/list-agent-thread-sources.js.map +1 -0
- package/dist/actions/list-available-workspace-templates.d.ts +3 -0
- package/dist/actions/list-available-workspace-templates.d.ts.map +1 -0
- package/dist/actions/list-available-workspace-templates.js +10 -0
- package/dist/actions/list-available-workspace-templates.js.map +1 -0
- package/dist/actions/navigate.js +1 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/remove-pending-workspace-app.d.ts +3 -0
- package/dist/actions/remove-pending-workspace-app.d.ts.map +1 -0
- package/dist/actions/remove-pending-workspace-app.js +15 -0
- package/dist/actions/remove-pending-workspace-app.js.map +1 -0
- package/dist/actions/scaffold-workspace-app.d.ts +3 -0
- package/dist/actions/scaffold-workspace-app.d.ts.map +1 -0
- package/dist/actions/scaffold-workspace-app.js +27 -0
- package/dist/actions/scaffold-workspace-app.js.map +1 -0
- package/dist/actions/search-agent-threads.d.ts +3 -0
- package/dist/actions/search-agent-threads.d.ts.map +1 -0
- package/dist/actions/search-agent-threads.js +25 -0
- package/dist/actions/search-agent-threads.js.map +1 -0
- package/dist/actions/unarchive-workspace-app.d.ts +3 -0
- package/dist/actions/unarchive-workspace-app.d.ts.map +1 -0
- package/dist/actions/unarchive-workspace-app.js +15 -0
- package/dist/actions/unarchive-workspace-app.js.map +1 -0
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +38 -0
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +8 -1
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/ui/command.d.ts +7 -7
- package/dist/hooks/use-navigation-state.js +5 -0
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +1 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/thread-debug.d.ts +5 -0
- package/dist/routes/pages/thread-debug.d.ts.map +1 -0
- package/dist/routes/pages/thread-debug.js +160 -0
- package/dist/routes/pages/thread-debug.js.map +1 -0
- package/dist/server/lib/app-creation-store.d.ts +40 -0
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +245 -6
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/thread-debug-store.d.ts +101 -0
- package/dist/server/lib/thread-debug-store.d.ts.map +1 -0
- package/dist/server/lib/thread-debug-store.js +587 -0
- package/dist/server/lib/thread-debug-store.js.map +1 -0
- package/package.json +2 -2
- package/src/actions/archive-workspace-app.ts +16 -0
- package/src/actions/get-agent-thread-debug.ts +25 -0
- package/src/actions/index.ts +12 -0
- package/src/actions/list-agent-thread-sources.ts +12 -0
- package/src/actions/list-available-workspace-templates.ts +11 -0
- package/src/actions/navigate.ts +1 -1
- package/src/actions/remove-pending-workspace-app.ts +16 -0
- package/src/actions/scaffold-workspace-app.ts +34 -0
- package/src/actions/search-agent-threads.ts +30 -0
- package/src/actions/unarchive-workspace-app.ts +16 -0
- package/src/actions/view-screen.ts +41 -0
- package/src/components/layout/Layout.tsx +8 -0
- package/src/hooks/use-navigation-state.ts +4 -0
- package/src/routes/index.ts +1 -0
- package/src/routes/pages/thread-debug.tsx +683 -0
- package/src/server/lib/app-creation-store.ts +312 -15
- package/src/server/lib/thread-debug-store.ts +779 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
1
2
|
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -52,10 +53,27 @@ export interface WorkspaceAppSummary {
|
|
|
52
53
|
a2aEndpointUrl?: string | null;
|
|
53
54
|
agentName?: string | null;
|
|
54
55
|
agentSkillsCount?: number | null;
|
|
56
|
+
archived?: boolean;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export interface ListWorkspaceAppsOptions {
|
|
58
60
|
includeAgentCards?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Include apps the current viewer has hidden (archived). Defaults to false
|
|
63
|
+
* so polling/UI callers see only the visible set; the apps page passes true
|
|
64
|
+
* when rendering the "Hidden apps" expander.
|
|
65
|
+
*/
|
|
66
|
+
includeArchived?: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface AvailableWorkspaceTemplate {
|
|
70
|
+
name: string;
|
|
71
|
+
label: string;
|
|
72
|
+
hint: string;
|
|
73
|
+
icon: string;
|
|
74
|
+
color: string;
|
|
75
|
+
colorRgb: string;
|
|
76
|
+
core: boolean;
|
|
59
77
|
}
|
|
60
78
|
|
|
61
79
|
export interface AppCreationSettings {
|
|
@@ -260,6 +278,76 @@ async function listPendingWorkspaceApps(): Promise<PendingWorkspaceApp[]> {
|
|
|
260
278
|
return parsePendingWorkspaceApps(raw.pendingApps);
|
|
261
279
|
}
|
|
262
280
|
|
|
281
|
+
function parseArchivedAppIds(value: unknown): string[] {
|
|
282
|
+
if (!Array.isArray(value)) return [];
|
|
283
|
+
const ids = value
|
|
284
|
+
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
|
|
285
|
+
.filter(Boolean);
|
|
286
|
+
return Array.from(new Set(ids));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
async function listArchivedAppIds(): Promise<string[]> {
|
|
290
|
+
const raw = await readSettingsRecord();
|
|
291
|
+
return parseArchivedAppIds(raw.archivedAppIds);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export async function archiveWorkspaceApp(input: {
|
|
295
|
+
appId: string;
|
|
296
|
+
}): Promise<{ archivedAppIds: string[] }> {
|
|
297
|
+
const appId = input.appId.trim();
|
|
298
|
+
if (!appId) throw new Error("appId is required");
|
|
299
|
+
const raw = await readSettingsRecord();
|
|
300
|
+
const current = parseArchivedAppIds(raw.archivedAppIds);
|
|
301
|
+
if (!current.includes(appId)) current.push(appId);
|
|
302
|
+
await putSetting(scopedSettingsKey(), { ...raw, archivedAppIds: current });
|
|
303
|
+
await recordAudit({
|
|
304
|
+
action: "workspace-app.archived",
|
|
305
|
+
targetType: "workspace-app",
|
|
306
|
+
targetId: appId,
|
|
307
|
+
summary: "Hid workspace app from the Apps list",
|
|
308
|
+
});
|
|
309
|
+
return { archivedAppIds: current };
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export async function unarchiveWorkspaceApp(input: {
|
|
313
|
+
appId: string;
|
|
314
|
+
}): Promise<{ archivedAppIds: string[] }> {
|
|
315
|
+
const appId = input.appId.trim();
|
|
316
|
+
if (!appId) throw new Error("appId is required");
|
|
317
|
+
const raw = await readSettingsRecord();
|
|
318
|
+
const current = parseArchivedAppIds(raw.archivedAppIds).filter(
|
|
319
|
+
(id) => id !== appId,
|
|
320
|
+
);
|
|
321
|
+
await putSetting(scopedSettingsKey(), { ...raw, archivedAppIds: current });
|
|
322
|
+
await recordAudit({
|
|
323
|
+
action: "workspace-app.unarchived",
|
|
324
|
+
targetType: "workspace-app",
|
|
325
|
+
targetId: appId,
|
|
326
|
+
summary: "Restored workspace app to the Apps list",
|
|
327
|
+
});
|
|
328
|
+
return { archivedAppIds: current };
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
export async function removePendingWorkspaceApp(input: {
|
|
332
|
+
appId: string;
|
|
333
|
+
}): Promise<{ removed: boolean }> {
|
|
334
|
+
const appId = input.appId.trim();
|
|
335
|
+
if (!appId) throw new Error("appId is required");
|
|
336
|
+
const raw = await readSettingsRecord();
|
|
337
|
+
const pending = parsePendingWorkspaceApps(raw.pendingApps);
|
|
338
|
+
const next = pending.filter((app) => app.id !== appId);
|
|
339
|
+
const removed = next.length !== pending.length;
|
|
340
|
+
if (!removed) return { removed: false };
|
|
341
|
+
await putSetting(scopedSettingsKey(), { ...raw, pendingApps: next });
|
|
342
|
+
await recordAudit({
|
|
343
|
+
action: "workspace-app.pending-removed",
|
|
344
|
+
targetType: "workspace-app",
|
|
345
|
+
targetId: appId,
|
|
346
|
+
summary: "Removed pending Builder app from the Apps list",
|
|
347
|
+
});
|
|
348
|
+
return { removed: true };
|
|
349
|
+
}
|
|
350
|
+
|
|
263
351
|
function pendingAppToSummary(app: PendingWorkspaceApp): WorkspaceAppSummary {
|
|
264
352
|
return {
|
|
265
353
|
id: app.id,
|
|
@@ -597,13 +685,30 @@ export function getWorkspaceInfo(): WorkspaceInfo {
|
|
|
597
685
|
};
|
|
598
686
|
}
|
|
599
687
|
|
|
688
|
+
async function applyArchivedAndPending(
|
|
689
|
+
apps: WorkspaceAppSummary[],
|
|
690
|
+
options: ListWorkspaceAppsOptions,
|
|
691
|
+
): Promise<WorkspaceAppSummary[]> {
|
|
692
|
+
const [withPending, archivedIds] = await Promise.all([
|
|
693
|
+
appendPendingWorkspaceApps(apps),
|
|
694
|
+
listArchivedAppIds(),
|
|
695
|
+
]);
|
|
696
|
+
const archivedSet = new Set(archivedIds);
|
|
697
|
+
const annotated = withPending.map((app) =>
|
|
698
|
+
archivedSet.has(app.id) ? { ...app, archived: true } : app,
|
|
699
|
+
);
|
|
700
|
+
return options.includeArchived
|
|
701
|
+
? annotated
|
|
702
|
+
: annotated.filter((app) => !app.archived);
|
|
703
|
+
}
|
|
704
|
+
|
|
600
705
|
export async function listWorkspaceApps(
|
|
601
706
|
options: ListWorkspaceAppsOptions = {},
|
|
602
707
|
): Promise<WorkspaceAppSummary[]> {
|
|
603
708
|
const gatewayApps = await readWorkspaceAppsFromGateway();
|
|
604
709
|
if (gatewayApps) {
|
|
605
710
|
return maybeIncludeAgentCards(
|
|
606
|
-
await
|
|
711
|
+
await applyArchivedAndPending(gatewayApps, options),
|
|
607
712
|
options,
|
|
608
713
|
);
|
|
609
714
|
}
|
|
@@ -615,7 +720,7 @@ export async function listWorkspaceApps(
|
|
|
615
720
|
: null;
|
|
616
721
|
if (localFilesystemApps) {
|
|
617
722
|
return maybeIncludeAgentCards(
|
|
618
|
-
await
|
|
723
|
+
await applyArchivedAndPending(localFilesystemApps, options),
|
|
619
724
|
options,
|
|
620
725
|
);
|
|
621
726
|
}
|
|
@@ -624,35 +729,227 @@ export async function listWorkspaceApps(
|
|
|
624
729
|
readWorkspaceAppsFromEnv() ?? readWorkspaceAppsFromManifestFile();
|
|
625
730
|
if (manifestApps) {
|
|
626
731
|
return maybeIncludeAgentCards(
|
|
627
|
-
await
|
|
732
|
+
await applyArchivedAndPending(manifestApps, options),
|
|
628
733
|
options,
|
|
629
734
|
);
|
|
630
735
|
}
|
|
631
736
|
|
|
632
737
|
if (!workspaceRoot) {
|
|
633
738
|
return maybeIncludeAgentCards(
|
|
634
|
-
await
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
739
|
+
await applyArchivedAndPending(
|
|
740
|
+
[
|
|
741
|
+
{
|
|
742
|
+
id: "dispatch",
|
|
743
|
+
name: "Dispatch",
|
|
744
|
+
description: "Workspace control plane",
|
|
745
|
+
path: "/dispatch",
|
|
746
|
+
url: workspaceAppUrl("/dispatch"),
|
|
747
|
+
isDispatch: true,
|
|
748
|
+
status: "ready",
|
|
749
|
+
},
|
|
750
|
+
],
|
|
751
|
+
options,
|
|
752
|
+
),
|
|
645
753
|
options,
|
|
646
754
|
);
|
|
647
755
|
}
|
|
648
756
|
|
|
649
757
|
const apps = readWorkspaceAppsFromFilesystem(workspaceRoot) ?? [];
|
|
650
758
|
return maybeIncludeAgentCards(
|
|
651
|
-
await
|
|
759
|
+
await applyArchivedAndPending(apps, options),
|
|
652
760
|
options,
|
|
653
761
|
);
|
|
654
762
|
}
|
|
655
763
|
|
|
764
|
+
/**
|
|
765
|
+
* First-party templates the user can scaffold into this workspace via the
|
|
766
|
+
* Apps page tiles. Inlined here (rather than importing from
|
|
767
|
+
* `@agent-native/shared-app-config`) because the published `@agent-native/dispatch`
|
|
768
|
+
* package has no `workspace:*` runtime dependencies. Keep in sync with
|
|
769
|
+
* `packages/core/src/cli/templates-meta.ts`.
|
|
770
|
+
*/
|
|
771
|
+
const ADDABLE_TEMPLATES: AvailableWorkspaceTemplate[] = [
|
|
772
|
+
{
|
|
773
|
+
name: "mail",
|
|
774
|
+
label: "Mail",
|
|
775
|
+
hint: "Email client with keyboard shortcuts and AI triage",
|
|
776
|
+
icon: "Mail",
|
|
777
|
+
color: "#3B82F6",
|
|
778
|
+
colorRgb: "59 130 246",
|
|
779
|
+
core: true,
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
name: "calendar",
|
|
783
|
+
label: "Calendar",
|
|
784
|
+
hint: "Manage events, sync, and public booking",
|
|
785
|
+
icon: "CalendarDays",
|
|
786
|
+
color: "#8B5CF6",
|
|
787
|
+
colorRgb: "139 92 246",
|
|
788
|
+
core: true,
|
|
789
|
+
},
|
|
790
|
+
{
|
|
791
|
+
name: "content",
|
|
792
|
+
label: "Content",
|
|
793
|
+
hint: "Write and organize with agent assistance",
|
|
794
|
+
icon: "FileText",
|
|
795
|
+
color: "#10B981",
|
|
796
|
+
colorRgb: "16 185 129",
|
|
797
|
+
core: true,
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
name: "slides",
|
|
801
|
+
label: "Slides",
|
|
802
|
+
hint: "Generate and edit React presentations",
|
|
803
|
+
icon: "GalleryHorizontal",
|
|
804
|
+
color: "#EC4899",
|
|
805
|
+
colorRgb: "236 72 153",
|
|
806
|
+
core: true,
|
|
807
|
+
},
|
|
808
|
+
{
|
|
809
|
+
name: "clips",
|
|
810
|
+
label: "Clips",
|
|
811
|
+
hint: "Screen recording, meeting notes, and voice dictation",
|
|
812
|
+
icon: "ScreenShare",
|
|
813
|
+
color: "#625DF5",
|
|
814
|
+
colorRgb: "98 93 245",
|
|
815
|
+
core: true,
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
name: "analytics",
|
|
819
|
+
label: "Analytics",
|
|
820
|
+
hint: "Connect data sources, prompt for charts",
|
|
821
|
+
icon: "BarChart2",
|
|
822
|
+
color: "#F59E0B",
|
|
823
|
+
colorRgb: "245 158 11",
|
|
824
|
+
core: true,
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "forms",
|
|
828
|
+
label: "Forms",
|
|
829
|
+
hint: "Create, edit, and manage forms",
|
|
830
|
+
icon: "ClipboardList",
|
|
831
|
+
color: "#06B6D4",
|
|
832
|
+
colorRgb: "6 182 212",
|
|
833
|
+
core: true,
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
name: "design",
|
|
837
|
+
label: "Design",
|
|
838
|
+
hint: "Create and edit visual designs with agent assistance",
|
|
839
|
+
icon: "Brush",
|
|
840
|
+
color: "#F472B6",
|
|
841
|
+
colorRgb: "244 114 182",
|
|
842
|
+
core: true,
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
name: "videos",
|
|
846
|
+
label: "Video",
|
|
847
|
+
hint: "Video editing with Remotion",
|
|
848
|
+
icon: "Video",
|
|
849
|
+
color: "#EF4444",
|
|
850
|
+
colorRgb: "239 68 68",
|
|
851
|
+
core: false,
|
|
852
|
+
},
|
|
853
|
+
];
|
|
854
|
+
|
|
855
|
+
export async function listAvailableWorkspaceTemplates(): Promise<
|
|
856
|
+
AvailableWorkspaceTemplate[]
|
|
857
|
+
> {
|
|
858
|
+
const installed = new Set(
|
|
859
|
+
(await listWorkspaceApps({ includeArchived: true })).map((app) => app.id),
|
|
860
|
+
);
|
|
861
|
+
return ADDABLE_TEMPLATES.filter((tpl) => !installed.has(tpl.name));
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
const SCAFFOLD_TIMEOUT_MS = 90_000;
|
|
865
|
+
|
|
866
|
+
export async function scaffoldWorkspaceAppFromTemplate(input: {
|
|
867
|
+
template: string;
|
|
868
|
+
appId?: string | null;
|
|
869
|
+
}): Promise<{ appId: string; template: string; output: string }> {
|
|
870
|
+
if (!isLocalAppCreationRuntime()) {
|
|
871
|
+
throw new Error(
|
|
872
|
+
"Scaffolding from Dispatch is only available in local development. " +
|
|
873
|
+
"Use the Builder branch flow on a deployed workspace.",
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
const template = input.template.trim();
|
|
877
|
+
if (!template) throw new Error("template is required");
|
|
878
|
+
if (!ADDABLE_TEMPLATES.some((tpl) => tpl.name === template)) {
|
|
879
|
+
throw new Error(`Unknown template "${template}".`);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const appId = (input.appId?.trim() || template).toLowerCase();
|
|
883
|
+
assertValidWorkspaceAppId(appId);
|
|
884
|
+
|
|
885
|
+
const workspaceRoot = findWorkspaceRoot();
|
|
886
|
+
if (!workspaceRoot) {
|
|
887
|
+
throw new Error("No agent-native workspace detected for scaffolding.");
|
|
888
|
+
}
|
|
889
|
+
const appDir = path.join(workspaceRoot, "apps", appId);
|
|
890
|
+
if (fs.existsSync(appDir)) {
|
|
891
|
+
throw new Error(`apps/${appId} already exists.`);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
const output = await runScaffoldCli({
|
|
895
|
+
cwd: workspaceRoot,
|
|
896
|
+
args: ["add-app", appId, "--template", template],
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
await recordAudit({
|
|
900
|
+
action: "workspace-app.scaffolded",
|
|
901
|
+
targetType: "workspace-app",
|
|
902
|
+
targetId: appId,
|
|
903
|
+
summary: `Scaffolded apps/${appId} from ${template}`,
|
|
904
|
+
metadata: { template },
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
return { appId, template, output };
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function runScaffoldCli(input: {
|
|
911
|
+
cwd: string;
|
|
912
|
+
args: string[];
|
|
913
|
+
}): Promise<string> {
|
|
914
|
+
return new Promise((resolve, reject) => {
|
|
915
|
+
const child = spawn("pnpm", ["exec", "agent-native", ...input.args], {
|
|
916
|
+
cwd: input.cwd,
|
|
917
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
918
|
+
env: { ...process.env, CI: "1", FORCE_COLOR: "0" },
|
|
919
|
+
});
|
|
920
|
+
let stdout = "";
|
|
921
|
+
let stderr = "";
|
|
922
|
+
child.stdout?.on("data", (chunk) => {
|
|
923
|
+
stdout += String(chunk);
|
|
924
|
+
});
|
|
925
|
+
child.stderr?.on("data", (chunk) => {
|
|
926
|
+
stderr += String(chunk);
|
|
927
|
+
});
|
|
928
|
+
const timer = setTimeout(() => {
|
|
929
|
+
child.kill("SIGTERM");
|
|
930
|
+
reject(
|
|
931
|
+
new Error(
|
|
932
|
+
`Scaffold timed out after ${Math.round(SCAFFOLD_TIMEOUT_MS / 1000)}s`,
|
|
933
|
+
),
|
|
934
|
+
);
|
|
935
|
+
}, SCAFFOLD_TIMEOUT_MS);
|
|
936
|
+
timer.unref();
|
|
937
|
+
child.on("error", (err) => {
|
|
938
|
+
clearTimeout(timer);
|
|
939
|
+
reject(err);
|
|
940
|
+
});
|
|
941
|
+
child.on("exit", (code) => {
|
|
942
|
+
clearTimeout(timer);
|
|
943
|
+
if (code === 0) {
|
|
944
|
+
resolve([stdout, stderr].filter(Boolean).join("\n").trim());
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const detail = (stderr || stdout || "").trim() || `exit code ${code}`;
|
|
948
|
+
reject(new Error(`Scaffold failed: ${detail}`));
|
|
949
|
+
});
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
|
|
656
953
|
export async function getAppCreationSettings(): Promise<AppCreationSettings> {
|
|
657
954
|
const envBuilderProjectId = getEnvBuilderProjectId();
|
|
658
955
|
const resolvedBuilderProjectId = await resolveBuilderBranchProjectId();
|