@agent-native/dispatch 0.6.0 → 0.7.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/README.md +1 -1
- package/dist/actions/create-pylon-ticket.d.ts +3 -0
- package/dist/actions/create-pylon-ticket.d.ts.map +1 -0
- package/dist/actions/create-pylon-ticket.js +94 -0
- package/dist/actions/create-pylon-ticket.js.map +1 -0
- package/dist/actions/create-vault-grant.js +1 -1
- package/dist/actions/create-vault-grant.js.map +1 -1
- package/dist/actions/create-vault-secret.d.ts.map +1 -1
- package/dist/actions/create-vault-secret.js +4 -3
- package/dist/actions/create-vault-secret.js.map +1 -1
- package/dist/actions/get-vault-access-settings.d.ts +3 -0
- package/dist/actions/get-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/get-vault-access-settings.js +10 -0
- package/dist/actions/get-vault-access-settings.js.map +1 -0
- package/dist/actions/grant-vault-secrets-to-app.js +1 -1
- package/dist/actions/grant-vault-secrets-to-app.js.map +1 -1
- 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-integrations-catalog.js +1 -1
- package/dist/actions/list-integrations-catalog.js.map +1 -1
- package/dist/actions/list-vault-grants.js +1 -1
- package/dist/actions/list-vault-grants.js.map +1 -1
- package/dist/actions/list-workspace-apps.d.ts.map +1 -1
- package/dist/actions/list-workspace-apps.js +5 -1
- package/dist/actions/list-workspace-apps.js.map +1 -1
- package/dist/actions/set-vault-access-settings.d.ts +3 -0
- package/dist/actions/set-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/set-vault-access-settings.js +13 -0
- package/dist/actions/set-vault-access-settings.js.map +1 -0
- package/dist/actions/start-workspace-app-creation.d.ts.map +1 -1
- package/dist/actions/start-workspace-app-creation.js +6 -0
- package/dist/actions/start-workspace-app-creation.js.map +1 -1
- package/dist/actions/sync-vault-to-app.js +1 -1
- package/dist/actions/sync-vault-to-app.js.map +1 -1
- package/dist/actions/update-workspace-app-metadata.d.ts +3 -0
- package/dist/actions/update-workspace-app-metadata.d.ts.map +1 -0
- package/dist/actions/update-workspace-app-metadata.js +30 -0
- package/dist/actions/update-workspace-app-metadata.js.map +1 -0
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +4 -2
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/app-keys-popover.d.ts.map +1 -1
- package/dist/components/app-keys-popover.js +17 -5
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +38 -14
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts +4 -4
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +6 -6
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +10 -3
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +2 -2
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +41 -2
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/hooks/use-navigation-state.js +12 -5
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/catch-all-target.d.ts +2 -0
- package/dist/lib/catch-all-target.d.ts.map +1 -0
- package/dist/lib/catch-all-target.js +95 -0
- package/dist/lib/catch-all-target.js.map +1 -0
- package/dist/lib/workspace-apps.d.ts +9 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js.map +1 -1
- package/dist/routes/pages/$appId.d.ts +2 -24
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +42 -8
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/approval.d.ts.map +1 -1
- package/dist/routes/pages/approval.js +2 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/apps.$appId.d.ts.map +1 -1
- package/dist/routes/pages/apps.$appId.js +2 -1
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +20 -15
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +14 -1
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +25 -6
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/routes/pages/workspace.d.ts.map +1 -1
- package/dist/routes/pages/workspace.js +5 -3
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts +13 -0
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +295 -9
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/env-config.d.ts.map +1 -1
- package/dist/server/lib/env-config.js +5 -0
- package/dist/server/lib/env-config.js.map +1 -1
- package/dist/server/lib/onboarding-steps.d.ts +12 -0
- package/dist/server/lib/onboarding-steps.d.ts.map +1 -0
- package/dist/server/lib/onboarding-steps.js +47 -0
- package/dist/server/lib/onboarding-steps.js.map +1 -0
- package/dist/server/lib/vault-store.d.ts +55 -0
- package/dist/server/lib/vault-store.d.ts.map +1 -1
- package/dist/server/lib/vault-store.js +210 -41
- package/dist/server/lib/vault-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.d.ts.map +1 -1
- package/dist/server/plugins/agent-chat.js +2 -1
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/server/plugins/core-routes.d.ts.map +1 -1
- package/dist/server/plugins/core-routes.js +4 -0
- package/dist/server/plugins/core-routes.js.map +1 -1
- package/dist/server/plugins/integrations.js +2 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +13 -11
- package/src/actions/create-pylon-ticket.ts +109 -0
- package/src/actions/create-vault-grant.ts +1 -1
- package/src/actions/create-vault-secret.ts +4 -3
- package/src/actions/get-vault-access-settings.ts +11 -0
- package/src/actions/grant-vault-secrets-to-app.ts +1 -1
- package/src/actions/index.ts +8 -0
- package/src/actions/list-integrations-catalog.ts +1 -1
- package/src/actions/list-vault-grants.ts +1 -1
- package/src/actions/list-workspace-apps.ts +5 -1
- package/src/actions/set-vault-access-settings.ts +16 -0
- package/src/actions/start-workspace-app-creation.ts +8 -0
- package/src/actions/sync-vault-to-app.ts +1 -1
- package/src/actions/update-workspace-app-metadata.ts +32 -0
- package/src/actions/view-screen.ts +4 -1
- package/src/components/app-keys-popover.tsx +38 -8
- package/src/components/create-app-popover.tsx +47 -14
- package/src/components/dispatch-shell.tsx +16 -15
- package/src/components/layout/Layout.tsx +11 -5
- package/src/components/messaging-setup-panel.tsx +54 -39
- package/src/components/workspace-app-card.tsx +102 -0
- package/src/hooks/use-navigation-state.ts +10 -4
- package/src/lib/catch-all-target.spec.ts +218 -0
- package/src/lib/catch-all-target.ts +99 -0
- package/src/lib/workspace-apps.ts +9 -0
- package/src/routes/pages/$appId.tsx +45 -7
- package/src/routes/pages/approval.tsx +33 -3
- package/src/routes/pages/apps.$appId.tsx +6 -1
- package/src/routes/pages/integrations.tsx +57 -18
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/overview.tsx +69 -29
- package/src/routes/pages/vault.tsx +101 -21
- package/src/routes/pages/workspace.tsx +21 -3
- package/src/server/lib/app-creation-store.spec.ts +61 -2
- package/src/server/lib/app-creation-store.ts +386 -11
- package/src/server/lib/env-config.ts +5 -0
- package/src/server/lib/onboarding-steps.ts +49 -0
- package/src/server/lib/vault-store.spec.ts +69 -0
- package/src/server/lib/vault-store.ts +266 -49
- package/src/server/plugins/agent-chat.ts +2 -1
- package/src/server/plugins/core-routes.ts +5 -0
- package/src/server/plugins/integrations.ts +2 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
type WorkspaceAppAudience = "internal" | "public";
|
|
1
2
|
export interface WorkspaceAppSummary {
|
|
2
3
|
id: string;
|
|
3
4
|
name: string;
|
|
@@ -5,6 +6,9 @@ export interface WorkspaceAppSummary {
|
|
|
5
6
|
path: string;
|
|
6
7
|
url: string | null;
|
|
7
8
|
isDispatch: boolean;
|
|
9
|
+
audience: WorkspaceAppAudience;
|
|
10
|
+
publicPaths: string[];
|
|
11
|
+
protectedPaths: string[];
|
|
8
12
|
status?: "ready" | "pending";
|
|
9
13
|
statusLabel?: string;
|
|
10
14
|
builderUrl?: string | null;
|
|
@@ -25,6 +29,7 @@ export interface ListWorkspaceAppsOptions {
|
|
|
25
29
|
* when rendering the "Hidden apps" expander.
|
|
26
30
|
*/
|
|
27
31
|
includeArchived?: boolean;
|
|
32
|
+
audience?: WorkspaceAppAudience | "all";
|
|
28
33
|
}
|
|
29
34
|
export interface AvailableWorkspaceTemplate {
|
|
30
35
|
name: string;
|
|
@@ -52,6 +57,7 @@ export interface WorkspaceInfo {
|
|
|
52
57
|
/** Number of apps currently scaffolded under apps/. */
|
|
53
58
|
appCount: number;
|
|
54
59
|
}
|
|
60
|
+
export declare function generateWorkspaceAppDescription(prompt: string, appId: string): string;
|
|
55
61
|
export declare function archiveWorkspaceApp(input: {
|
|
56
62
|
appId: string;
|
|
57
63
|
}): Promise<{
|
|
@@ -75,6 +81,11 @@ export declare function getEnvBuilderProjectId(): string | null;
|
|
|
75
81
|
* "starter" / "dispatch" with no parent context).
|
|
76
82
|
*/
|
|
77
83
|
export declare function getWorkspaceInfo(): WorkspaceInfo;
|
|
84
|
+
export declare function updateWorkspaceAppMetadata(input: {
|
|
85
|
+
appId: string;
|
|
86
|
+
name?: string | null;
|
|
87
|
+
description?: string | null;
|
|
88
|
+
}): Promise<WorkspaceAppSummary>;
|
|
78
89
|
export declare function listWorkspaceApps(options?: ListWorkspaceAppsOptions): Promise<WorkspaceAppSummary[]>;
|
|
79
90
|
export declare function listAvailableWorkspaceTemplates(): Promise<AvailableWorkspaceTemplate[]>;
|
|
80
91
|
export declare function scaffoldWorkspaceAppFromTemplate(input: {
|
|
@@ -92,6 +103,7 @@ export declare function setAppCreationSettings(input: {
|
|
|
92
103
|
export declare function startWorkspaceAppCreation(input: {
|
|
93
104
|
prompt: string;
|
|
94
105
|
appId?: string | null;
|
|
106
|
+
description?: string | null;
|
|
95
107
|
template?: string | null;
|
|
96
108
|
secretIds?: string[];
|
|
97
109
|
resourceIds?: string[];
|
|
@@ -140,4 +152,5 @@ export declare function startWorkspaceAppCreation(input: {
|
|
|
140
152
|
message: string;
|
|
141
153
|
prompt?: undefined;
|
|
142
154
|
}>;
|
|
155
|
+
export {};
|
|
143
156
|
//# sourceMappingURL=app-creation-store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-creation-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/app-creation-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app-creation-store.d.ts","sourceRoot":"","sources":["../../../src/server/lib/app-creation-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,14 +3,15 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { getSetting, putSetting } from "@agent-native/core/settings";
|
|
6
|
+
import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
|
|
6
7
|
import { getBuilderBranchProjectId, getRequestContext, isIntegrationCallerRequest, resolveBuilderBranchProjectId, resolveBuilderCredentials, runBuilderAgent, } from "@agent-native/core/server";
|
|
7
8
|
import { getDbExec } from "@agent-native/core/db";
|
|
8
|
-
import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
|
|
9
9
|
import { currentOrgId, currentOwnerEmail, recordAudit, resolveLinkedOwner, } from "./dispatch-store.js";
|
|
10
10
|
import { identityKeyForIncoming } from "./dispatch-integrations.js";
|
|
11
11
|
import { createRequest, listSecrets } from "./vault-store.js";
|
|
12
12
|
import { grantWorkspaceResourcesToApp, listWorkspaceResourceOptions, } from "./workspace-resources-store.js";
|
|
13
13
|
const SETTINGS_KEY = "dispatch-app-creation-settings";
|
|
14
|
+
const WORKSPACE_APP_METADATA_SETTINGS_KEY = "workspace-app-metadata";
|
|
14
15
|
const WORKSPACE_APPS_ENV_KEY = "AGENT_NATIVE_WORKSPACE_APPS_JSON";
|
|
15
16
|
const WORKSPACE_APPS_MANIFEST_FILE = "workspace-apps.json";
|
|
16
17
|
const WORKSPACE_APPS_GATEWAY_PATH = "/_workspace/apps";
|
|
@@ -18,6 +19,7 @@ const WORKSPACE_APPS_GATEWAY_TIMEOUT_MS = 1_000;
|
|
|
18
19
|
const MAX_PENDING_APPS = 50;
|
|
19
20
|
const AGENT_CARD_PATH = "/.well-known/agent-card.json";
|
|
20
21
|
const AGENT_CARD_FETCH_TIMEOUT_MS = 1_500;
|
|
22
|
+
const DEFAULT_WORKSPACE_APP_AUDIENCE = "internal";
|
|
21
23
|
function readJson(file) {
|
|
22
24
|
try {
|
|
23
25
|
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
@@ -47,18 +49,145 @@ function titleCase(value) {
|
|
|
47
49
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
48
50
|
.join(" ");
|
|
49
51
|
}
|
|
52
|
+
function normalizeWhitespace(value) {
|
|
53
|
+
return value.replace(/\s+/g, " ").trim();
|
|
54
|
+
}
|
|
55
|
+
function ensureSentence(value) {
|
|
56
|
+
if (!value)
|
|
57
|
+
return value;
|
|
58
|
+
const capitalized = value.charAt(0).toUpperCase() + value.slice(1);
|
|
59
|
+
return /[.!?]$/.test(capitalized) ? capitalized : `${capitalized}.`;
|
|
60
|
+
}
|
|
61
|
+
function clipSentence(value, max = 180) {
|
|
62
|
+
if (value.length <= max)
|
|
63
|
+
return value;
|
|
64
|
+
const clipped = value
|
|
65
|
+
.slice(0, max - 1)
|
|
66
|
+
.replace(/\s+\S*$/, "")
|
|
67
|
+
.trim();
|
|
68
|
+
return `${clipped || value.slice(0, max - 1).trim()}…`;
|
|
69
|
+
}
|
|
70
|
+
export function generateWorkspaceAppDescription(prompt, appId) {
|
|
71
|
+
const cleaned = normalizeWhitespace(prompt)
|
|
72
|
+
.replace(/^(please\s+)?(build|create|make|generate|scaffold)\s+(me\s+|us\s+)?/i, "")
|
|
73
|
+
.replace(/^(an?\s+)?(workspace\s+)?(agent-native\s+)?(app|tool)\s+(that|to|for)\s+/i, "")
|
|
74
|
+
.replace(/^(an?\s+)?(dashboard|workspace|agent)\s+(that|to|for)\s+/i, "");
|
|
75
|
+
if (!cleaned)
|
|
76
|
+
return `Workspace app for ${titleCase(appId)}.`;
|
|
77
|
+
return clipSentence(ensureSentence(cleaned));
|
|
78
|
+
}
|
|
50
79
|
function scopedSettingsKey() {
|
|
51
80
|
const orgId = currentOrgId();
|
|
52
81
|
if (orgId)
|
|
53
82
|
return `${SETTINGS_KEY}:org:${orgId}`;
|
|
54
83
|
return `${SETTINGS_KEY}:user:${currentOwnerEmail()}`;
|
|
55
84
|
}
|
|
85
|
+
function workspaceAppMetadataSettingsKey() {
|
|
86
|
+
const orgId = currentOrgId();
|
|
87
|
+
if (orgId)
|
|
88
|
+
return `${WORKSPACE_APP_METADATA_SETTINGS_KEY}:org:${orgId}`;
|
|
89
|
+
return `${WORKSPACE_APP_METADATA_SETTINGS_KEY}:user:${currentOwnerEmail()}`;
|
|
90
|
+
}
|
|
56
91
|
async function readSettingsRecord() {
|
|
57
92
|
const raw = await getSetting(scopedSettingsKey()).catch(() => null);
|
|
58
93
|
return raw && typeof raw === "object" && !Array.isArray(raw)
|
|
59
94
|
? raw
|
|
60
95
|
: {};
|
|
61
96
|
}
|
|
97
|
+
function cleanOptionalText(value) {
|
|
98
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
99
|
+
}
|
|
100
|
+
function parseWorkspaceAppMetadataSettings(raw) {
|
|
101
|
+
const record = raw && typeof raw === "object" && !Array.isArray(raw)
|
|
102
|
+
? raw
|
|
103
|
+
: {};
|
|
104
|
+
const rawApps = record.apps &&
|
|
105
|
+
typeof record.apps === "object" &&
|
|
106
|
+
!Array.isArray(record.apps)
|
|
107
|
+
? record.apps
|
|
108
|
+
: {};
|
|
109
|
+
const apps = {};
|
|
110
|
+
for (const [id, value] of Object.entries(rawApps)) {
|
|
111
|
+
if (!id.trim() || !value || typeof value !== "object")
|
|
112
|
+
continue;
|
|
113
|
+
const item = value;
|
|
114
|
+
const override = {};
|
|
115
|
+
const name = cleanOptionalText(item.name);
|
|
116
|
+
const description = cleanOptionalText(item.description);
|
|
117
|
+
const sourcePrompt = cleanOptionalText(item.sourcePrompt);
|
|
118
|
+
const updatedAt = cleanOptionalText(item.updatedAt);
|
|
119
|
+
const updatedBy = cleanOptionalText(item.updatedBy);
|
|
120
|
+
if (name)
|
|
121
|
+
override.name = name;
|
|
122
|
+
if (description)
|
|
123
|
+
override.description = description;
|
|
124
|
+
if (item.generated === true)
|
|
125
|
+
override.generated = true;
|
|
126
|
+
if (sourcePrompt)
|
|
127
|
+
override.sourcePrompt = sourcePrompt;
|
|
128
|
+
if (updatedAt)
|
|
129
|
+
override.updatedAt = updatedAt;
|
|
130
|
+
if (updatedBy)
|
|
131
|
+
override.updatedBy = updatedBy;
|
|
132
|
+
if (Object.keys(override).length > 0)
|
|
133
|
+
apps[id.trim()] = override;
|
|
134
|
+
}
|
|
135
|
+
return { apps };
|
|
136
|
+
}
|
|
137
|
+
async function readWorkspaceAppMetadataSettings() {
|
|
138
|
+
const raw = await getSetting(workspaceAppMetadataSettingsKey()).catch(() => null);
|
|
139
|
+
return parseWorkspaceAppMetadataSettings(raw);
|
|
140
|
+
}
|
|
141
|
+
async function writeWorkspaceAppMetadataOverride(input) {
|
|
142
|
+
const key = workspaceAppMetadataSettingsKey();
|
|
143
|
+
const current = parseWorkspaceAppMetadataSettings(await getSetting(key).catch(() => null));
|
|
144
|
+
const appId = input.appId.trim();
|
|
145
|
+
const existing = current.apps[appId] ?? {};
|
|
146
|
+
const next = {
|
|
147
|
+
...existing,
|
|
148
|
+
updatedAt: new Date().toISOString(),
|
|
149
|
+
};
|
|
150
|
+
const name = cleanOptionalText(input.name);
|
|
151
|
+
const description = cleanOptionalText(input.description);
|
|
152
|
+
const sourcePrompt = cleanOptionalText(input.sourcePrompt);
|
|
153
|
+
const updatedBy = cleanOptionalText(input.updatedBy);
|
|
154
|
+
if (name)
|
|
155
|
+
next.name = name;
|
|
156
|
+
else
|
|
157
|
+
delete next.name;
|
|
158
|
+
if (description)
|
|
159
|
+
next.description = description;
|
|
160
|
+
else
|
|
161
|
+
delete next.description;
|
|
162
|
+
if (input.generated === true)
|
|
163
|
+
next.generated = true;
|
|
164
|
+
else if (input.generated === false)
|
|
165
|
+
delete next.generated;
|
|
166
|
+
if (sourcePrompt)
|
|
167
|
+
next.sourcePrompt = sourcePrompt;
|
|
168
|
+
if (updatedBy)
|
|
169
|
+
next.updatedBy = updatedBy;
|
|
170
|
+
current.apps[appId] = next;
|
|
171
|
+
await putSetting(key, { apps: current.apps });
|
|
172
|
+
return current;
|
|
173
|
+
}
|
|
174
|
+
function applyWorkspaceAppMetadataOverride(app, settings) {
|
|
175
|
+
const override = settings.apps[app.id];
|
|
176
|
+
if (!override)
|
|
177
|
+
return app;
|
|
178
|
+
const name = cleanOptionalText(override.name);
|
|
179
|
+
const description = cleanOptionalText(override.description);
|
|
180
|
+
const generated = override.generated === true;
|
|
181
|
+
const shouldApplyName = !!name && !generated;
|
|
182
|
+
const shouldApplyDescription = !!description && (!generated || !cleanOptionalText(app.description));
|
|
183
|
+
if (!shouldApplyName && !shouldApplyDescription)
|
|
184
|
+
return app;
|
|
185
|
+
return {
|
|
186
|
+
...app,
|
|
187
|
+
...(shouldApplyName ? { name } : {}),
|
|
188
|
+
...(shouldApplyDescription ? { description } : {}),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
62
191
|
function workspaceAppUrl(appPath) {
|
|
63
192
|
const base = process.env.WORKSPACE_GATEWAY_URL ||
|
|
64
193
|
process.env.APP_URL ||
|
|
@@ -88,6 +217,71 @@ function workspaceAppLink(appPath, explicitUrl) {
|
|
|
88
217
|
return urlValue;
|
|
89
218
|
}
|
|
90
219
|
}
|
|
220
|
+
function normalizeWorkspaceAppAudience(value) {
|
|
221
|
+
return value === "public" ? "public" : DEFAULT_WORKSPACE_APP_AUDIENCE;
|
|
222
|
+
}
|
|
223
|
+
function normalizeWorkspaceAppPathList(value) {
|
|
224
|
+
let rawPaths = [];
|
|
225
|
+
if (Array.isArray(value)) {
|
|
226
|
+
rawPaths = value;
|
|
227
|
+
}
|
|
228
|
+
else if (typeof value === "string") {
|
|
229
|
+
const trimmed = value.trim();
|
|
230
|
+
if (!trimmed)
|
|
231
|
+
return [];
|
|
232
|
+
try {
|
|
233
|
+
const parsed = JSON.parse(trimmed);
|
|
234
|
+
rawPaths = Array.isArray(parsed) ? parsed : [trimmed];
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
rawPaths = trimmed.split(",");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
const paths = rawPaths
|
|
241
|
+
.map((entry) => (typeof entry === "string" ? entry.trim() : ""))
|
|
242
|
+
.filter((entry) => entry.startsWith("/"))
|
|
243
|
+
.map((entry) => entry.length > 1 && entry.endsWith("/") ? entry.slice(0, -1) : entry);
|
|
244
|
+
return Array.from(new Set(paths));
|
|
245
|
+
}
|
|
246
|
+
function workspaceAppAudienceFromPackageJson(pkg) {
|
|
247
|
+
if (!pkg || typeof pkg !== "object" || Array.isArray(pkg))
|
|
248
|
+
return undefined;
|
|
249
|
+
const record = pkg;
|
|
250
|
+
const config = record["agent-native"] ?? record.agentNative;
|
|
251
|
+
const nested = config && typeof config === "object" && !Array.isArray(config)
|
|
252
|
+
? config
|
|
253
|
+
: {};
|
|
254
|
+
const raw = nested.workspaceApp?.audience ??
|
|
255
|
+
nested.workspace?.audience ??
|
|
256
|
+
nested.audience ??
|
|
257
|
+
record.workspaceAppAudience;
|
|
258
|
+
if (raw === undefined)
|
|
259
|
+
return undefined;
|
|
260
|
+
return normalizeWorkspaceAppAudience(raw);
|
|
261
|
+
}
|
|
262
|
+
function workspaceAppRouteAccessFromPackageJson(pkg) {
|
|
263
|
+
if (!pkg || typeof pkg !== "object" || Array.isArray(pkg)) {
|
|
264
|
+
return { publicPaths: [], protectedPaths: [] };
|
|
265
|
+
}
|
|
266
|
+
const record = pkg;
|
|
267
|
+
const config = record["agent-native"] ?? record.agentNative;
|
|
268
|
+
const nested = config && typeof config === "object" && !Array.isArray(config)
|
|
269
|
+
? config
|
|
270
|
+
: {};
|
|
271
|
+
return {
|
|
272
|
+
publicPaths: normalizeWorkspaceAppPathList(nested.workspaceApp?.publicPaths ??
|
|
273
|
+
nested.workspaceApp?.publicPagePaths ??
|
|
274
|
+
nested.workspace?.publicPaths ??
|
|
275
|
+
nested.publicPaths ??
|
|
276
|
+
record.workspaceAppPublicPaths),
|
|
277
|
+
protectedPaths: normalizeWorkspaceAppPathList(nested.workspaceApp?.protectedPaths ??
|
|
278
|
+
nested.workspaceApp?.privatePaths ??
|
|
279
|
+
nested.workspaceApp?.authRequiredPaths ??
|
|
280
|
+
nested.workspace?.protectedPaths ??
|
|
281
|
+
nested.protectedPaths ??
|
|
282
|
+
record.workspaceAppProtectedPaths),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
91
285
|
function parseWorkspaceAppsManifest(parsed) {
|
|
92
286
|
const rawApps = Array.isArray(parsed?.apps)
|
|
93
287
|
? parsed.apps
|
|
@@ -115,6 +309,11 @@ function parseWorkspaceAppsManifest(parsed) {
|
|
|
115
309
|
isDispatch: typeof entry.isDispatch === "boolean"
|
|
116
310
|
? entry.isDispatch
|
|
117
311
|
: id === "dispatch",
|
|
312
|
+
audience: entry.audience === undefined
|
|
313
|
+
? DEFAULT_WORKSPACE_APP_AUDIENCE
|
|
314
|
+
: normalizeWorkspaceAppAudience(entry.audience),
|
|
315
|
+
publicPaths: normalizeWorkspaceAppPathList(entry.publicPaths),
|
|
316
|
+
protectedPaths: normalizeWorkspaceAppPathList(entry.protectedPaths),
|
|
118
317
|
status: "ready",
|
|
119
318
|
};
|
|
120
319
|
})
|
|
@@ -164,6 +363,9 @@ function parsePendingWorkspaceApps(value) {
|
|
|
164
363
|
projectId: typeof record.projectId === "string" && record.projectId.trim()
|
|
165
364
|
? record.projectId.trim()
|
|
166
365
|
: null,
|
|
366
|
+
...(record.audience === undefined
|
|
367
|
+
? {}
|
|
368
|
+
: { audience: normalizeWorkspaceAppAudience(record.audience) }),
|
|
167
369
|
createdAt: typeof record.createdAt === "string" && record.createdAt.trim()
|
|
168
370
|
? record.createdAt.trim()
|
|
169
371
|
: now,
|
|
@@ -250,6 +452,9 @@ function pendingAppToSummary(app) {
|
|
|
250
452
|
path: app.path,
|
|
251
453
|
url: app.builderUrl,
|
|
252
454
|
isDispatch: false,
|
|
455
|
+
audience: app.audience ?? DEFAULT_WORKSPACE_APP_AUDIENCE,
|
|
456
|
+
publicPaths: [],
|
|
457
|
+
protectedPaths: [],
|
|
253
458
|
status: "pending",
|
|
254
459
|
statusLabel: "Building in Builder",
|
|
255
460
|
builderUrl: app.builderUrl,
|
|
@@ -363,7 +568,8 @@ async function recordPendingWorkspaceApp(input) {
|
|
|
363
568
|
const next = {
|
|
364
569
|
id: input.appId,
|
|
365
570
|
name: titleCase(input.appId),
|
|
366
|
-
description:
|
|
571
|
+
description: input.description ||
|
|
572
|
+
"Builder is creating this app. The workspace path becomes live after the branch is merged and deployed.",
|
|
367
573
|
path: `/${input.appId}`,
|
|
368
574
|
builderUrl: input.builderUrl?.trim() || null,
|
|
369
575
|
branchName: input.branchName?.trim() || null,
|
|
@@ -378,6 +584,13 @@ async function recordPendingWorkspaceApp(input) {
|
|
|
378
584
|
...pendingApps.filter((app) => app.id !== input.appId),
|
|
379
585
|
].slice(0, MAX_PENDING_APPS),
|
|
380
586
|
});
|
|
587
|
+
await writeWorkspaceAppMetadataOverride({
|
|
588
|
+
appId: input.appId,
|
|
589
|
+
description: input.description,
|
|
590
|
+
generated: true,
|
|
591
|
+
sourcePrompt: input.sourcePrompt,
|
|
592
|
+
updatedBy: currentOwnerEmail(),
|
|
593
|
+
});
|
|
381
594
|
await recordAudit({
|
|
382
595
|
action: "workspace-app.pending",
|
|
383
596
|
targetType: "workspace-app",
|
|
@@ -457,12 +670,13 @@ function readWorkspaceAppsFromFilesystem(workspaceRoot) {
|
|
|
457
670
|
return null;
|
|
458
671
|
const apps = fs
|
|
459
672
|
.readdirSync(appsDir, { withFileTypes: true })
|
|
460
|
-
.filter((entry) => entry.isDirectory())
|
|
673
|
+
.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."))
|
|
461
674
|
.map((entry) => {
|
|
462
675
|
const appDir = path.join(appsDir, entry.name);
|
|
463
676
|
const pkg = readJson(path.join(appDir, "package.json"));
|
|
464
677
|
if (!pkg)
|
|
465
678
|
return null;
|
|
679
|
+
const routeAccess = workspaceAppRouteAccessFromPackageJson(pkg);
|
|
466
680
|
return {
|
|
467
681
|
id: entry.name,
|
|
468
682
|
name: pkg.displayName || titleCase(entry.name),
|
|
@@ -470,6 +684,10 @@ function readWorkspaceAppsFromFilesystem(workspaceRoot) {
|
|
|
470
684
|
path: `/${entry.name}`,
|
|
471
685
|
url: workspaceAppUrl(`/${entry.name}`),
|
|
472
686
|
isDispatch: entry.name === "dispatch",
|
|
687
|
+
audience: workspaceAppAudienceFromPackageJson(pkg) ??
|
|
688
|
+
DEFAULT_WORKSPACE_APP_AUDIENCE,
|
|
689
|
+
publicPaths: routeAccess.publicPaths,
|
|
690
|
+
protectedPaths: routeAccess.protectedPaths,
|
|
473
691
|
status: "ready",
|
|
474
692
|
};
|
|
475
693
|
})
|
|
@@ -524,15 +742,69 @@ export function getWorkspaceInfo() {
|
|
|
524
742
|
};
|
|
525
743
|
}
|
|
526
744
|
async function applyArchivedAndPending(apps, options) {
|
|
527
|
-
const [withPending, archivedIds] = await Promise.all([
|
|
745
|
+
const [withPending, archivedIds, metadataSettings] = await Promise.all([
|
|
528
746
|
appendPendingWorkspaceApps(apps),
|
|
529
747
|
listArchivedAppIds(),
|
|
748
|
+
readWorkspaceAppMetadataSettings(),
|
|
530
749
|
]);
|
|
531
750
|
const archivedSet = new Set(archivedIds);
|
|
532
|
-
const annotated = withPending.map((app) =>
|
|
751
|
+
const annotated = withPending.map((app) => {
|
|
752
|
+
const withMetadata = applyWorkspaceAppMetadataOverride(app, metadataSettings);
|
|
753
|
+
return archivedSet.has(app.id)
|
|
754
|
+
? { ...withMetadata, archived: true }
|
|
755
|
+
: withMetadata;
|
|
756
|
+
});
|
|
533
757
|
return options.includeArchived
|
|
534
|
-
? annotated
|
|
535
|
-
: annotated.filter((app) => !app.archived);
|
|
758
|
+
? filterAppsByAudience(annotated, options.audience)
|
|
759
|
+
: filterAppsByAudience(annotated.filter((app) => !app.archived), options.audience);
|
|
760
|
+
}
|
|
761
|
+
function filterAppsByAudience(apps, audience) {
|
|
762
|
+
if (!audience || audience === "all")
|
|
763
|
+
return apps;
|
|
764
|
+
return apps.filter((app) => (app.audience ?? DEFAULT_WORKSPACE_APP_AUDIENCE) ===
|
|
765
|
+
normalizeWorkspaceAppAudience(audience));
|
|
766
|
+
}
|
|
767
|
+
export async function updateWorkspaceAppMetadata(input) {
|
|
768
|
+
await assertCanManageAppCreationSettings();
|
|
769
|
+
const appId = input.appId.trim();
|
|
770
|
+
assertValidWorkspaceAppId(appId);
|
|
771
|
+
const apps = await listWorkspaceApps({
|
|
772
|
+
includeAgentCards: false,
|
|
773
|
+
includeArchived: true,
|
|
774
|
+
});
|
|
775
|
+
const app = apps.find((candidate) => candidate.id === appId);
|
|
776
|
+
if (!app)
|
|
777
|
+
throw new Error(`Workspace app "${appId}" was not found.`);
|
|
778
|
+
// Treat undefined/null as "field omitted, leave existing value alone"; an
|
|
779
|
+
// explicit empty string clears the override (the app reverts to its
|
|
780
|
+
// built-in name / no description). Without this, a partial update that
|
|
781
|
+
// only touches one field silently wipes the other.
|
|
782
|
+
const name = input.name == null ? app.name : input.name.trim();
|
|
783
|
+
const description = input.description == null
|
|
784
|
+
? (app.description ?? undefined)
|
|
785
|
+
: input.description.trim();
|
|
786
|
+
await writeWorkspaceAppMetadataOverride({
|
|
787
|
+
appId,
|
|
788
|
+
name,
|
|
789
|
+
description,
|
|
790
|
+
generated: false,
|
|
791
|
+
updatedBy: currentOwnerEmail(),
|
|
792
|
+
});
|
|
793
|
+
await recordAudit({
|
|
794
|
+
action: "workspace-app.metadata-updated",
|
|
795
|
+
targetType: "workspace-app",
|
|
796
|
+
targetId: appId,
|
|
797
|
+
summary: `Updated workspace app details for ${name}`,
|
|
798
|
+
metadata: {
|
|
799
|
+
name,
|
|
800
|
+
descriptionConfigured: !!description,
|
|
801
|
+
},
|
|
802
|
+
});
|
|
803
|
+
const updated = (await listWorkspaceApps({
|
|
804
|
+
includeAgentCards: false,
|
|
805
|
+
includeArchived: true,
|
|
806
|
+
})).find((candidate) => candidate.id === appId);
|
|
807
|
+
return updated ?? { ...app, name, description };
|
|
536
808
|
}
|
|
537
809
|
export async function listWorkspaceApps(options = {}) {
|
|
538
810
|
const gatewayApps = await readWorkspaceAppsFromGateway();
|
|
@@ -559,6 +831,9 @@ export async function listWorkspaceApps(options = {}) {
|
|
|
559
831
|
path: "/dispatch",
|
|
560
832
|
url: workspaceAppUrl("/dispatch"),
|
|
561
833
|
isDispatch: true,
|
|
834
|
+
audience: DEFAULT_WORKSPACE_APP_AUDIENCE,
|
|
835
|
+
publicPaths: [],
|
|
836
|
+
protectedPaths: [],
|
|
562
837
|
status: "ready",
|
|
563
838
|
},
|
|
564
839
|
], options), options);
|
|
@@ -913,6 +1188,8 @@ function buildWorkspaceAppPrompt(input) {
|
|
|
913
1188
|
const appId = slugify(input.appId || "") ||
|
|
914
1189
|
slugify(input.prompt.replace(/\b(build|create|make|an?|the|app|tool)\b/gi, " ")) ||
|
|
915
1190
|
"new-app";
|
|
1191
|
+
const appDescription = input.description?.trim() ||
|
|
1192
|
+
generateWorkspaceAppDescription(input.prompt, appId);
|
|
916
1193
|
const selectedKeys = input.selectedKeys || [];
|
|
917
1194
|
const selectedResources = input.selectedResources || [];
|
|
918
1195
|
const resourceList = selectedResources.length
|
|
@@ -926,6 +1203,7 @@ function buildWorkspaceAppPrompt(input) {
|
|
|
926
1203
|
"Create a new agent-native app in this workspace.",
|
|
927
1204
|
"",
|
|
928
1205
|
`App name: ${appId}`,
|
|
1206
|
+
`App description: ${appDescription}`,
|
|
929
1207
|
`Template to start from: ${input.template || "starter"}`,
|
|
930
1208
|
`User prompt: ${input.prompt.trim()}`,
|
|
931
1209
|
"If the user mentions a product or company such as Granola, Loom, Superhuman, Linear, or Notion, treat it as product inspiration unless they explicitly ask to connect to that service. Do not invent or require third-party API keys like GRANOLA_API_KEY just because a product is named.",
|
|
@@ -956,11 +1234,13 @@ function buildWorkspaceAppPrompt(input) {
|
|
|
956
1234
|
"",
|
|
957
1235
|
"Branch readiness requirements before handing off:",
|
|
958
1236
|
"- The CLI auto-fills package.json name and displayName from the app id; only edit the description / scripts / dependencies if the app actually needs more than the template provides.",
|
|
1237
|
+
`- Save a concise, human-readable app description in apps/${appId}/package.json "description" so Dispatch, A2A discovery, and connected agents can describe what this app does. Use the description above or improve it based on the prompt.`,
|
|
959
1238
|
"- Do not add or update workspace-apps.json or .agent-native/workspace-apps.json unless the app needs an explicit external URL override; the root deploy generates the workspace app registry from apps/* and deploy metadata.",
|
|
960
1239
|
"- Update pnpm-lock.yaml when adding or changing dependencies so Netlify can install the branch reliably.",
|
|
961
1240
|
"- Update the app manifest/package/deploy metadata needed by the existing workspace deployment model; do not leave the branch relying only on uncommitted local state.",
|
|
962
|
-
"- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment.",
|
|
963
|
-
"-
|
|
1241
|
+
"- Verify the app's agent card/A2A metadata is ready so Dispatch can discover and delegate to the app after deployment. Every sibling workspace app should be usable over A2A by default through call-agent.",
|
|
1242
|
+
"- Give the app agent context that sibling workspace apps are available over A2A with names and descriptions from the workspace app registry; do not hardcode a stale app list.",
|
|
1243
|
+
"- Include a final verification note covering the registry entry, manifest/deploy metadata, relative same-origin routing, and agent-card readiness.",
|
|
964
1244
|
`When it is ready, start or update the workspace dev server and navigate the user to /${appId}.`,
|
|
965
1245
|
].join("\n"),
|
|
966
1246
|
};
|
|
@@ -990,6 +1270,7 @@ export async function startWorkspaceAppCreation(input) {
|
|
|
990
1270
|
const initial = buildWorkspaceAppPrompt({
|
|
991
1271
|
prompt: input.prompt,
|
|
992
1272
|
appId: input.appId,
|
|
1273
|
+
description: input.description,
|
|
993
1274
|
template: input.template,
|
|
994
1275
|
});
|
|
995
1276
|
assertValidWorkspaceAppId(initial.appId);
|
|
@@ -1013,11 +1294,14 @@ export async function startWorkspaceAppCreation(input) {
|
|
|
1013
1294
|
const built = buildWorkspaceAppPrompt({
|
|
1014
1295
|
prompt: input.prompt,
|
|
1015
1296
|
appId: input.appId,
|
|
1297
|
+
description: input.description,
|
|
1016
1298
|
template: input.template,
|
|
1017
1299
|
selectedKeys,
|
|
1018
1300
|
selectedResources,
|
|
1019
1301
|
});
|
|
1020
1302
|
const prompt = built.prompt;
|
|
1303
|
+
const appDescription = input.description?.trim() ||
|
|
1304
|
+
generateWorkspaceAppDescription(input.prompt, built.appId);
|
|
1021
1305
|
if (isLocal) {
|
|
1022
1306
|
await requestSelectedVaultKeys({
|
|
1023
1307
|
appId: built.appId,
|
|
@@ -1070,6 +1354,8 @@ export async function startWorkspaceAppCreation(input) {
|
|
|
1070
1354
|
await recordPendingWorkspaceApp({
|
|
1071
1355
|
appId: built.appId,
|
|
1072
1356
|
projectId: settings.builderProjectId,
|
|
1357
|
+
description: appDescription,
|
|
1358
|
+
sourcePrompt: input.prompt,
|
|
1073
1359
|
branchName: result.branchName,
|
|
1074
1360
|
builderUrl: result.url,
|
|
1075
1361
|
});
|