@agent-native/core 0.7.23 → 0.7.24

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 (137) hide show
  1. package/README.md +2 -2
  2. package/dist/a2a/client.d.ts +10 -4
  3. package/dist/a2a/client.d.ts.map +1 -1
  4. package/dist/a2a/client.js +16 -1
  5. package/dist/a2a/client.js.map +1 -1
  6. package/dist/a2a/handlers.d.ts.map +1 -1
  7. package/dist/a2a/handlers.js +20 -17
  8. package/dist/a2a/handlers.js.map +1 -1
  9. package/dist/cli/create.d.ts +2 -1
  10. package/dist/cli/create.d.ts.map +1 -1
  11. package/dist/cli/create.js +13 -19
  12. package/dist/cli/create.js.map +1 -1
  13. package/dist/cli/index.js +23 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/workspace-dev.d.ts +3 -0
  16. package/dist/cli/workspace-dev.d.ts.map +1 -0
  17. package/dist/cli/workspace-dev.js +323 -0
  18. package/dist/cli/workspace-dev.js.map +1 -0
  19. package/dist/cli/workspacify.d.ts +3 -3
  20. package/dist/cli/workspacify.js +4 -4
  21. package/dist/cli/workspacify.js.map +1 -1
  22. package/dist/client/AgentPanel.d.ts.map +1 -1
  23. package/dist/client/AgentPanel.js +10 -9
  24. package/dist/client/AgentPanel.js.map +1 -1
  25. package/dist/client/AssistantChat.d.ts.map +1 -1
  26. package/dist/client/AssistantChat.js +2 -1
  27. package/dist/client/AssistantChat.js.map +1 -1
  28. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  29. package/dist/client/MultiTabAssistantChat.js +2 -1
  30. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  31. package/dist/client/components/ui/tooltip.d.ts +8 -0
  32. package/dist/client/components/ui/tooltip.d.ts.map +1 -0
  33. package/dist/client/components/ui/tooltip.js +11 -0
  34. package/dist/client/components/ui/tooltip.js.map +1 -0
  35. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  36. package/dist/client/resources/ResourceTree.js +21 -17
  37. package/dist/client/resources/ResourceTree.js.map +1 -1
  38. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  39. package/dist/client/resources/ResourcesPanel.js +13 -11
  40. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  41. package/dist/deploy/workspace-core.d.ts +1 -1
  42. package/dist/deploy/workspace-core.d.ts.map +1 -1
  43. package/dist/deploy/workspace-core.js +14 -11
  44. package/dist/deploy/workspace-core.js.map +1 -1
  45. package/dist/integrations/a2a-continuation-processor.d.ts +10 -0
  46. package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -0
  47. package/dist/integrations/a2a-continuation-processor.js +150 -0
  48. package/dist/integrations/a2a-continuation-processor.js.map +1 -0
  49. package/dist/integrations/a2a-continuations-store.d.ts +41 -0
  50. package/dist/integrations/a2a-continuations-store.d.ts.map +1 -0
  51. package/dist/integrations/a2a-continuations-store.js +214 -0
  52. package/dist/integrations/a2a-continuations-store.js.map +1 -0
  53. package/dist/integrations/plugin.d.ts.map +1 -1
  54. package/dist/integrations/plugin.js +52 -0
  55. package/dist/integrations/plugin.js.map +1 -1
  56. package/dist/integrations/types.d.ts +5 -0
  57. package/dist/integrations/types.d.ts.map +1 -1
  58. package/dist/integrations/types.js.map +1 -1
  59. package/dist/integrations/webhook-handler.d.ts +6 -0
  60. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  61. package/dist/integrations/webhook-handler.js +69 -15
  62. package/dist/integrations/webhook-handler.js.map +1 -1
  63. package/dist/org/handlers.d.ts.map +1 -1
  64. package/dist/org/handlers.js +22 -16
  65. package/dist/org/handlers.js.map +1 -1
  66. package/dist/scripts/call-agent.d.ts.map +1 -1
  67. package/dist/scripts/call-agent.js +91 -30
  68. package/dist/scripts/call-agent.js.map +1 -1
  69. package/dist/server/agent-discovery.d.ts.map +1 -1
  70. package/dist/server/agent-discovery.js +17 -105
  71. package/dist/server/agent-discovery.js.map +1 -1
  72. package/dist/server/agents-bundle.js +1 -1
  73. package/dist/server/agents-bundle.js.map +1 -1
  74. package/dist/server/auth.d.ts.map +1 -1
  75. package/dist/server/auth.js +29 -120
  76. package/dist/server/auth.js.map +1 -1
  77. package/dist/server/better-auth-instance.d.ts +1 -0
  78. package/dist/server/better-auth-instance.d.ts.map +1 -1
  79. package/dist/server/better-auth-instance.js.map +1 -1
  80. package/dist/server/builder-browser.d.ts.map +1 -1
  81. package/dist/server/builder-browser.js +7 -5
  82. package/dist/server/builder-browser.js.map +1 -1
  83. package/dist/server/framework-request-handler.js +1 -1
  84. package/dist/server/framework-request-handler.js.map +1 -1
  85. package/dist/server/onboarding-html.d.ts +1 -8
  86. package/dist/server/onboarding-html.d.ts.map +1 -1
  87. package/dist/server/onboarding-html.js +321 -152
  88. package/dist/server/onboarding-html.js.map +1 -1
  89. package/dist/server/request-context.d.ts +14 -3
  90. package/dist/server/request-context.d.ts.map +1 -1
  91. package/dist/server/request-context.js +3 -0
  92. package/dist/server/request-context.js.map +1 -1
  93. package/dist/templates/default/_gitignore +2 -0
  94. package/dist/templates/workspace-core/AGENTS.md +18 -71
  95. package/dist/templates/workspace-core/package.json +2 -20
  96. package/dist/templates/workspace-core/src/client/index.ts +2 -26
  97. package/dist/templates/workspace-core/src/index.ts +1 -21
  98. package/dist/templates/workspace-core/src/server/index.ts +3 -22
  99. package/dist/templates/workspace-root/README.md +17 -20
  100. package/dist/templates/workspace-root/_gitignore +3 -0
  101. package/dist/templates/workspace-root/package.json +6 -13
  102. package/dist/templates/workspace-root/pnpm-workspace.yaml +4 -2
  103. package/dist/vite/agents-bundle-plugin.js +2 -2
  104. package/dist/vite/agents-bundle-plugin.js.map +1 -1
  105. package/docs/content/authentication.md +3 -5
  106. package/docs/content/multi-app-workspace.md +38 -50
  107. package/package.json +1 -1
  108. package/src/templates/default/_gitignore +2 -0
  109. package/src/templates/workspace-core/AGENTS.md +18 -71
  110. package/src/templates/workspace-core/package.json +2 -20
  111. package/src/templates/workspace-core/src/client/index.ts +2 -26
  112. package/src/templates/workspace-core/src/index.ts +1 -21
  113. package/src/templates/workspace-core/src/server/index.ts +3 -22
  114. package/src/templates/workspace-root/README.md +17 -20
  115. package/src/templates/workspace-root/_gitignore +3 -0
  116. package/src/templates/workspace-root/package.json +6 -13
  117. package/src/templates/workspace-root/pnpm-workspace.yaml +4 -2
  118. package/dist/templates/default/.claude/settings.json +0 -100
  119. package/dist/templates/workspace-core/.agents/skills/company-policies/SKILL.md +0 -42
  120. package/dist/templates/workspace-core/actions/company-directory.ts +0 -38
  121. package/dist/templates/workspace-core/src/client/AuthenticatedLayout.tsx +0 -37
  122. package/dist/templates/workspace-core/src/credentials.ts +0 -67
  123. package/dist/templates/workspace-core/src/server/agent-chat-plugin.ts +0 -30
  124. package/dist/templates/workspace-core/src/server/auth-plugin.ts +0 -35
  125. package/dist/templates/workspace-core/styles/tokens.css +0 -22
  126. package/dist/templates/workspace-root/.github/workflows/ci.yml +0 -32
  127. package/dist/templates/workspace-root/scripts/workspace-dev.ts +0 -377
  128. package/src/templates/default/.claude/settings.json +0 -100
  129. package/src/templates/workspace-core/.agents/skills/company-policies/SKILL.md +0 -42
  130. package/src/templates/workspace-core/actions/company-directory.ts +0 -38
  131. package/src/templates/workspace-core/src/client/AuthenticatedLayout.tsx +0 -37
  132. package/src/templates/workspace-core/src/credentials.ts +0 -67
  133. package/src/templates/workspace-core/src/server/agent-chat-plugin.ts +0 -30
  134. package/src/templates/workspace-core/src/server/auth-plugin.ts +0 -35
  135. package/src/templates/workspace-core/styles/tokens.css +0 -22
  136. package/src/templates/workspace-root/.github/workflows/ci.yml +0 -32
  137. package/src/templates/workspace-root/scripts/workspace-dev.ts +0 -377
@@ -1,377 +0,0 @@
1
- #!/usr/bin/env tsx
2
- import { spawn, type ChildProcess } from "node:child_process";
3
- import fs from "node:fs";
4
- import http from "node:http";
5
- import net from "node:net";
6
- import path from "node:path";
7
-
8
- interface WorkspaceApp {
9
- id: string;
10
- name: string;
11
- dir: string;
12
- port: number;
13
- process?: ChildProcess;
14
- }
15
-
16
- const root = process.cwd();
17
- const appsDir = path.join(root, "apps");
18
- fs.mkdirSync(path.join(root, "data"), { recursive: true });
19
- const gatewayHost = process.env.WORKSPACE_HOST || "127.0.0.1";
20
- const requestedPort = Number(
21
- process.env.WORKSPACE_PORT || process.env.PORT || 8080,
22
- );
23
- const appPortStart = Number(process.env.WORKSPACE_APP_PORT_START || 8100);
24
- const forceVite = process.env.WORKSPACE_VITE_FORCE === "1";
25
- let gatewayUrl = `http://${gatewayHost}:${requestedPort}`;
26
-
27
- function readJson(file: string): any {
28
- try {
29
- return JSON.parse(fs.readFileSync(file, "utf8"));
30
- } catch {
31
- return null;
32
- }
33
- }
34
-
35
- function discoverApps(): WorkspaceApp[] {
36
- if (!fs.existsSync(appsDir)) return [];
37
- return fs
38
- .readdirSync(appsDir, { withFileTypes: true })
39
- .filter((entry) => entry.isDirectory())
40
- .map((entry) => {
41
- const dir = path.join(appsDir, entry.name);
42
- const pkg = readJson(path.join(dir, "package.json"));
43
- if (!pkg) return null;
44
- return {
45
- id: entry.name,
46
- name: pkg.displayName || pkg.name || entry.name,
47
- dir,
48
- port: appPortStart,
49
- } satisfies WorkspaceApp;
50
- })
51
- .filter((app): app is WorkspaceApp => !!app)
52
- .sort((a, b) => {
53
- if (a.id === "dispatch") return -1;
54
- if (b.id === "dispatch") return 1;
55
- return a.id.localeCompare(b.id);
56
- })
57
- .map((app, index) => ({ ...app, port: appPortStart + index }));
58
- }
59
-
60
- const apps = discoverApps();
61
- if (apps.length === 0) {
62
- console.error("[workspace] No apps found under ./apps");
63
- process.exit(1);
64
- }
65
-
66
- const appById = new Map(apps.map((app) => [app.id, app]));
67
- const defaultApp =
68
- process.env.WORKSPACE_DEFAULT_APP &&
69
- appById.has(process.env.WORKSPACE_DEFAULT_APP)
70
- ? process.env.WORKSPACE_DEFAULT_APP
71
- : appById.has("dispatch")
72
- ? "dispatch"
73
- : apps[0].id;
74
-
75
- function syncApps(): void {
76
- const discovered = discoverApps();
77
- for (const app of discovered) {
78
- if (appById.has(app.id)) continue;
79
- const usedPorts = new Set(apps.map((existing) => existing.port));
80
- let port = appPortStart;
81
- while (usedPorts.has(port)) port++;
82
- const next = { ...app, port };
83
- apps.push(next);
84
- apps.sort((a, b) => {
85
- if (a.id === "dispatch") return -1;
86
- if (b.id === "dispatch") return 1;
87
- return a.id.localeCompare(b.id);
88
- });
89
- appById.set(next.id, next);
90
- console.log(`[workspace] Detected new app: /${next.id}`);
91
- startApp(next);
92
- }
93
- }
94
-
95
- let syncTimer: NodeJS.Timeout | undefined;
96
- function scheduleSync(): void {
97
- if (syncTimer) clearTimeout(syncTimer);
98
- syncTimer = setTimeout(syncApps, 400);
99
- }
100
-
101
- function firstPathSegment(url: string | undefined): string | null {
102
- if (!url) return null;
103
- try {
104
- const parsed = new URL(url, "http://workspace.local");
105
- const [segment] = parsed.pathname.split("/").filter(Boolean);
106
- return segment || null;
107
- } catch {
108
- return null;
109
- }
110
- }
111
-
112
- function appForRequest(req: http.IncomingMessage): WorkspaceApp | null {
113
- const direct = firstPathSegment(req.url);
114
- if (direct && appById.has(direct)) return appById.get(direct) ?? null;
115
- const referer = req.headers.referer;
116
- const fromReferer =
117
- typeof referer === "string" ? firstPathSegment(referer) : null;
118
- return fromReferer && appById.has(fromReferer)
119
- ? (appById.get(fromReferer) ?? null)
120
- : null;
121
- }
122
-
123
- function startApp(app: WorkspaceApp): void {
124
- const basePath = `/${app.id}`;
125
- const child = spawn(
126
- "pnpm",
127
- [
128
- "--dir",
129
- app.dir,
130
- "exec",
131
- "vite",
132
- "--host",
133
- "127.0.0.1",
134
- "--port",
135
- String(app.port),
136
- "--strictPort",
137
- ...(forceVite ? ["--force"] : []),
138
- ],
139
- {
140
- cwd: root,
141
- stdio: ["ignore", "pipe", "pipe"],
142
- env: {
143
- ...process.env,
144
- APP_NAME: app.id,
145
- APP_BASE_PATH: basePath,
146
- VITE_APP_BASE_PATH: basePath,
147
- PORT: String(app.port),
148
- WORKSPACE_GATEWAY_URL: gatewayUrl,
149
- },
150
- },
151
- );
152
- app.process = child;
153
-
154
- const prefix = `[${app.id}]`;
155
- child.stdout?.on("data", (chunk) => {
156
- process.stdout.write(
157
- String(chunk)
158
- .split(/\r?\n/)
159
- .filter(Boolean)
160
- .map((line) => `${prefix} ${line}`)
161
- .join("\n") + "\n",
162
- );
163
- });
164
- child.stderr?.on("data", (chunk) => {
165
- process.stderr.write(
166
- String(chunk)
167
- .split(/\r?\n/)
168
- .filter(Boolean)
169
- .map((line) => `${prefix} ${line}`)
170
- .join("\n") + "\n",
171
- );
172
- });
173
- child.on("exit", (code) => {
174
- if (code === 0 || shuttingDown) return;
175
- console.error(`${prefix} exited with code ${code}`);
176
- });
177
- }
178
-
179
- function renderIndex(): string {
180
- return `<!doctype html>
181
- <html>
182
- <head>
183
- <meta charset="utf-8" />
184
- <meta name="viewport" content="width=device-width, initial-scale=1" />
185
- <title>Agent-Native Workspace</title>
186
- <style>
187
- body { font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; margin: 0; padding: 32px; background: #fafafa; color: #171717; }
188
- main { max-width: 760px; margin: 0 auto; }
189
- a { color: inherit; text-decoration: none; }
190
- .grid { display: grid; gap: 12px; margin-top: 20px; }
191
- .card { display: flex; justify-content: space-between; border: 1px solid #d4d4d4; border-radius: 8px; padding: 14px 16px; background: white; }
192
- .muted { color: #737373; }
193
- </style>
194
- </head>
195
- <body>
196
- <main>
197
- <h1>Agent-Native Workspace</h1>
198
- <p class="muted">Open an app below. Dispatch is the workspace control plane.</p>
199
- <div class="grid">
200
- ${apps
201
- .map(
202
- (app) =>
203
- `<a class="card" href="/${app.id}"><strong>${app.name}</strong><span class="muted">/${app.id}</span></a>`,
204
- )
205
- .join("")}
206
- </div>
207
- </main>
208
- </body>
209
- </html>`;
210
- }
211
-
212
- function proxyHttp(
213
- app: WorkspaceApp,
214
- req: http.IncomingMessage,
215
- res: http.ServerResponse,
216
- ): void {
217
- const headers = { ...req.headers, host: `127.0.0.1:${app.port}` };
218
- const proxyReq = http.request(
219
- {
220
- hostname: "127.0.0.1",
221
- port: app.port,
222
- method: req.method,
223
- path: req.url,
224
- headers,
225
- },
226
- (proxyRes) => {
227
- res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
228
- proxyRes.pipe(res);
229
- },
230
- );
231
-
232
- proxyReq.on("error", (err) => {
233
- res.writeHead(502, { "content-type": "text/plain" });
234
- res.end(`App "${app.id}" is not ready yet: ${err.message}`);
235
- });
236
-
237
- req.pipe(proxyReq);
238
- }
239
-
240
- function proxyUpgrade(
241
- app: WorkspaceApp,
242
- req: http.IncomingMessage,
243
- socket: net.Socket,
244
- head: Buffer,
245
- ): void {
246
- const target = net.connect(app.port, "127.0.0.1", () => {
247
- const headers = Object.entries({
248
- ...req.headers,
249
- host: `127.0.0.1:${app.port}`,
250
- })
251
- .flatMap(([key, value]) =>
252
- Array.isArray(value)
253
- ? value.map((item) => `${key}: ${item}`)
254
- : [`${key}: ${value ?? ""}`],
255
- )
256
- .join("\r\n");
257
- target.write(
258
- `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n${headers}\r\n\r\n`,
259
- );
260
- if (head.length) target.write(head);
261
- socket.pipe(target).pipe(socket);
262
- });
263
-
264
- target.on("error", () => socket.destroy());
265
- }
266
-
267
- let shuttingDown = false;
268
- let workspaceStarted = false;
269
-
270
- function startWorkspaceProcesses(): void {
271
- if (workspaceStarted) return;
272
- workspaceStarted = true;
273
- for (const app of apps) startApp(app);
274
- try {
275
- fs.watch(appsDir, { recursive: true }, scheduleSync);
276
- } catch {
277
- // Some platforms do not support recursive directory watches.
278
- }
279
- setInterval(syncApps, 2_000).unref();
280
- }
281
-
282
- function openBrowser(url: string): void {
283
- if (process.env.WORKSPACE_NO_OPEN === "1") return;
284
- const command =
285
- process.platform === "darwin"
286
- ? "open"
287
- : process.platform === "win32"
288
- ? "cmd"
289
- : "xdg-open";
290
- const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
291
- const child = spawn(command, args, {
292
- stdio: "ignore",
293
- detached: true,
294
- });
295
- child.unref();
296
- }
297
-
298
- const server = http.createServer((req, res) => {
299
- if (req.url === "/" || req.url === "/index.html") {
300
- res.writeHead(302, { location: `/${defaultApp}` });
301
- res.end();
302
- return;
303
- }
304
-
305
- if (req.url === "/_workspace/apps") {
306
- res.writeHead(200, { "content-type": "application/json" });
307
- res.end(
308
- JSON.stringify(
309
- apps.map((app) => ({
310
- id: app.id,
311
- name: app.name,
312
- path: `/${app.id}`,
313
- port: app.port,
314
- })),
315
- ),
316
- );
317
- return;
318
- }
319
-
320
- const app = appForRequest(req);
321
- if (!app) {
322
- res.writeHead(404, { "content-type": "text/html" });
323
- res.end(renderIndex());
324
- return;
325
- }
326
- proxyHttp(app, req, res);
327
- });
328
-
329
- server.on("upgrade", (req, socket, head) => {
330
- const app = appForRequest(req);
331
- if (!app) {
332
- socket.destroy();
333
- return;
334
- }
335
- proxyUpgrade(app, req, socket, head);
336
- });
337
-
338
- function listen(port: number, attempts = 20): void {
339
- server.once("error", (err: NodeJS.ErrnoException) => {
340
- if (err.code === "EADDRINUSE" && attempts > 0) {
341
- listen(port + 1, attempts - 1);
342
- return;
343
- }
344
- console.error(`[workspace] Could not start gateway: ${err.message}`);
345
- process.exit(1);
346
- });
347
- server.listen(port, gatewayHost, () => {
348
- const address = server.address();
349
- const actualPort =
350
- typeof address === "object" && address ? address.port : port;
351
- gatewayUrl = `http://${gatewayHost}:${actualPort}`;
352
- console.log(`[workspace] Gateway: http://${gatewayHost}:${actualPort}`);
353
- console.log(
354
- `[workspace] Default: http://${gatewayHost}:${actualPort}/${defaultApp}`,
355
- );
356
- for (const app of apps) {
357
- console.log(`[workspace] ${app.id}: /${app.id} -> 127.0.0.1:${app.port}`);
358
- }
359
- startWorkspaceProcesses();
360
- openBrowser(`http://${gatewayHost}:${actualPort}/${defaultApp}`);
361
- });
362
- }
363
-
364
- function shutdown(): void {
365
- if (shuttingDown) return;
366
- shuttingDown = true;
367
- server.close();
368
- for (const app of apps) {
369
- app.process?.kill("SIGTERM");
370
- }
371
- setTimeout(() => process.exit(0), 300).unref();
372
- }
373
-
374
- process.on("SIGINT", shutdown);
375
- process.on("SIGTERM", shutdown);
376
-
377
- listen(requestedPort);
@@ -1,100 +0,0 @@
1
- {
2
- "hooks": {
3
- "UserPromptSubmit": [
4
- {
5
- "hooks": [
6
- {
7
- "type": "command",
8
- "command": "pnpm action view-screen 2>/dev/null || echo '{\"view\": \"unknown\"}'",
9
- "timeout": 10
10
- }
11
- ]
12
- }
13
- ]
14
- },
15
- "permissions": {
16
- "allow": [
17
- "Read",
18
- "Edit",
19
- "Write",
20
- "Glob",
21
- "Grep",
22
- "NotebookEdit",
23
- "WebFetch",
24
- "WebSearch",
25
- "Bash(ls *)",
26
- "Bash(pwd)",
27
- "Bash(echo *)",
28
- "Bash(cat *)",
29
- "Bash(head *)",
30
- "Bash(tail *)",
31
- "Bash(find *)",
32
- "Bash(wc *)",
33
- "Bash(sort *)",
34
- "Bash(uniq *)",
35
- "Bash(diff *)",
36
- "Bash(which *)",
37
- "Bash(env)",
38
- "Bash(mkdir *)",
39
- "Bash(cp *)",
40
- "Bash(mv *)",
41
- "Bash(touch *)",
42
- "Bash(chmod *)",
43
- "Bash(cd *)",
44
- "Bash(node *)",
45
- "Bash(npx *)",
46
- "Bash(npm *)",
47
- "Bash(pnpm *)",
48
- "Bash(yarn *)",
49
- "Bash(tsx *)",
50
- "Bash(tsc *)",
51
- "Bash(vitest *)",
52
- "Bash(jest *)",
53
- "Bash(eslint *)",
54
- "Bash(prettier *)",
55
- "Bash(git status*)",
56
- "Bash(git log *)",
57
- "Bash(git diff *)",
58
- "Bash(git show *)",
59
- "Bash(git branch*)",
60
- "Bash(git add *)",
61
- "Bash(git commit *)",
62
- "Bash(git checkout *)",
63
- "Bash(git switch *)",
64
- "Bash(git stash *)",
65
- "Bash(git merge *)",
66
- "Bash(git rebase *)",
67
- "Bash(git pull *)",
68
- "Bash(git blame *)",
69
- "Bash(git rev-parse *)",
70
- "Bash(git worktree *)",
71
- "Bash(git remote -v)",
72
- "Bash(gh *)",
73
- "Bash(curl *)",
74
- "Bash(grep *)",
75
- "Bash(rg *)",
76
- "Bash(sed *)",
77
- "Bash(awk *)",
78
- "Bash(jq *)",
79
- "Bash(rm *)"
80
- ],
81
- "deny": [
82
- "Bash(rm -rf /)",
83
- "Bash(rm -rf /*)",
84
- "Bash(rm -rf ~)",
85
- "Bash(rm -rf ~/*)",
86
- "Bash(sudo *)",
87
- "Bash(git push --force *)",
88
- "Bash(git push -f *)",
89
- "Bash(git reset --hard *)",
90
- "Bash(git clean -f *)",
91
- "Bash(dd *)",
92
- "Bash(mkfs *)",
93
- "Bash(kill -9 *)",
94
- "Bash(killall *)",
95
- "Bash(pkill *)",
96
- "Bash(shutdown *)",
97
- "Bash(reboot *)"
98
- ]
99
- }
100
- }
@@ -1,42 +0,0 @@
1
- ---
2
- name: company-policies
3
- description: {{APP_TITLE}}-wide policies the agent must enforce for every app — data handling, PII, approval flows, compliance rules.
4
- ---
5
-
6
- # {{APP_TITLE}} Company Policies
7
-
8
- Every app in the workspace shares these policies. Read this skill before
9
- taking any action that touches customer data, external services, or
10
- deployed state.
11
-
12
- ## Data handling
13
-
14
- - **PII minimization.** Only load the fields you actually need. Never
15
- `SELECT *` on a table that contains customer records.
16
- - **No raw customer email in logs.** Hash or redact before logging.
17
- - **Retention.** Deleted records are soft-deleted first and purged by a
18
- scheduled job. Do not write actions that hard-delete customer data.
19
-
20
- ## Third-party calls
21
-
22
- - **Allowlist only.** Only call domains on the approved allowlist
23
- (documented in the root `README.md`). If an integration needs a new
24
- domain, surface a warning and wait for human approval before making
25
- the call.
26
- - **Secrets come from `resolveCompanyCredential`.** Never hardcode.
27
- Never check secrets into git. Rotating a key in the central store
28
- updates every app on the next request.
29
-
30
- ## Approval flows
31
-
32
- - **Destructive operations need a confirmation preview.** Any action
33
- that modifies production data must first return a preview of the
34
- change (what will be created / updated / deleted) and wait for
35
- explicit user confirmation before executing.
36
-
37
- ## Apply across apps
38
-
39
- This skill is loaded automatically in every workspace app. If an
40
- individual app needs different behavior, it can add a same-named skill
41
- under its own `.agents/skills/company-policies/SKILL.md` and that copy
42
- will win for that app only.
@@ -1,38 +0,0 @@
1
- /**
2
- * Shared action: look up an employee in the company directory.
3
- *
4
- * Every app in the workspace inherits this action automatically — no
5
- * wiring required. From the agent's perspective it behaves exactly like
6
- * a template action: the tool shows up in every app's agent, and calling
7
- * it from the UI via `useActionQuery("company-directory", { ... })` Just
8
- * Works.
9
- *
10
- * Replace the stub implementation with a real call to your company
11
- * directory (SCIM, Okta Users API, internal /people endpoint, etc.).
12
- */
13
- import { z } from "zod";
14
- import { defineAction } from "@agent-native/core";
15
-
16
- export default defineAction({
17
- description:
18
- "Look up a person in the {{APP_TITLE}} company directory by name or email. Returns role, team, and manager.",
19
- schema: z.object({
20
- query: z.string().describe("Name, email, or partial match to search for"),
21
- }),
22
- run: async (args) => {
23
- // TODO: replace with a real lookup. This stub just echoes the query
24
- // so the agent has a reasonable no-op while you wire up the real
25
- // directory integration.
26
- return {
27
- results: [
28
- {
29
- query: args.query,
30
- name: "(stub) " + args.query,
31
- role: "Unknown",
32
- team: "Unknown",
33
- manager: null,
34
- },
35
- ],
36
- };
37
- },
38
- });
@@ -1,37 +0,0 @@
1
- /**
2
- * Shared authenticated layout for every app in the @{{APP_NAME}} workspace.
3
- *
4
- * Provides the common chrome (brand header, user menu, agent chat sidebar)
5
- * so individual apps only have to render their own content. Replace this
6
- * with a real component that pulls in your design system. Every app
7
- * imports it the same way:
8
- *
9
- * import { AuthenticatedLayout } from "@{{APP_NAME}}/core-module/client";
10
- *
11
- * export default function Home() {
12
- * return (
13
- * <AuthenticatedLayout>
14
- * <h1>My app's screen</h1>
15
- * </AuthenticatedLayout>
16
- * );
17
- * }
18
- */
19
- import type { ReactNode } from "react";
20
-
21
- export interface AuthenticatedLayoutProps {
22
- children: ReactNode;
23
- }
24
-
25
- // Workspace title — replaced at scaffold time by the create-workspace CLI.
26
- const WORKSPACE_TITLE = "{{APP_TITLE}}";
27
-
28
- export function AuthenticatedLayout({ children }: AuthenticatedLayoutProps) {
29
- return (
30
- <div className="min-h-screen flex flex-col">
31
- <header className="border-b px-6 py-3">
32
- <strong>{WORKSPACE_TITLE}</strong>
33
- </header>
34
- <main className="flex-1 p-6">{children}</main>
35
- </div>
36
- );
37
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * Centralized credential helpers for the @{{APP_NAME}} workspace.
3
- *
4
- * Every enterprise has a few API keys that multiple apps need to share:
5
- * a Slack bot token, a Sentry DSN, an OpenAI key, internal service
6
- * credentials. Instead of each app reading them separately, we namespace
7
- * them here so there's a single place to update when a key rotates.
8
- *
9
- * Under the hood this is a thin wrapper over @agent-native/core's
10
- * `resolveCredential()`, which reads per-user / per-org rows in the
11
- * shared SQL settings table. Apps inside the workspace share the same
12
- * DATABASE_URL by default, so storing a credential once makes it
13
- * available everywhere.
14
- *
15
- * A request/action context is required so credentials stay scoped to the
16
- * correct user and organization. This helper can read that context
17
- * automatically inside agent-native actions; otherwise pass it explicitly.
18
- */
19
- import { resolveCredential } from "@agent-native/core/credentials";
20
- import {
21
- getRequestOrgId,
22
- getRequestUserEmail,
23
- } from "@agent-native/core/server";
24
-
25
- /**
26
- * Optional context for scoping a credential lookup to a specific user or org.
27
- */
28
- export interface CompanyCredentialContext {
29
- userEmail?: string;
30
- orgId?: string | null;
31
- }
32
-
33
- type ResolveCredentialFn = (
34
- key: string,
35
- ctx: CompanyCredentialContext,
36
- ) => Promise<string | undefined>;
37
-
38
- /**
39
- * Resolve a company-wide credential. Prefer this over `resolveCredential()`
40
- * directly — it keeps your keys organized under a workspace namespace and
41
- * makes "where does this secret come from" greppable.
42
- *
43
- * Inside an agent-native action:
44
- * const slackToken = await resolveCompanyCredential("SLACK_BOT_TOKEN");
45
- *
46
- * Outside request context:
47
- * const slackToken = await resolveCompanyCredential("SLACK_BOT_TOKEN", {
48
- * userEmail: session.email,
49
- * orgId: session.orgId ?? null,
50
- * });
51
- */
52
- export async function resolveCompanyCredential(
53
- key: string,
54
- ctx?: CompanyCredentialContext,
55
- ): Promise<string | undefined> {
56
- const effectiveCtx: CompanyCredentialContext = ctx?.userEmail
57
- ? ctx
58
- : {
59
- userEmail: getRequestUserEmail() ?? undefined,
60
- orgId: getRequestOrgId(),
61
- };
62
- if (!effectiveCtx.userEmail) return undefined;
63
- return await (resolveCredential as ResolveCredentialFn)(key, {
64
- userEmail: effectiveCtx.userEmail,
65
- orgId: effectiveCtx.orgId ?? null,
66
- });
67
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * Workspace-wide agent-chat plugin for @{{APP_NAME}}/core-module.
3
- *
4
- * This mounts the framework's default agent-chat plugin so every app in
5
- * the workspace gets the same chat endpoint, mention providers, and
6
- * built-in tools. The ENTERPRISE-WIDE system prompt additions — things
7
- * the agent should know across every app — live in the workspace's
8
- * AGENTS.md file, which is loaded automatically into the prompt as a
9
- * `<resource scope="workspace">` block.
10
- *
11
- * Customize this wrapper when you need agent behavior that can't be
12
- * expressed in AGENTS.md — e.g. injecting enterprise-specific mention
13
- * providers, pre-loading a custom set of MCP servers, or rewriting
14
- * model choice based on your company's allowlist.
15
- */
16
- import { defaultAgentChatPlugin } from "@agent-native/core/server";
17
-
18
- export const agentChatPlugin = async (nitroApp: any): Promise<void> => {
19
- await defaultAgentChatPlugin(nitroApp);
20
-
21
- // Hook for enterprise customization:
22
- //
23
- // const chat = createAgentChatPlugin({
24
- // systemPrompt: (base) => `${base}\n\nCompany policy: …`,
25
- // mentionProviders: {
26
- // people: async (query) => searchCompanyDirectory(query),
27
- // },
28
- // });
29
- // await chat(nitroApp);
30
- };