@agent-native/dispatch 0.15.20 → 0.15.21

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.
Files changed (32) hide show
  1. package/dist/actions/provider-api-catalog.d.ts +1 -0
  2. package/dist/actions/provider-api-register.d.ts +14 -14
  3. package/dist/actions/remix-workspace-template.d.ts +20 -32
  4. package/dist/actions/set-app-creation-settings.js +2 -2
  5. package/dist/actions/set-app-creation-settings.js.map +1 -1
  6. package/dist/actions/start-workspace-app-creation.d.ts +1 -45
  7. package/dist/components/create-app-popover.d.ts.map +1 -1
  8. package/dist/components/create-app-popover.js +30 -2
  9. package/dist/components/create-app-popover.js.map +1 -1
  10. package/dist/components/layout/Layout.d.ts.map +1 -1
  11. package/dist/components/layout/Layout.js +1 -1
  12. package/dist/components/layout/Layout.js.map +1 -1
  13. package/dist/components/workspace-template-card.d.ts.map +1 -1
  14. package/dist/components/workspace-template-card.js +14 -1
  15. package/dist/components/workspace-template-card.js.map +1 -1
  16. package/dist/server/lib/app-creation-store.d.ts +36 -37
  17. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  18. package/dist/server/lib/app-creation-store.js +71 -6
  19. package/dist/server/lib/app-creation-store.js.map +1 -1
  20. package/dist/server/lib/provider-api.d.ts +1 -0
  21. package/dist/server/lib/provider-api.d.ts.map +1 -1
  22. package/dist/server/plugins/integrations.js +1 -1
  23. package/dist/server/plugins/integrations.js.map +1 -1
  24. package/package.json +2 -2
  25. package/src/actions/set-app-creation-settings.ts +4 -2
  26. package/src/components/create-app-popover.spec.tsx +249 -0
  27. package/src/components/create-app-popover.tsx +77 -10
  28. package/src/components/layout/Layout.tsx +9 -6
  29. package/src/components/workspace-template-card.tsx +11 -1
  30. package/src/server/lib/app-creation-store.spec.ts +252 -0
  31. package/src/server/lib/app-creation-store.ts +148 -8
  32. package/src/server/plugins/integrations.ts +1 -1
@@ -3,7 +3,8 @@ import fs from "node:fs";
3
3
  import path from "node:path";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { getDbExec } from "@agent-native/core/db";
6
- import { getBuilderBranchProjectId, getRequestContext, isIntegrationCallerRequest, resolveBuilderBranchProjectId, resolveBuilderCredentials, runBuilderAgent, } from "@agent-native/core/server";
6
+ import { deleteAppSecret, writeAppSecret, } from "@agent-native/core/secrets";
7
+ import { getBuilderBranchProjectId, getRequestContext, isIntegrationCallerRequest, resolveBuilderBranchProjectId, resolveBuilderCredentialsDetailed, runBuilderAgent, } from "@agent-native/core/server";
7
8
  import { getSetting, putSetting } from "@agent-native/core/settings";
8
9
  import { assertValidWorkspaceAppId } from "@agent-native/core/shared";
9
10
  import { identityKeyForIncoming } from "./dispatch-integrations.js";
@@ -11,6 +12,8 @@ import { currentOrgId, currentOwnerEmail, recordAudit, resolveLinkedOwner, } fro
11
12
  import { createRequest, listSecrets } from "./vault-store.js";
12
13
  import { grantWorkspaceResourcesToApp, listWorkspaceResourceOptions, } from "./workspace-resources-store.js";
13
14
  const SETTINGS_KEY = "dispatch-app-creation-settings";
15
+ const BUILDER_BRANCH_PROJECT_SECRET_KEY = "BUILDER_BRANCH_PROJECT_ID";
16
+ const BUILDER_BRANCH_PROJECT_SECRET_DESCRIPTION = "Builder project for cloud code-change branches (set in Dispatch)";
14
17
  const WORKSPACE_APP_METADATA_SETTINGS_KEY = "workspace-app-metadata";
15
18
  const WORKSPACE_APPS_ENV_KEY = "AGENT_NATIVE_WORKSPACE_APPS_JSON";
16
19
  const WORKSPACE_APPS_MANIFEST_FILE = "workspace-apps.json";
@@ -83,6 +86,13 @@ function scopedSettingsKey() {
83
86
  return `${SETTINGS_KEY}:org:${orgId}`;
84
87
  return `${SETTINGS_KEY}:user:${currentOwnerEmail()}`;
85
88
  }
89
+ function builderProjectSecretTarget() {
90
+ const orgId = currentOrgId();
91
+ if (orgId)
92
+ return { scope: "org", scopeId: orgId };
93
+ const email = currentOwnerEmail();
94
+ return email ? { scope: "workspace", scopeId: `solo:${email}` } : null;
95
+ }
86
96
  function workspaceAppMetadataSettingsKey() {
87
97
  const orgId = currentOrgId();
88
98
  if (orgId)
@@ -1158,6 +1168,28 @@ export async function setAppCreationSettings(input) {
1158
1168
  await assertCanManageAppCreationSettings();
1159
1169
  const builderProjectId = input.builderProjectId?.trim() || null;
1160
1170
  const raw = await readSettingsRecord();
1171
+ // The credential store, not this settings row, is what
1172
+ // `resolveBuilderBranchProjectId()` reads. Write it first: a saved setting
1173
+ // whose secret never landed reports the project as configured while cloud
1174
+ // code changes stay silently disabled.
1175
+ const secretTarget = builderProjectSecretTarget();
1176
+ if (secretTarget) {
1177
+ const ref = {
1178
+ key: BUILDER_BRANCH_PROJECT_SECRET_KEY,
1179
+ scope: secretTarget.scope,
1180
+ scopeId: secretTarget.scopeId,
1181
+ };
1182
+ if (builderProjectId) {
1183
+ await writeAppSecret({
1184
+ ...ref,
1185
+ value: builderProjectId,
1186
+ description: BUILDER_BRANCH_PROJECT_SECRET_DESCRIPTION,
1187
+ });
1188
+ }
1189
+ else {
1190
+ await deleteAppSecret(ref);
1191
+ }
1192
+ }
1161
1193
  await putSetting(scopedSettingsKey(), { ...raw, builderProjectId });
1162
1194
  await recordAudit({
1163
1195
  action: "settings.updated",
@@ -1292,6 +1324,7 @@ async function remoteAppCreationAuthorization() {
1292
1324
  return { ok: true };
1293
1325
  return {
1294
1326
  ok: false,
1327
+ reason: "identity-not-linked",
1295
1328
  message: "Messaging-triggered app creation is using the deployment default Dispatch owner. " +
1296
1329
  "Link the messaging identity to a Dispatch user with /link, start the app from Dispatch while signed in, or explicitly set ENABLE_BUILDER=true for this deployment.",
1297
1330
  };
@@ -1303,6 +1336,7 @@ async function remoteAppCreationAuthorization() {
1303
1336
  : "Synthetic integration";
1304
1337
  return {
1305
1338
  ok: false,
1339
+ reason: "identity-not-linked",
1306
1340
  message: `${source} app creation needs a trusted Dispatch owner before Builder can start a branch. ` +
1307
1341
  "Link the messaging identity to a Dispatch user with /link, start the app from Dispatch while signed in, or explicitly set ENABLE_BUILDER=true for this deployment.",
1308
1342
  };
@@ -1405,6 +1439,7 @@ export async function startWorkspaceAppCreation(input) {
1405
1439
  return {
1406
1440
  mode: "builder-unavailable",
1407
1441
  appId: initial.appId,
1442
+ reason: authorization.reason,
1408
1443
  message: authorization.message,
1409
1444
  };
1410
1445
  }
@@ -1450,10 +1485,40 @@ export async function startWorkspaceAppCreation(input) {
1450
1485
  message: "This requires a code change. Edit locally or use Builder.io to edit this code in the cloud and continue customizing the app any way you like.",
1451
1486
  };
1452
1487
  }
1488
+ let builderCreds;
1489
+ try {
1490
+ builderCreds = await resolveBuilderCredentialsDetailed();
1491
+ }
1492
+ catch {
1493
+ return {
1494
+ mode: "builder-unavailable",
1495
+ appId: built.appId,
1496
+ reason: "credential-store-unavailable",
1497
+ projectId: settings.builderProjectId,
1498
+ message: "Could not read your Builder connection just now. Try creating the app again in a moment.",
1499
+ };
1500
+ }
1501
+ if (builderCreds.lookupFailed) {
1502
+ return {
1503
+ mode: "builder-unavailable",
1504
+ appId: built.appId,
1505
+ reason: "credential-store-unavailable",
1506
+ projectId: settings.builderProjectId,
1507
+ message: "Could not read your Builder connection just now. Try creating the app again in a moment.",
1508
+ };
1509
+ }
1510
+ if (!builderCreds.privateKey || !builderCreds.publicKey) {
1511
+ return {
1512
+ mode: "builder-unavailable",
1513
+ appId: built.appId,
1514
+ reason: "builder-not-connected",
1515
+ projectId: settings.builderProjectId,
1516
+ message: "Connect your Builder account to create apps from Dispatch.",
1517
+ };
1518
+ }
1519
+ const builderUserId = builderCreds.userId || undefined;
1453
1520
  let result;
1454
1521
  try {
1455
- const builderCreds = await resolveBuilderCredentials().catch(() => null);
1456
- const builderUserId = builderCreds?.userId || undefined;
1457
1522
  result = normalizeBuilderRunResult(await runBuilderAgent({
1458
1523
  prompt,
1459
1524
  projectId: settings.builderProjectId,
@@ -1469,10 +1534,10 @@ export async function startWorkspaceAppCreation(input) {
1469
1534
  return {
1470
1535
  mode: "builder-unavailable",
1471
1536
  appId: built.appId,
1537
+ reason: "builder-error",
1472
1538
  projectId: settings.builderProjectId,
1473
- message: `Builder app creation is configured for project ${settings.builderProjectId}, ` +
1474
- `but it could not start yet: ${detail}. Connect Builder for this user, ` +
1475
- `link the messaging identity to that user, or configure deployment-managed Builder credentials for this workspace.`,
1539
+ detail,
1540
+ message: "Builder could not start the app branch. This is usually temporary try again.",
1476
1541
  };
1477
1542
  }
1478
1543
  await recordPendingWorkspaceApp({