@agent-native/dispatch 0.40.30-nightly-20261021064625 → 0.40.30

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 (117) hide show
  1. package/CHANGELOG.md +7 -47
  2. package/dist/actions/connect-external-agent.d.ts.map +1 -1
  3. package/dist/actions/connect-external-agent.js +12 -13
  4. package/dist/actions/connect-external-agent.js.map +1 -1
  5. package/dist/actions/create-workspace-resource.d.ts +13 -13
  6. package/dist/actions/delete-destination.d.ts +12 -12
  7. package/dist/actions/delete-workspace-resource.d.ts +13 -13
  8. package/dist/actions/import-agent.d.ts +13 -13
  9. package/dist/actions/index.d.ts.map +1 -1
  10. package/dist/actions/index.js +8 -0
  11. package/dist/actions/index.js.map +1 -1
  12. package/dist/actions/inspect-connect-agent-card.d.ts +5 -0
  13. package/dist/actions/inspect-connect-agent-card.d.ts.map +1 -0
  14. package/dist/actions/inspect-connect-agent-card.js +15 -0
  15. package/dist/actions/inspect-connect-agent-card.js.map +1 -0
  16. package/dist/actions/install-curated-community-app.d.ts +36 -0
  17. package/dist/actions/install-curated-community-app.d.ts.map +1 -0
  18. package/dist/actions/install-curated-community-app.js +26 -0
  19. package/dist/actions/install-curated-community-app.js.map +1 -0
  20. package/dist/actions/list-connect-marketplace-apps.d.ts +3 -0
  21. package/dist/actions/list-connect-marketplace-apps.d.ts.map +1 -0
  22. package/dist/actions/list-connect-marketplace-apps.js +15 -0
  23. package/dist/actions/list-connect-marketplace-apps.js.map +1 -0
  24. package/dist/actions/list-connected-agents.d.ts +2 -0
  25. package/dist/actions/list-curated-community-apps.d.ts +3 -0
  26. package/dist/actions/list-curated-community-apps.d.ts.map +1 -0
  27. package/dist/actions/list-curated-community-apps.js +10 -0
  28. package/dist/actions/list-curated-community-apps.js.map +1 -0
  29. package/dist/actions/provider-api-register.d.ts +14 -14
  30. package/dist/actions/remix-workspace-template.d.ts +6 -0
  31. package/dist/actions/update-workspace-app-metadata.d.ts +1 -0
  32. package/dist/actions/update-workspace-app-metadata.js +26 -5
  33. package/dist/actions/update-workspace-app-metadata.js.map +1 -1
  34. package/dist/components/community-apps-section.d.ts +2 -0
  35. package/dist/components/community-apps-section.d.ts.map +1 -0
  36. package/dist/components/community-apps-section.js +90 -0
  37. package/dist/components/community-apps-section.js.map +1 -0
  38. package/dist/components/workspace-app-card.d.ts.map +1 -1
  39. package/dist/components/workspace-app-card.js +63 -9
  40. package/dist/components/workspace-app-card.js.map +1 -1
  41. package/dist/lib/connect-apps.d.ts +1 -2
  42. package/dist/lib/connect-apps.d.ts.map +1 -1
  43. package/dist/lib/connect-apps.js +41 -65
  44. package/dist/lib/connect-apps.js.map +1 -1
  45. package/dist/lib/workspace-apps.d.ts +1 -0
  46. package/dist/lib/workspace-apps.d.ts.map +1 -1
  47. package/dist/lib/workspace-apps.js.map +1 -1
  48. package/dist/routes/pages/apps.d.ts.map +1 -1
  49. package/dist/routes/pages/apps.js +2 -1
  50. package/dist/routes/pages/apps.js.map +1 -1
  51. package/dist/routes/pages/connect.d.ts.map +1 -1
  52. package/dist/routes/pages/connect.js +5 -7
  53. package/dist/routes/pages/connect.js.map +1 -1
  54. package/dist/server/index.d.ts +2 -0
  55. package/dist/server/index.d.ts.map +1 -1
  56. package/dist/server/index.js +2 -0
  57. package/dist/server/index.js.map +1 -1
  58. package/dist/server/lib/app-creation-store.d.ts +11 -1
  59. package/dist/server/lib/app-creation-store.d.ts.map +1 -1
  60. package/dist/server/lib/app-creation-store.js +258 -39
  61. package/dist/server/lib/app-creation-store.js.map +1 -1
  62. package/dist/server/lib/community-apps.d.ts +45 -0
  63. package/dist/server/lib/community-apps.d.ts.map +1 -0
  64. package/dist/server/lib/community-apps.js +267 -0
  65. package/dist/server/lib/community-apps.js.map +1 -0
  66. package/dist/server/lib/community-source.d.ts +19 -0
  67. package/dist/server/lib/community-source.d.ts.map +1 -0
  68. package/dist/server/lib/community-source.js +118 -0
  69. package/dist/server/lib/community-source.js.map +1 -0
  70. package/dist/server/lib/connect-apps.d.ts +4 -0
  71. package/dist/server/lib/connect-apps.d.ts.map +1 -0
  72. package/dist/server/lib/connect-apps.js +99 -0
  73. package/dist/server/lib/connect-apps.js.map +1 -0
  74. package/dist/server/lib/org-apps-directory-cache.d.ts +20 -0
  75. package/dist/server/lib/org-apps-directory-cache.d.ts.map +1 -0
  76. package/dist/server/lib/org-apps-directory-cache.js +44 -0
  77. package/dist/server/lib/org-apps-directory-cache.js.map +1 -0
  78. package/dist/server/plugins/integrations.js +3 -3
  79. package/dist/server/plugins/integrations.js.map +1 -1
  80. package/dist/shared/labs.d.ts +2 -0
  81. package/dist/shared/labs.d.ts.map +1 -0
  82. package/dist/shared/labs.js +8 -0
  83. package/dist/shared/labs.js.map +1 -0
  84. package/package.json +5 -4
  85. package/src/actions/connect-external-agent.spec.ts +101 -3
  86. package/src/actions/connect-external-agent.ts +12 -11
  87. package/src/actions/index.spec.ts +13 -0
  88. package/src/actions/index.ts +8 -0
  89. package/src/actions/inspect-connect-agent-card.ts +17 -0
  90. package/src/actions/install-curated-community-app.ts +32 -0
  91. package/src/actions/list-connect-marketplace-apps.ts +17 -0
  92. package/src/actions/list-curated-community-apps.ts +12 -0
  93. package/src/actions/update-workspace-app-metadata.spec.ts +25 -0
  94. package/src/actions/update-workspace-app-metadata.ts +48 -24
  95. package/src/components/community-apps-section.tsx +224 -0
  96. package/src/components/workspace-app-card.spec.tsx +226 -1
  97. package/src/components/workspace-app-card.tsx +115 -12
  98. package/src/lib/connect-apps.spec.ts +118 -66
  99. package/src/lib/connect-apps.ts +47 -82
  100. package/src/lib/workspace-apps.ts +1 -0
  101. package/src/routes/pages/apps.spec.tsx +201 -1
  102. package/src/routes/pages/apps.tsx +3 -0
  103. package/src/routes/pages/connect.spec.tsx +53 -6
  104. package/src/routes/pages/connect.tsx +14 -11
  105. package/src/server/index.ts +9 -0
  106. package/src/server/lib/app-creation-store.spec.ts +539 -11
  107. package/src/server/lib/app-creation-store.ts +332 -41
  108. package/src/server/lib/community-apps.spec.ts +367 -0
  109. package/src/server/lib/community-apps.ts +372 -0
  110. package/src/server/lib/community-source.spec.ts +151 -0
  111. package/src/server/lib/community-source.ts +186 -0
  112. package/src/server/lib/connect-apps.ts +149 -0
  113. package/src/server/lib/org-apps-directory-cache.spec.ts +71 -0
  114. package/src/server/lib/org-apps-directory-cache.ts +66 -0
  115. package/src/server/plugins/integrations.spec.ts +60 -0
  116. package/src/server/plugins/integrations.ts +3 -3
  117. package/src/shared/labs.ts +9 -0
@@ -0,0 +1,10 @@
1
+ import { defineAction } from "@agent-native/core/action";
2
+ import { z } from "zod";
3
+ import { listCuratedCommunityApps } from "../server/lib/community-apps.js";
4
+ export default defineAction({
5
+ description: "List reviewed, pinned community app templates that can be installed in the associated workspace. This catalog is separate from deployed agents in Connect.",
6
+ schema: z.object({}),
7
+ http: { method: "GET" },
8
+ run: async () => listCuratedCommunityApps(),
9
+ });
10
+ //# sourceMappingURL=list-curated-community-apps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-curated-community-apps.js","sourceRoot":"","sources":["../../src/actions/list-curated-community-apps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,4JAA4J;IAC9J,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACpB,IAAI,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE;IACvB,GAAG,EAAE,KAAK,IAAI,EAAE,CAAC,wBAAwB,EAAE;CAC5C,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport { z } from \"zod\";\n\nimport { listCuratedCommunityApps } from \"../server/lib/community-apps.js\";\n\nexport default defineAction({\n description:\n \"List reviewed, pinned community app templates that can be installed in the associated workspace. This catalog is separate from deployed agents in Connect.\",\n schema: z.object({}),\n http: { method: \"GET\" },\n run: async () => listCuratedCommunityApps(),\n});\n"]}
@@ -47,10 +47,7 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
47
47
  notes?: string | undefined;
48
48
  scope?: "org" | "user" | undefined;
49
49
  }, {
50
- message?: undefined;
51
50
  provider?: undefined;
52
- id?: undefined;
53
- deleted?: undefined;
54
51
  providers: {
55
52
  id: string;
56
53
  label: string;
@@ -62,44 +59,47 @@ declare const _default: import("node_modules/@agent-native/core/dist").ActionDef
62
59
  }[];
63
60
  count: number;
64
61
  found?: undefined;
62
+ deleted?: undefined;
65
63
  registered?: undefined;
64
+ id?: undefined;
66
65
  label?: undefined;
67
- } | {
68
66
  message?: undefined;
69
- id?: undefined;
70
- count?: undefined;
71
- deleted?: undefined;
67
+ } | {
72
68
  providers?: undefined;
69
+ count?: undefined;
73
70
  found: boolean;
74
71
  provider: import("node_modules/@agent-native/core/dist/provider-api").CustomProviderConfig;
72
+ deleted?: undefined;
75
73
  registered?: undefined;
74
+ id?: undefined;
76
75
  label?: undefined;
77
- } | {
78
76
  message?: undefined;
77
+ } | {
79
78
  provider?: undefined;
80
- count?: undefined;
81
- deleted?: undefined;
82
79
  providers?: undefined;
80
+ count?: undefined;
83
81
  found: boolean;
84
82
  id: string;
83
+ deleted?: undefined;
85
84
  registered?: undefined;
86
85
  label?: undefined;
87
- } | {
88
86
  message?: undefined;
87
+ } | {
89
88
  provider?: undefined;
90
- count?: undefined;
91
89
  providers?: undefined;
90
+ count?: undefined;
92
91
  found?: undefined;
93
92
  deleted: boolean;
94
93
  id: string;
95
94
  registered?: undefined;
96
95
  label?: undefined;
96
+ message?: undefined;
97
97
  } | {
98
98
  provider?: undefined;
99
- count?: undefined;
100
- deleted?: undefined;
101
99
  providers?: undefined;
100
+ count?: undefined;
102
101
  found?: undefined;
102
+ deleted?: undefined;
103
103
  registered: boolean;
104
104
  id: string;
105
105
  label: string;
@@ -50,6 +50,12 @@ declare const _default: import("@agent-native/core/action").ActionDefinition<{
50
50
  appId: string;
51
51
  prompt: string;
52
52
  message: string;
53
+ attachments?: Array<{
54
+ type: "file";
55
+ name: string;
56
+ contentType: string;
57
+ text: string;
58
+ }>;
53
59
  sourceTemplate: import("../server/lib/curated-workspace-templates.js").CuratedWorkspaceTemplate;
54
60
  }>;
55
61
  export default _default;
@@ -2,6 +2,7 @@ declare const _default: import("@agent-native/core/action").ActionDefinition<{
2
2
  appId: string;
3
3
  name?: string | null | undefined;
4
4
  description?: string | null | undefined;
5
+ whenToUse?: string[] | null | undefined;
5
6
  }, import("../server/lib/app-creation-store.js").WorkspaceAppSummary>;
6
7
  export default _default;
7
8
  //# sourceMappingURL=update-workspace-app-metadata.d.ts.map
@@ -1,10 +1,11 @@
1
1
  import { defineAction } from "@agent-native/core/action";
2
- import { getWorkspaceAppIdValidationError } from "@agent-native/core/shared";
2
+ import { getWorkspaceAppIdValidationError, parseAgentProfileMetadata, } from "@agent-native/core/shared";
3
3
  import { z } from "zod";
4
4
  import { updateWorkspaceAppMetadata } from "../server/lib/app-creation-store.js";
5
5
  export default defineAction({
6
- description: "Update the human-editable display name and description Dispatch uses for a workspace app. Workspace members can edit these shared details, which are also used as connected-agent/A2A context.",
7
- schema: z.object({
6
+ description: "Update a workspace app's display name, description, and when-to-use profile. Only organization owners and admins can edit these shared details.",
7
+ schema: z
8
+ .object({
8
9
  appId: z
9
10
  .string()
10
11
  .max(64)
@@ -20,10 +21,30 @@ export default defineAction({
20
21
  .describe("Human-readable app name"),
21
22
  description: z
22
23
  .string()
23
- .max(500)
24
+ .max(1000)
24
25
  .optional()
25
26
  .nullable()
26
- .describe("Human-readable app description"),
27
+ .describe("Human-readable app description, up to 1,000 characters"),
28
+ whenToUse: z
29
+ .array(z.string())
30
+ .max(6)
31
+ .optional()
32
+ .nullable()
33
+ .describe("Example requests that indicate when this app is useful"),
34
+ })
35
+ .superRefine(({ description, whenToUse }, context) => {
36
+ if (description == null && whenToUse == null)
37
+ return;
38
+ const profile = parseAgentProfileMetadata({
39
+ ...(description != null ? { description } : {}),
40
+ ...(whenToUse != null ? { whenToUse } : {}),
41
+ });
42
+ if (!profile) {
43
+ context.addIssue({
44
+ code: "custom",
45
+ message: "Use a description up to 1,000 characters and up to 6 non-empty examples, each no longer than 140 characters.",
46
+ });
47
+ }
27
48
  }),
28
49
  run: async (args) => updateWorkspaceAppMetadata(args),
29
50
  });
@@ -1 +1 @@
1
- {"version":3,"file":"update-workspace-app-metadata.js","sourceRoot":"","sources":["../../src/actions/update-workspace-app-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,gMAAgM;IAClM,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,EAAE,CAAC;aACP,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,gCAAgC,CAAC,KAAK,CAAC,EAAE;YAC3D,OAAO,EACL,yEAAyE;SAC5E,CAAC;aACD,QAAQ,CAAC,iDAAiD,CAAC;QAC9D,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,yBAAyB,CAAC;QACtC,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,gCAAgC,CAAC;KAC9C,CAAC;IACF,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;CACtD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport { getWorkspaceAppIdValidationError } from \"@agent-native/core/shared\";\nimport { z } from \"zod\";\n\nimport { updateWorkspaceAppMetadata } from \"../server/lib/app-creation-store.js\";\n\nexport default defineAction({\n description:\n \"Update the human-editable display name and description Dispatch uses for a workspace app. Workspace members can edit these shared details, which are also used as connected-agent/A2A context.\",\n schema: z.object({\n appId: z\n .string()\n .max(64)\n .refine((appId) => !getWorkspaceAppIdValidationError(appId), {\n message:\n \"Use a non-reserved app id with lowercase letters, numbers, and hyphens.\",\n })\n .describe(\"Workspace app id, matching the apps/<id> folder\"),\n name: z\n .string()\n .max(120)\n .optional()\n .nullable()\n .describe(\"Human-readable app name\"),\n description: z\n .string()\n .max(500)\n .optional()\n .nullable()\n .describe(\"Human-readable app description\"),\n }),\n run: async (args) => updateWorkspaceAppMetadata(args),\n});\n"]}
1
+ {"version":3,"file":"update-workspace-app-metadata.js","sourceRoot":"","sources":["../../src/actions/update-workspace-app-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EACL,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF,eAAe,YAAY,CAAC;IAC1B,WAAW,EACT,iJAAiJ;IACnJ,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,EAAE,CAAC;aACP,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,gCAAgC,CAAC,KAAK,CAAC,EAAE;YAC3D,OAAO,EACL,yEAAyE;SAC5E,CAAC;aACD,QAAQ,CAAC,iDAAiD,CAAC;QAC9D,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,yBAAyB,CAAC;QACtC,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,GAAG,CAAC,IAAI,CAAC;aACT,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;QACrE,SAAS,EAAE,CAAC;aACT,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;aACjB,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,wDAAwD,CAAC;KACtE,CAAC;SACD,WAAW,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,EAAE;QACnD,IAAI,WAAW,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI;YAAE,OAAO;QACrD,MAAM,OAAO,GAAG,yBAAyB,CAAC;YACxC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/C,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5C,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,QAAQ,CAAC;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EACL,8GAA8G;aACjH,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IACJ,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC;CACtD,CAAC,CAAC","sourcesContent":["import { defineAction } from \"@agent-native/core/action\";\nimport {\n getWorkspaceAppIdValidationError,\n parseAgentProfileMetadata,\n} from \"@agent-native/core/shared\";\nimport { z } from \"zod\";\n\nimport { updateWorkspaceAppMetadata } from \"../server/lib/app-creation-store.js\";\n\nexport default defineAction({\n description:\n \"Update a workspace app's display name, description, and when-to-use profile. Only organization owners and admins can edit these shared details.\",\n schema: z\n .object({\n appId: z\n .string()\n .max(64)\n .refine((appId) => !getWorkspaceAppIdValidationError(appId), {\n message:\n \"Use a non-reserved app id with lowercase letters, numbers, and hyphens.\",\n })\n .describe(\"Workspace app id, matching the apps/<id> folder\"),\n name: z\n .string()\n .max(120)\n .optional()\n .nullable()\n .describe(\"Human-readable app name\"),\n description: z\n .string()\n .max(1000)\n .optional()\n .nullable()\n .describe(\"Human-readable app description, up to 1,000 characters\"),\n whenToUse: z\n .array(z.string())\n .max(6)\n .optional()\n .nullable()\n .describe(\"Example requests that indicate when this app is useful\"),\n })\n .superRefine(({ description, whenToUse }, context) => {\n if (description == null && whenToUse == null) return;\n const profile = parseAgentProfileMetadata({\n ...(description != null ? { description } : {}),\n ...(whenToUse != null ? { whenToUse } : {}),\n });\n if (!profile) {\n context.addIssue({\n code: \"custom\",\n message:\n \"Use a description up to 1,000 characters and up to 6 non-empty examples, each no longer than 140 characters.\",\n });\n }\n }),\n run: async (args) => updateWorkspaceAppMetadata(args),\n});\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function CommunityAppsSection(): import("node_modules/@types/react/index.js").JSX.Element | null;
2
+ //# sourceMappingURL=community-apps-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"community-apps-section.d.ts","sourceRoot":"","sources":["../../src/components/community-apps-section.tsx"],"names":[],"mappings":"AAsDA,wBAAgB,oBAAoB,oEAyKnC"}
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { sendToAgentChat } from "@agent-native/core/client/agent-chat";
3
+ import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
4
+ import { useT } from "@agent-native/core/client/i18n";
5
+ import { useLab } from "@agent-native/core/client/labs";
6
+ import { IconArrowUpRight, IconCircleCheck, IconPlus, } from "@tabler/icons-react";
7
+ import { useState } from "react";
8
+ import { toast } from "sonner";
9
+ import { COMMUNITY_APPS_LAB } from "../shared/labs.js";
10
+ import { ActionQueryError } from "./action-query-error.js";
11
+ import { AppIcon } from "./app-icon.js";
12
+ import { AppList, AppListRow } from "./app-list-row.js";
13
+ import { Badge } from "./ui/badge.js";
14
+ import { Button } from "./ui/button.js";
15
+ import { Skeleton } from "./ui/skeleton.js";
16
+ import { Spinner } from "./ui/spinner.js";
17
+ function pinnedSourceUrl(source) {
18
+ return ("https://github.com/" +
19
+ source.repo +
20
+ "/tree/" +
21
+ source.ref +
22
+ "/" +
23
+ source.templatePath);
24
+ }
25
+ export function CommunityAppsSection() {
26
+ const t = useT();
27
+ const enabled = useLab(COMMUNITY_APPS_LAB);
28
+ const [installingId, setInstallingId] = useState(null);
29
+ const catalogQuery = useActionQuery("list-curated-community-apps", {}, { enabled });
30
+ const workspaceAppsQuery = useActionQuery("list-workspace-apps", {
31
+ includeAgentCards: false,
32
+ includeArchived: true,
33
+ });
34
+ const install = useActionMutation("install-curated-community-app", {
35
+ onSuccess: (result) => {
36
+ const mode = result?.mode;
37
+ const message = result?.message;
38
+ if (mode === "builder") {
39
+ toast.success(t("dispatch.pages.communityAppsInstallStarted"));
40
+ }
41
+ else if (mode === "pending") {
42
+ toast.info(t("dispatch.pages.communityAppsPending"));
43
+ }
44
+ else if (mode === "already-installed") {
45
+ toast.success(t("dispatch.pages.communityAppsAlreadyInstalled"));
46
+ }
47
+ else if (mode === "builder-unavailable" || mode === "app-id-taken") {
48
+ toast.error(message || t("dispatch.pages.communityAppsInstallFailed"));
49
+ }
50
+ else if (mode === "local-agent") {
51
+ sendToAgentChat({
52
+ message: result?.prompt ||
53
+ t("dispatch.pages.communityAppsLocalRequestReady"),
54
+ attachments: result?.attachments,
55
+ submit: true,
56
+ type: "code",
57
+ newTab: true,
58
+ reuseEmptyTab: true,
59
+ });
60
+ toast.info(t("dispatch.pages.communityAppsLocalRequestReady"));
61
+ }
62
+ else {
63
+ toast.error(t("dispatch.pages.communityAppsInstallFailed"));
64
+ }
65
+ setInstallingId(null);
66
+ void catalogQuery.refetch();
67
+ void workspaceAppsQuery.refetch();
68
+ },
69
+ onError: () => {
70
+ setInstallingId(null);
71
+ toast.error(t("dispatch.pages.communityAppsInstallFailed"));
72
+ },
73
+ });
74
+ if (!enabled)
75
+ return null;
76
+ return (_jsxs("section", { className: "space-y-3 border-t pt-6", children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: t("dispatch.pages.communityApps") }), catalogQuery.isError ? (_jsx(ActionQueryError, { error: catalogQuery.error, onRetry: () => void catalogQuery.refetch() })) : catalogQuery.isLoading ? (_jsx(AppList, { className: "divide-y rounded-xl border", children: _jsxs("div", { className: "flex items-center gap-3 px-4 py-3.5", children: [_jsx(Skeleton, { className: "size-8 rounded-lg" }), _jsx(Skeleton, { className: "h-4 w-40" })] }) })) : catalogQuery.data?.length ? (_jsx(AppList, { className: "divide-y rounded-xl border", children: catalogQuery.data.map((source) => (_jsxs(AppListRow, { className: "border-b-0", children: [_jsx(AppIcon, { id: source.id, name: source.name, size: "sm" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex min-w-0 flex-wrap items-center gap-2", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: source.name }), source.installed ? (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(IconCircleCheck, { size: 13 }), t("dispatch.pages.communityAppsInstalled")] })) : source.pending ? (_jsx(Badge, { variant: "secondary", children: t("dispatch.pages.communityAppsPending") })) : null] }), source.description ? (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: source.description })) : null, _jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground", children: [_jsxs("span", { children: [t("dispatch.pages.communityAppsLicense"), ": ", source.license] }), _jsxs("a", { href: pinnedSourceUrl(source), target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1 underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [t("dispatch.pages.communityAppsTemplateSource"), _jsx(IconArrowUpRight, { size: 12, "aria-hidden": "true" })] })] })] }), source.installable ? (_jsxs(Button, { type: "button", size: "sm", variant: "outline", disabled: install.isPending, onClick: () => {
77
+ setInstallingId(source.id);
78
+ install.mutate({ sourceId: source.id });
79
+ }, children: [install.isPending && installingId === source.id ? (_jsx(Spinner, { className: "mr-1.5" })) : (_jsx(IconPlus, { size: 14, className: "mr-1.5" })), install.isPending && installingId === source.id
80
+ ? t("dispatch.pages.communityAppsInstalling")
81
+ : t("dispatch.pages.communityAppsInstall")] })) : !source.installed &&
82
+ !source.pending &&
83
+ source.installUnavailableReason === "workspace-required" ? (_jsx("span", { className: "max-w-48 text-right text-xs text-muted-foreground", children: t("dispatch.pages.communityAppsWorkspaceRequired") })) : !source.installed &&
84
+ !source.pending &&
85
+ source.installUnavailableReason === "app-id-conflict" ? (_jsx("span", { className: "max-w-48 text-right text-xs text-muted-foreground", children: t("dispatch.pages.communityAppsIdConflict") })) : !source.installed &&
86
+ !source.pending &&
87
+ source.installUnavailableReason ===
88
+ "builder-install-unverified" ? (_jsx("span", { className: "max-w-48 text-right text-xs text-muted-foreground", children: t("dispatch.pages.communityAppsBuilderInstallUnavailable") })) : null] }, source.id))) })) : (_jsx("p", { className: "text-sm text-muted-foreground", children: t("dispatch.pages.communityAppsEmpty") }))] }));
89
+ }
90
+ //# sourceMappingURL=community-apps-section.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"community-apps-section.js","sourceRoot":"","sources":["../../src/components/community-apps-section.tsx"],"names":[],"mappings":"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","sourcesContent":["import { sendToAgentChat } from \"@agent-native/core/client/agent-chat\";\nimport {\n useActionMutation,\n useActionQuery,\n} from \"@agent-native/core/client/hooks\";\nimport { useT } from \"@agent-native/core/client/i18n\";\nimport { useLab } from \"@agent-native/core/client/labs\";\nimport {\n IconArrowUpRight,\n IconCircleCheck,\n IconPlus,\n} from \"@tabler/icons-react\";\nimport { useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport { COMMUNITY_APPS_LAB } from \"../shared/labs.js\";\nimport { ActionQueryError } from \"./action-query-error\";\nimport { AppIcon } from \"./app-icon\";\nimport { AppList, AppListRow } from \"./app-list-row\";\nimport { Badge } from \"./ui/badge\";\nimport { Button } from \"./ui/button\";\nimport { Skeleton } from \"./ui/skeleton\";\nimport { Spinner } from \"./ui/spinner\";\n\ninterface CommunityAppSource {\n id: string;\n name: string;\n description?: string;\n appId: string;\n repo: string;\n ref: string;\n license: string;\n provenance: string;\n templatePath: string;\n installed: boolean;\n pending: boolean;\n installable: boolean;\n installUnavailableReason?:\n | \"workspace-required\"\n | \"app-id-conflict\"\n | \"builder-install-unverified\";\n}\n\nfunction pinnedSourceUrl(source: CommunityAppSource): string {\n return (\n \"https://github.com/\" +\n source.repo +\n \"/tree/\" +\n source.ref +\n \"/\" +\n source.templatePath\n );\n}\n\nexport function CommunityAppsSection() {\n const t = useT();\n const enabled = useLab(COMMUNITY_APPS_LAB);\n const [installingId, setInstallingId] = useState<string | null>(null);\n const catalogQuery = useActionQuery<CommunityAppSource[]>(\n \"list-curated-community-apps\" as never,\n {},\n { enabled },\n );\n const workspaceAppsQuery = useActionQuery(\"list-workspace-apps\", {\n includeAgentCards: false,\n includeArchived: true,\n });\n const install = useActionMutation(\"install-curated-community-app\", {\n onSuccess: (result) => {\n const mode = (result as { mode?: string } | null)?.mode;\n const message = (result as { message?: string } | null)?.message;\n if (mode === \"builder\") {\n toast.success(t(\"dispatch.pages.communityAppsInstallStarted\"));\n } else if (mode === \"pending\") {\n toast.info(t(\"dispatch.pages.communityAppsPending\"));\n } else if (mode === \"already-installed\") {\n toast.success(t(\"dispatch.pages.communityAppsAlreadyInstalled\"));\n } else if (mode === \"builder-unavailable\" || mode === \"app-id-taken\") {\n toast.error(message || t(\"dispatch.pages.communityAppsInstallFailed\"));\n } else if (mode === \"local-agent\") {\n sendToAgentChat({\n message:\n (result as { prompt?: string } | null)?.prompt ||\n t(\"dispatch.pages.communityAppsLocalRequestReady\"),\n attachments: (\n result as {\n attachments?: Array<{\n type: \"file\";\n name: string;\n contentType: string;\n text: string;\n }>;\n } | null\n )?.attachments,\n submit: true,\n type: \"code\",\n newTab: true,\n reuseEmptyTab: true,\n });\n toast.info(t(\"dispatch.pages.communityAppsLocalRequestReady\"));\n } else {\n toast.error(t(\"dispatch.pages.communityAppsInstallFailed\"));\n }\n setInstallingId(null);\n void catalogQuery.refetch();\n void workspaceAppsQuery.refetch();\n },\n onError: () => {\n setInstallingId(null);\n toast.error(t(\"dispatch.pages.communityAppsInstallFailed\"));\n },\n });\n\n if (!enabled) return null;\n\n return (\n <section className=\"space-y-3 border-t pt-6\">\n <h2 className=\"text-sm font-semibold text-foreground\">\n {t(\"dispatch.pages.communityApps\")}\n </h2>\n {catalogQuery.isError ? (\n <ActionQueryError\n error={catalogQuery.error}\n onRetry={() => void catalogQuery.refetch()}\n />\n ) : catalogQuery.isLoading ? (\n <AppList className=\"divide-y rounded-xl border\">\n <div className=\"flex items-center gap-3 px-4 py-3.5\">\n <Skeleton className=\"size-8 rounded-lg\" />\n <Skeleton className=\"h-4 w-40\" />\n </div>\n </AppList>\n ) : catalogQuery.data?.length ? (\n <AppList className=\"divide-y rounded-xl border\">\n {catalogQuery.data.map((source) => (\n <AppListRow key={source.id} className=\"border-b-0\">\n <AppIcon id={source.id} name={source.name} size=\"sm\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2\">\n <h3 className=\"truncate text-sm font-semibold text-foreground\">\n {source.name}\n </h3>\n {source.installed ? (\n <Badge variant=\"secondary\" className=\"gap-1\">\n <IconCircleCheck size={13} />\n {t(\"dispatch.pages.communityAppsInstalled\")}\n </Badge>\n ) : source.pending ? (\n <Badge variant=\"secondary\">\n {t(\"dispatch.pages.communityAppsPending\")}\n </Badge>\n ) : null}\n </div>\n {source.description ? (\n <p className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {source.description}\n </p>\n ) : null}\n <div className=\"mt-1 flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground\">\n <span>\n {t(\"dispatch.pages.communityAppsLicense\")}: {source.license}\n </span>\n <a\n href={pinnedSourceUrl(source)}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 underline-offset-4 hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {t(\"dispatch.pages.communityAppsTemplateSource\")}\n <IconArrowUpRight size={12} aria-hidden=\"true\" />\n </a>\n </div>\n </div>\n {source.installable ? (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={install.isPending}\n onClick={() => {\n setInstallingId(source.id);\n install.mutate({ sourceId: source.id });\n }}\n >\n {install.isPending && installingId === source.id ? (\n <Spinner className=\"mr-1.5\" />\n ) : (\n <IconPlus size={14} className=\"mr-1.5\" />\n )}\n {install.isPending && installingId === source.id\n ? t(\"dispatch.pages.communityAppsInstalling\")\n : t(\"dispatch.pages.communityAppsInstall\")}\n </Button>\n ) : !source.installed &&\n !source.pending &&\n source.installUnavailableReason === \"workspace-required\" ? (\n <span className=\"max-w-48 text-right text-xs text-muted-foreground\">\n {t(\"dispatch.pages.communityAppsWorkspaceRequired\")}\n </span>\n ) : !source.installed &&\n !source.pending &&\n source.installUnavailableReason === \"app-id-conflict\" ? (\n <span className=\"max-w-48 text-right text-xs text-muted-foreground\">\n {t(\"dispatch.pages.communityAppsIdConflict\")}\n </span>\n ) : !source.installed &&\n !source.pending &&\n source.installUnavailableReason ===\n \"builder-install-unverified\" ? (\n <span className=\"max-w-48 text-right text-xs text-muted-foreground\">\n {t(\"dispatch.pages.communityAppsBuilderInstallUnavailable\")}\n </span>\n ) : null}\n </AppListRow>\n ))}\n </AppList>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t(\"dispatch.pages.communityAppsEmpty\")}\n </p>\n )}\n </section>\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-app-card.d.ts","sourceRoot":"","sources":["../../src/components/workspace-app-card.tsx"],"names":[],"mappings":"AA6BA,OAAO,EASL,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AA2D/B,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,SAAS,EACT,QAAgB,EAChB,cAAc,GACf,EAAE;IACD,GAAG,EAAE,mBAAmB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,mDA6NA"}
1
+ {"version":3,"file":"workspace-app-card.d.ts","sourceRoot":"","sources":["../../src/components/workspace-app-card.tsx"],"names":[],"mappings":"AA+BA,OAAO,EASL,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AA4E/B,wBAAgB,gBAAgB,CAAC,EAC/B,GAAG,EACH,SAAS,EACT,QAAgB,EAChB,cAAc,GACf,EAAE;IACD,GAAG,EAAE,mBAAmB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B,mDA6SA"}
@@ -1,6 +1,8 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks";
3
3
  import { useT } from "@agent-native/core/client/i18n";
4
+ import { useOrgRole } from "@agent-native/core/client/org";
5
+ import { parseAgentProfileMetadata } from "@agent-native/core/shared";
4
6
  import { APP_ACTION_MENU_CONTENT_CLASS } from "@agent-native/toolkit/app/chat/chat-first/app-open-actions";
5
7
  import { ShareButton } from "@agent-native/toolkit/app/sharing";
6
8
  import { IconChevronDown, IconChevronRight, IconClockHour4, IconEdit, IconEye, IconEyeOff, IconFileText, IconKey, IconPin, IconShare3, IconSettings, IconTrash, IconUser, IconUsersGroup, IconWorld, } from "@tabler/icons-react";
@@ -24,6 +26,20 @@ import { Textarea } from "./ui/textarea.js";
24
26
  import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip.js";
25
27
  import { AppResourceEffectiveStack } from "./workspace-resource-effective-stack.js";
26
28
  const APP_CARD_ACTION_CLASS = "size-7 rounded-md p-0 text-muted-foreground transition-[background-color,color] hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:bg-accent data-[state=open]:text-foreground";
29
+ function normalizeProfileDescription(value) {
30
+ return value.replace(/[\r\n]+/g, " ").replace(/[\u0000-\u001f\u007f]/g, "");
31
+ }
32
+ function normalizeWhenToUseText(value) {
33
+ return value
34
+ .replace(/\r\n?/g, "\n")
35
+ .replace(/[\u0000-\u0009\u000b-\u001f\u007f]/g, "");
36
+ }
37
+ function parseWhenToUseText(value) {
38
+ return value
39
+ .split("\n")
40
+ .map((item) => item.trim())
41
+ .filter(Boolean);
42
+ }
27
43
  function deferWorkspaceAppOverlayOpen(event, closeMenu, openOverlay) {
28
44
  event.preventDefault();
29
45
  closeMenu();
@@ -43,6 +59,11 @@ function consumeWorkspaceAppOverlayFocusRestore(pendingOverlayRef, event) {
43
59
  }
44
60
  export function WorkspaceAppCard({ app, className, isPinned = false, onTogglePinned, }) {
45
61
  const t = useT();
62
+ const { org, role, isLoading: orgLoading, error: orgError } = useOrgRole();
63
+ const canEditMetadata = !orgLoading &&
64
+ !orgError &&
65
+ !!org?.orgId &&
66
+ (role === "owner" || role === "admin");
46
67
  const href = workspaceAppHref(app);
47
68
  const directHref = app.status !== "pending" &&
48
69
  !isWorkspaceSsoApp(app) &&
@@ -60,13 +81,22 @@ export function WorkspaceAppCard({ app, className, isPinned = false, onTogglePin
60
81
  const [keysOpen, setKeysOpen] = useState(false);
61
82
  const [resourcesOpen, setResourcesOpen] = useState(false);
62
83
  const [draftName, setDraftName] = useState(app.name);
63
- const [draftDescription, setDraftDescription] = useState(app.description || "");
84
+ const [draftDescription, setDraftDescription] = useState(normalizeProfileDescription(app.description || ""));
85
+ const [draftWhenToUse, setDraftWhenToUse] = useState(app.whenToUse?.join("\n") ?? "");
86
+ const draftWhenToUseValues = parseWhenToUseText(draftWhenToUse);
87
+ const validProfile = Boolean(parseAgentProfileMetadata({
88
+ ...(draftDescription.trim()
89
+ ? { description: draftDescription.trim() }
90
+ : {}),
91
+ whenToUse: draftWhenToUseValues,
92
+ }));
64
93
  useEffect(() => {
65
94
  if (editOpen)
66
95
  return;
67
96
  setDraftName(app.name);
68
- setDraftDescription(app.description || "");
69
- }, [app.description, app.name, editOpen]);
97
+ setDraftDescription(normalizeProfileDescription(app.description || ""));
98
+ setDraftWhenToUse(app.whenToUse?.join("\n") ?? "");
99
+ }, [app.description, app.name, app.whenToUse, editOpen]);
70
100
  const archive = useActionMutation("archive-workspace-app", {
71
101
  onError: (err) => toast.error(`Could not hide ${app.name}: ${stringifyError(err)}`),
72
102
  });
@@ -102,22 +132,46 @@ export function WorkspaceAppCard({ app, className, isPinned = false, onTogglePin
102
132
  toast.error("App name is required.");
103
133
  return;
104
134
  }
135
+ const description = draftDescription.trim();
136
+ const currentDescription = normalizeProfileDescription(app.description || "").trim();
137
+ const currentWhenToUse = app.whenToUse ?? [];
138
+ const nameChanged = name !== app.name.trim();
139
+ const descriptionChanged = description !== currentDescription;
140
+ const whenToUseChanged = draftWhenToUseValues.length !== currentWhenToUse.length ||
141
+ draftWhenToUseValues.some((example, index) => example !== currentWhenToUse[index]);
142
+ if (!parseAgentProfileMetadata({
143
+ ...(description ? { description } : {}),
144
+ whenToUse: draftWhenToUseValues,
145
+ })) {
146
+ return;
147
+ }
148
+ if (!nameChanged && !descriptionChanged && !whenToUseChanged) {
149
+ setEditOpen(false);
150
+ return;
151
+ }
105
152
  updateMetadata.mutate({
106
153
  appId: app.id,
107
- name,
108
- description: draftDescription.trim(),
154
+ ...(nameChanged ? { name } : {}),
155
+ ...(descriptionChanged ? { description } : {}),
156
+ ...(whenToUseChanged ? { whenToUse: draftWhenToUseValues } : {}),
109
157
  });
110
158
  };
111
159
  const pinLabel = t(isPinned ? "dispatch.pages.unpinApp" : "dispatch.pages.pinApp", {
112
160
  name: app.name,
113
161
  defaultValue: isPinned ? "Unpin this app" : "Pin this app",
114
162
  });
115
- return (_jsxs(_Fragment, { children: [_jsxs(AppListRow, { className: cn(!href && "opacity-60", isArchived && "opacity-70", className), children: [_jsx(AppIcon, { id: app.id, name: app.name, size: "sm" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), app.description || isPending ? (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: app.description || pendingLabel })) : null, _jsxs("div", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-2 text-[11px] text-muted-foreground", children: [isPending ? (_jsxs("span", { className: "inline-flex min-w-0 items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconClockHour4, { size: 12 }), _jsx("span", { className: "truncate", children: pendingLabel })] })) : null, isArchived ? (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconEyeOff, { size: 12 }), "Hidden"] })) : null, audience === "public" ? (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconWorld, { size: 12 }), "Public"] })) : null] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(WorkspaceAppOpenActions, { app: app, href: directHref ?? href, openDirectly: Boolean(directHref && shouldOpenWorkspaceAppInTopWindow()), isPinned: isPinned, pinLabel: pinLabel, pendingOpenLabel: pendingOpenLabel, onTogglePinned: onTogglePinned }), _jsx(WorkspaceAppSettings, { app: app, isArchived: isArchived, isPending: isPending, onEdit: () => setEditOpen(true), onKeys: () => setKeysOpen(true), onResources: () => setResourcesOpen(true), onArchive: handleArchive, onUnarchive: handleUnarchive, onRemovePending: handleRemovePending, labels: {
163
+ return (_jsxs(_Fragment, { children: [_jsxs(AppListRow, { className: cn(!href && "opacity-60", isArchived && "opacity-70", className), children: [_jsx(AppIcon, { id: app.id, name: app.name, size: "sm" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h3", { className: "truncate text-sm font-semibold text-foreground", children: app.name }), app.description || isPending ? (_jsx("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: app.description || pendingLabel })) : null, _jsxs("div", { className: "mt-1.5 flex min-w-0 flex-wrap items-center gap-2 text-[11px] text-muted-foreground", children: [isPending ? (_jsxs("span", { className: "inline-flex min-w-0 items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconClockHour4, { size: 12 }), _jsx("span", { className: "truncate", children: pendingLabel })] })) : null, isArchived ? (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconEyeOff, { size: 12 }), "Hidden"] })) : null, audience === "public" ? (_jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5", children: [_jsx(IconWorld, { size: 12 }), "Public"] })) : null] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(WorkspaceAppOpenActions, { app: app, href: directHref ?? href, openDirectly: Boolean(directHref && shouldOpenWorkspaceAppInTopWindow()), isPinned: isPinned, pinLabel: pinLabel, pendingOpenLabel: pendingOpenLabel, onTogglePinned: onTogglePinned }), _jsx(WorkspaceAppSettings, { app: app, canEditMetadata: canEditMetadata, isArchived: isArchived, isPending: isPending, onEdit: () => setEditOpen(true), onKeys: () => setKeysOpen(true), onResources: () => setResourcesOpen(true), onArchive: handleArchive, onUnarchive: handleUnarchive, onRemovePending: handleRemovePending, labels: {
116
164
  createdBy: t("agents.dashboardMetadataCreatedBy"),
117
165
  owner: t("dispatch.pages.appMetadataOwner"),
118
166
  teams: t("dispatch.pages.appMetadataTeams"),
119
167
  share: t("share.share", { defaultValue: "Share" }),
120
- } })] })] }), _jsx(Dialog, { open: editOpen, onOpenChange: setEditOpen, children: _jsxs(DialogContent, { children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Edit app details" }) }), _jsxs("form", { className: "space-y-4", onSubmit: handleMetadataSubmit, children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `app-name-${app.id}`, children: "Name" }), _jsx(Input, { id: `app-name-${app.id}`, value: draftName, maxLength: 120, onChange: (event) => setDraftName(event.target.value) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `app-description-${app.id}`, children: "Description" }), _jsx(Textarea, { id: `app-description-${app.id}`, value: draftDescription, maxLength: 500, rows: 4, onChange: (event) => setDraftDescription(event.target.value) })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setEditOpen(false), children: "Cancel" }), _jsx(Button, { type: "submit", disabled: updateMetadata.isPending, children: updateMetadata.isPending ? "Saving..." : "Save" })] })] })] }) }), _jsx(Dialog, { open: keysOpen, onOpenChange: setKeysOpen, children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Manage keys for ", app.name] }), _jsx(DialogDescription, { children: "Choose which workspace credentials this app can use." })] }), _jsx(AppKeysPanel, { appId: app.id, appName: app.name }), _jsx(DialogFooter, { children: _jsx(Button, { type: "button", onClick: () => setKeysOpen(false), children: "Done" }) })] }) }), _jsx(AppResourcesDialog, { app: app, open: resourcesOpen, onOpenChange: setResourcesOpen })] }));
168
+ } })] })] }), _jsx(Dialog, { open: editOpen, onOpenChange: setEditOpen, children: _jsxs(DialogContent, { children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Edit app details" }) }), _jsxs("form", { className: "space-y-4", onSubmit: handleMetadataSubmit, children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `app-name-${app.id}`, children: "Name" }), _jsx(Input, { id: `app-name-${app.id}`, value: draftName, maxLength: 120, onChange: (event) => setDraftName(event.target.value) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `app-description-${app.id}`, children: "Description" }), _jsx(Textarea, { id: `app-description-${app.id}`, value: draftDescription, maxLength: 1000, rows: 4, onChange: (event) => setDraftDescription(normalizeProfileDescription(event.target.value)) })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: `app-when-to-use-${app.id}`, children: t("dispatch.pages.appProfileWhenToUse", {
169
+ defaultValue: "When to use",
170
+ }) }), _jsx(Textarea, { id: `app-when-to-use-${app.id}`, value: draftWhenToUse, "aria-invalid": !validProfile, rows: 3, placeholder: t("dispatch.pages.appProfileWhenToUsePlaceholder", {
171
+ defaultValue: "One example request per line",
172
+ }), onChange: (event) => setDraftWhenToUse(normalizeWhenToUseText(event.target.value)) }), _jsx("p", { className: "text-xs text-muted-foreground", children: t("dispatch.pages.appProfileWhenToUseHint", {
173
+ defaultValue: "Add up to 6 examples, with no more than 140 characters each.",
174
+ }) })] }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: () => setEditOpen(false), children: "Cancel" }), _jsx(Button, { type: "submit", disabled: updateMetadata.isPending || !validProfile, children: updateMetadata.isPending ? "Saving..." : "Save" })] })] })] }) }), _jsx(Dialog, { open: keysOpen, onOpenChange: setKeysOpen, children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsxs(DialogTitle, { children: ["Manage keys for ", app.name] }), _jsx(DialogDescription, { children: "Choose which workspace credentials this app can use." })] }), _jsx(AppKeysPanel, { appId: app.id, appName: app.name }), _jsx(DialogFooter, { children: _jsx(Button, { type: "button", onClick: () => setKeysOpen(false), children: "Done" }) })] }) }), _jsx(AppResourcesDialog, { app: app, open: resourcesOpen, onOpenChange: setResourcesOpen })] }));
121
175
  }
122
176
  function WorkspaceAppOpenActions({ app, href, openDirectly, isPinned, pinLabel, pendingOpenLabel, onTogglePinned, }) {
123
177
  const navigate = useNavigate();
@@ -144,7 +198,7 @@ function WorkspaceAppOpenActions({ app, href, openDirectly, isPinned, pinLabel,
144
198
  ]
145
199
  : undefined }));
146
200
  }
147
- function WorkspaceAppSettings({ app, isArchived, isPending, onEdit, onKeys, onResources, onArchive, onUnarchive, onRemovePending, labels, }) {
201
+ function WorkspaceAppSettings({ app, canEditMetadata, isArchived, isPending, onEdit, onKeys, onResources, onArchive, onUnarchive, onRemovePending, labels, }) {
148
202
  const [shareOpen, setShareOpen] = useState(false);
149
203
  const [settingsOpen, setSettingsOpen] = useState(false);
150
204
  const settingsTriggerRef = useRef(null);
@@ -162,7 +216,7 @@ function WorkspaceAppSettings({ app, isArchived, isPending, onEdit, onKeys, onRe
162
216
  setTimeout(restoreSettingsFocus, 0);
163
217
  }
164
218
  };
165
- return (_jsxs(_Fragment, { children: [_jsxs(DropdownMenu, { open: settingsOpen, onOpenChange: setSettingsOpen, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", ref: settingsTriggerRef, "aria-label": `Settings for ${app.name}`, className: APP_CARD_ACTION_CLASS, children: _jsx(IconSettings, { size: 15 }) }) }) }), _jsx(TooltipContent, { children: "App settings" })] }), _jsxs(DropdownMenuContent, { align: "end", className: cn(APP_ACTION_MENU_CONTENT_CLASS, "min-w-max"), onCloseAutoFocus: (event) => consumeWorkspaceAppOverlayFocusRestore(pendingShareOverlayRef, event), children: [_jsxs(DropdownMenuItem, { onSelect: onEdit, children: [_jsx(IconEdit, { size: 14, "aria-hidden": "true" }), "Edit details"] }), !isPending ? (_jsxs(DropdownMenuItem, { onSelect: (event) => deferWorkspaceAppOverlayOpen(event, () => {
219
+ return (_jsxs(_Fragment, { children: [_jsxs(DropdownMenu, { open: settingsOpen, onOpenChange: setSettingsOpen, children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "sm", ref: settingsTriggerRef, "aria-label": `Settings for ${app.name}`, className: APP_CARD_ACTION_CLASS, children: _jsx(IconSettings, { size: 15 }) }) }) }), _jsx(TooltipContent, { children: "App settings" })] }), _jsxs(DropdownMenuContent, { align: "end", className: cn(APP_ACTION_MENU_CONTENT_CLASS, "min-w-max"), onCloseAutoFocus: (event) => consumeWorkspaceAppOverlayFocusRestore(pendingShareOverlayRef, event), children: [canEditMetadata ? (_jsxs(DropdownMenuItem, { onSelect: onEdit, children: [_jsx(IconEdit, { size: 14, "aria-hidden": "true" }), "Edit details"] })) : null, !isPending ? (_jsxs(DropdownMenuItem, { onSelect: (event) => deferWorkspaceAppOverlayOpen(event, () => {
166
220
  pendingShareOverlayRef.current = true;
167
221
  setSettingsOpen(false);
168
222
  }, () => setShareOpen(true)), children: [_jsx(IconShare3, { size: 14, "aria-hidden": "true" }), labels.share] })) : null, !isPending && !isArchived ? (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: onKeys, children: [_jsx(IconKey, { size: 14, "aria-hidden": "true" }), "Manage keys"] }), _jsxs(DropdownMenuItem, { onSelect: onResources, children: [_jsx(IconFileText, { size: 14, "aria-hidden": "true" }), "Agent resources"] })] })) : null, isPending ? (_jsxs(DropdownMenuItem, { onSelect: onRemovePending, className: "text-destructive focus:text-destructive", children: [_jsx(IconTrash, { size: 14, "aria-hidden": "true" }), "Remove from list"] })) : isArchived ? (_jsxs(DropdownMenuItem, { onSelect: onUnarchive, children: [_jsx(IconEye, { size: 14, "aria-hidden": "true" }), "Restore to list"] })) : (_jsxs(DropdownMenuItem, { onSelect: onArchive, children: [_jsx(IconEyeOff, { size: 14, "aria-hidden": "true" }), "Hide from list"] })), _jsx(WorkspaceAppMetadata, { app: app, labels: labels })] })] }), !isPending && shareOpen ? (_jsx(ShareButton, { resourceType: "workspace-app", resourceId: app.id, resourceTitle: app.name, defaultOpen: true, onOpenChange: handleShareOpenChange, triggerClassName: "sr-only" })) : null] }));