create-absolutejs 0.15.2 → 0.15.3

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.
@@ -2,13 +2,15 @@ import { exit } from 'process';
2
2
  import { spinner } from '@clack/prompts';
3
3
  import { $ } from 'bun';
4
4
  import { green, red } from 'picocolors';
5
- import { formatCommands, formatNoInstallCommands } from '../utils/commandMaps';
5
+ import { formatCommands } from '../utils/commandMaps';
6
6
  export const formatProject = async ({ projectName, packageManager, installDependenciesNow }) => {
7
+ // A no-install scaffold must be fully offline and must not assume a global
8
+ // formatter. Templates are already formatted in the published package.
9
+ if (!installDependenciesNow)
10
+ return;
7
11
  const spin = spinner();
8
12
  try {
9
- const fmt = installDependenciesNow
10
- ? formatCommands[packageManager]
11
- : formatNoInstallCommands[packageManager];
13
+ const fmt = formatCommands[packageManager];
12
14
  spin.start('Formatting files…');
13
15
  const [bin, ...args] = fmt.split(' ');
14
16
  await $ `${bin} ${args}`.cwd(projectName).quiet();
@@ -1,8 +1,8 @@
1
1
  import type { CreateConfiguration } from '../../types';
2
- type CreatePackageJsonProps = Pick<CreateConfiguration, 'authOption' | 'useTailwind' | 'databaseEngine' | 'databaseHost' | 'plugins' | 'orm' | 'frontendDirectories' | 'codeQualityTool'> & {
2
+ type CreatePackageJsonProps = Pick<CreateConfiguration, 'authOption' | 'agentic' | 'useTailwind' | 'databaseEngine' | 'databaseHost' | 'plugins' | 'orm' | 'frontendDirectories' | 'codeQualityTool'> & {
3
3
  projectName: string;
4
4
  latest: boolean;
5
5
  repositoryUrl: string | undefined;
6
6
  };
7
- export declare const createPackageJson: ({ projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }: CreatePackageJsonProps) => Promise<void>;
7
+ export declare const createPackageJson: ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }: CreatePackageJsonProps) => Promise<void>;
8
8
  export {};
@@ -16,7 +16,7 @@ const dbClientCommands = {
16
16
  postgresql: 'psql -h localhost -U user -d database',
17
17
  singlestore: 'singlestore -u root -ppassword -D database'
18
18
  };
19
- export const createPackageJson = async ({ projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }) => {
19
+ export const createPackageJson = async ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }) => {
20
20
  const flags = computeFlags(frontendDirectories);
21
21
  const isLocal = !databaseHost || databaseHost === 'none';
22
22
  /* ── Collect all package names that need versions ─────────── */
@@ -28,6 +28,27 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
28
28
  packageNames.add(dep.value);
29
29
  if (authOption === 'abs')
30
30
  packageNames.add(absoluteAuthPlugin.value);
31
+ if (agentic) {
32
+ packageNames.add('@absolutejs/a2a');
33
+ packageNames.add('@absolutejs/agency');
34
+ packageNames.add('@absolutejs/agent-conformance');
35
+ packageNames.add('@absolutejs/agent-discovery');
36
+ packageNames.add('@absolutejs/agent-inbox');
37
+ packageNames.add('@absolutejs/agent-memory');
38
+ packageNames.add('@absolutejs/agent-runtime');
39
+ packageNames.add('@absolutejs/agent-sandbox');
40
+ packageNames.add('@absolutejs/agent-trust');
41
+ packageNames.add('@absolutejs/agent-control');
42
+ packageNames.add('@absolutejs/auth');
43
+ packageNames.add('@absolutejs/egress');
44
+ packageNames.add('@absolutejs/execution');
45
+ packageNames.add('@absolutejs/manifest');
46
+ packageNames.add('@absolutejs/mcp');
47
+ packageNames.add('@absolutejs/policy');
48
+ packageNames.add('@absolutejs/secrets');
49
+ packageNames.add('@absolutejs/sync-bus-pg');
50
+ packageNames.add('@absolutejs/wallet');
51
+ }
31
52
  for (const pluginValue of plugins) {
32
53
  const meta = availablePlugins.find((p) => p.value === pluginValue);
33
54
  if (meta)
@@ -122,6 +143,31 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
122
143
  if (authOption === 'abs') {
123
144
  dependencies[absoluteAuthPlugin.value] = resolveVersion(absoluteAuthPlugin.value, absoluteAuthPlugin.latestVersion);
124
145
  }
146
+ if (agentic) {
147
+ for (const name of [
148
+ '@absolutejs/a2a',
149
+ '@absolutejs/agency',
150
+ '@absolutejs/agent-discovery',
151
+ '@absolutejs/agent-inbox',
152
+ '@absolutejs/agent-memory',
153
+ '@absolutejs/agent-runtime',
154
+ '@absolutejs/agent-sandbox',
155
+ '@absolutejs/agent-trust',
156
+ '@absolutejs/agent-control',
157
+ '@absolutejs/auth',
158
+ '@absolutejs/egress',
159
+ '@absolutejs/execution',
160
+ '@absolutejs/manifest',
161
+ '@absolutejs/mcp',
162
+ '@absolutejs/policy',
163
+ '@absolutejs/secrets',
164
+ '@absolutejs/sync-bus-pg',
165
+ '@absolutejs/wallet'
166
+ ]) {
167
+ dependencies[name] = resolveVersion(name, versions[name]);
168
+ }
169
+ devDependencies['@absolutejs/agent-conformance'] = resolveVersion('@absolutejs/agent-conformance', versions['@absolutejs/agent-conformance']);
170
+ }
125
171
  for (const pluginValue of plugins) {
126
172
  const meta = availablePlugins.find((p) => p.value === pluginValue);
127
173
  if (!meta)
@@ -0,0 +1,7 @@
1
+ export declare const agentRuntimeSource = "import {\n\tcreateAgency,\n\tcreateAgentControlPlane,\n\tcreateMemoryAgencyStore,\n\tcreateMemoryAgentControlStore,\n\tdenyAllPolicy\n} from '@absolutejs/agency'\nimport {\n\tcreateAgentRuntime,\n\tcreateMemoryAgentRuntimeStore\n} from '@absolutejs/agent-runtime'\n\n// Memory stores are development defaults. Replace them with durable stores\n// before running more than one process or accepting production actions.\nexport const agentControl = createAgentControlPlane({\n\tsources: [],\n\tstore: createMemoryAgentControlStore()\n})\n\n// Intentionally deny-by-default. Replace denyAllPolicy() with your policy\n// decision point only after declaring each action's effects and scopes.\nexport const agency = createAgency({\n\tcontrol: agentControl,\n\tpolicy: denyAllPolicy(),\n\tstore: createMemoryAgencyStore()\n})\n\n// Durable run semantics are available from the first commit. The placeholder\n// driver fails closed until the application supplies its model/tool loop.\nexport const agentRuntime = createAgentRuntime({\n\tstore: createMemoryAgentRuntimeStore(),\n\tdriver: {\n\t\tnext: async () => ({\n\t\t\ttype: 'fail',\n\t\t\tcode: 'agent_not_configured',\n\t\t\tmessage: 'Configure the agent driver before accepting runs'\n\t\t})\n\t},\n\teffects: {\n\t\texecute: async () => {\n\t\t\tthrow new Error('Agent effects are not configured')\n\t\t}\n\t}\n})\n";
2
+ export declare const agentDiscoverySource = "import {\n\tABSOLUTE_AGENT_SCHEMA,\n\tcreateAgentDiscoveryHandler,\n\tsignAgentDocument,\n\ttype AgentDiscoveryDocument,\n\ttype DiscoverySigner\n} from '@absolutejs/agent-discovery'\n\n// Keep this document specific and keyword-rich: registries rank declared\n// capabilities, effects, scopes, interfaces, examples, and publisher trust.\nexport const createAgentDocument = ({\n\torigin,\n\tpublishedAt,\n\tversion\n}: {\n\torigin: string\n\tpublishedAt: string\n\tversion: string\n}): AgentDiscoveryDocument => ({\n\t$schema: ABSOLUTE_AGENT_SCHEMA,\n\tid: `${origin}/agents/main`,\n\tname: 'Replace with your agent name',\n\tdescription: 'Replace with a precise description of the outcomes this agent delivers.',\n\tversion,\n\turl: origin,\n\tpublisher: {\n\t\tid: origin,\n\t\tname: 'Replace with your organization',\n\t\tjwksUri: `${origin}/.well-known/jwks.json`\n\t},\n\tcapabilities: [{\n\t\tid: 'status.read',\n\t\ttitle: 'Read service status',\n\t\tdescription: 'Returns the public health and readiness status of this agent.',\n\t\ttags: ['status', 'health', 'readiness'],\n\t\teffects: ['read'],\n\t\tapproval: 'never'\n\t}],\n\tinterfaces: [{\n\t\ttype: 'http',\n\t\turl: `${origin}/api/agents/main`,\n\t\tcontentTypes: ['application/json']\n\t}],\n\tcategories: ['replace-with-domain-category'],\n\ttags: ['replace-with-user-intent', 'replace-with-outcome'],\n\tlanguages: ['en'],\n\tdocumentationUrl: `${origin}/docs/agents/main`,\n\texamples: [{\n\t\ttitle: 'Check whether the agent is ready',\n\t\tprompt: 'Check the agent service status.',\n\t\tcapabilityId: 'status.read'\n\t}],\n\tcreatedAt: publishedAt,\n\tupdatedAt: publishedAt\n})\n\n// Use a KMS/HSM-backed signer in production. Mount the returned fetch handler\n// at the origin root so all well-known, A2A, JSON-LD, agents.txt, and sitemap\n// discovery surfaces are served from one signed descriptor.\nexport const createAgentDiscovery = async ({\n\tsigner,\n\torigin,\n\tpublishedAt,\n\tversion\n}: {\n\tsigner: DiscoverySigner\n\torigin: string\n\tpublishedAt: string\n\tversion: string\n}) =>\n\tcreateAgentDiscoveryHandler({\n\t\tdocuments: [await signAgentDocument(\n\t\t\tcreateAgentDocument({ origin, publishedAt, version }),\n\t\t\tsigner\n\t\t)]\n\t})\n";
3
+ export declare const agentsGuide = "# Agent execution contract\n\nThis project uses the AbsoluteJS provider-neutral agent stack.\n\n- Authenticate agents and bind every delegation to a user with\n `@absolutejs/auth`. Never treat model-provided identity as authenticated.\n- Route every effectful tool through `agency` in `src/backend/agent.ts`.\n Approval is exact-input-bound; execution requires a fresh single-use lease.\n- Declare tool effects, scopes, approval policy, idempotency keys,\n reversibility, destinations, and spend fields in manifest contract 2.\n- Keep raw credentials host-side with `@absolutejs/secrets` credential\n operations. Agents receive operation results, never secret values.\n- Give agents bounded wallet allowances and signed mandates. The host resolves\n ledger destinations; an agent never supplies the recipient account id.\n- Bind MCP task handles to the authenticated actor on get, update, and cancel.\n- Use `@absolutejs/execution` for idempotent effects and its transactional\n PostgreSQL outbox before handing work to a durable queue.\n- Publish and consume remote agents with `@absolutejs/a2a` using A2A 1.0;\n preserve the authenticated tenant and actor binding at every task boundary.\n- Route outbound HTTP through `@absolutejs/egress`. Authorize host, method,\n resolved public IP, redirects, byte limits, and injected credentials host-side.\n- Store immutable, digest-addressed policy revisions with `@absolutejs/policy`\n and atomically activate only reviewed versions.\n- Publish the signed descriptor in `src/backend/agent-discovery.ts` through\n `@absolutejs/agent-discovery`. Keep capabilities, examples, tags, effects,\n scopes, A2A/MCP interfaces, JSON-LD, agents.txt, and sitemap surfaces current.\n- Run long-lived work through `@absolutejs/agent-runtime`; use its leases,\n checkpoints, timers, budgets, cancellation, and crash-safe effect recovery.\n- Authorize all HTTP/filesystem/process access with expiring\n `@absolutejs/agent-sandbox` grants. There is no ambient agent authority.\n- Preserve instruction/data separation and provenance taints with\n `@absolutejs/agent-trust`; external content never becomes an instruction.\n- Store scoped, expiring, provenance-bearing data with\n `@absolutejs/agent-memory`, and validate writes against memory poisoning.\n- Receive only verified events through `@absolutejs/agent-inbox`; durable\n leases, retries, dead letters, and schedules do not require Redis.\n- Use OpenID AuthZEN AARP for requestable approvals and COAZ mappings for\n parameter-level MCP authorization. Approval always triggers re-evaluation.\n- Protect operator actions with `@absolutejs/agent-control` scopes, a\n kill-switch-first check, and leased idempotency records.\n- Use `@absolutejs/sync-bus-pg` for durable framework channels. Redis is an\n optional at-most-once fanout adapter, not a source of truth or work queue.\n- Run `@absolutejs/agent-conformance` suites for every new action, capability,\n credential, wallet, egress, execution, control, and task adapter.\n- Use the control plane kill switch for incident response. It blocks new\n requests, lease issuance, and execution before downstream revocation fans out.\n\nMemory stores are for local development only. Production stores must be\ndurable and enforce lease/capability consumption atomically. Apply each\npackage's exported PostgreSQL schema in a migration before enabling traffic.\n";
4
+ export declare const scaffoldAgentic: ({ backendDirectory, projectName }: {
5
+ backendDirectory: string;
6
+ projectName: string;
7
+ }) => void;
@@ -0,0 +1,181 @@
1
+ import { mkdirSync, writeFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ export const agentRuntimeSource = `import {
4
+ createAgency,
5
+ createAgentControlPlane,
6
+ createMemoryAgencyStore,
7
+ createMemoryAgentControlStore,
8
+ denyAllPolicy
9
+ } from '@absolutejs/agency'
10
+ import {
11
+ createAgentRuntime,
12
+ createMemoryAgentRuntimeStore
13
+ } from '@absolutejs/agent-runtime'
14
+
15
+ // Memory stores are development defaults. Replace them with durable stores
16
+ // before running more than one process or accepting production actions.
17
+ export const agentControl = createAgentControlPlane({
18
+ sources: [],
19
+ store: createMemoryAgentControlStore()
20
+ })
21
+
22
+ // Intentionally deny-by-default. Replace denyAllPolicy() with your policy
23
+ // decision point only after declaring each action's effects and scopes.
24
+ export const agency = createAgency({
25
+ control: agentControl,
26
+ policy: denyAllPolicy(),
27
+ store: createMemoryAgencyStore()
28
+ })
29
+
30
+ // Durable run semantics are available from the first commit. The placeholder
31
+ // driver fails closed until the application supplies its model/tool loop.
32
+ export const agentRuntime = createAgentRuntime({
33
+ store: createMemoryAgentRuntimeStore(),
34
+ driver: {
35
+ next: async () => ({
36
+ type: 'fail',
37
+ code: 'agent_not_configured',
38
+ message: 'Configure the agent driver before accepting runs'
39
+ })
40
+ },
41
+ effects: {
42
+ execute: async () => {
43
+ throw new Error('Agent effects are not configured')
44
+ }
45
+ }
46
+ })
47
+ `;
48
+ export const agentDiscoverySource = `import {
49
+ ABSOLUTE_AGENT_SCHEMA,
50
+ createAgentDiscoveryHandler,
51
+ signAgentDocument,
52
+ type AgentDiscoveryDocument,
53
+ type DiscoverySigner
54
+ } from '@absolutejs/agent-discovery'
55
+
56
+ // Keep this document specific and keyword-rich: registries rank declared
57
+ // capabilities, effects, scopes, interfaces, examples, and publisher trust.
58
+ export const createAgentDocument = ({
59
+ origin,
60
+ publishedAt,
61
+ version
62
+ }: {
63
+ origin: string
64
+ publishedAt: string
65
+ version: string
66
+ }): AgentDiscoveryDocument => ({
67
+ $schema: ABSOLUTE_AGENT_SCHEMA,
68
+ id: \`\${origin}/agents/main\`,
69
+ name: 'Replace with your agent name',
70
+ description: 'Replace with a precise description of the outcomes this agent delivers.',
71
+ version,
72
+ url: origin,
73
+ publisher: {
74
+ id: origin,
75
+ name: 'Replace with your organization',
76
+ jwksUri: \`\${origin}/.well-known/jwks.json\`
77
+ },
78
+ capabilities: [{
79
+ id: 'status.read',
80
+ title: 'Read service status',
81
+ description: 'Returns the public health and readiness status of this agent.',
82
+ tags: ['status', 'health', 'readiness'],
83
+ effects: ['read'],
84
+ approval: 'never'
85
+ }],
86
+ interfaces: [{
87
+ type: 'http',
88
+ url: \`\${origin}/api/agents/main\`,
89
+ contentTypes: ['application/json']
90
+ }],
91
+ categories: ['replace-with-domain-category'],
92
+ tags: ['replace-with-user-intent', 'replace-with-outcome'],
93
+ languages: ['en'],
94
+ documentationUrl: \`\${origin}/docs/agents/main\`,
95
+ examples: [{
96
+ title: 'Check whether the agent is ready',
97
+ prompt: 'Check the agent service status.',
98
+ capabilityId: 'status.read'
99
+ }],
100
+ createdAt: publishedAt,
101
+ updatedAt: publishedAt
102
+ })
103
+
104
+ // Use a KMS/HSM-backed signer in production. Mount the returned fetch handler
105
+ // at the origin root so all well-known, A2A, JSON-LD, agents.txt, and sitemap
106
+ // discovery surfaces are served from one signed descriptor.
107
+ export const createAgentDiscovery = async ({
108
+ signer,
109
+ origin,
110
+ publishedAt,
111
+ version
112
+ }: {
113
+ signer: DiscoverySigner
114
+ origin: string
115
+ publishedAt: string
116
+ version: string
117
+ }) =>
118
+ createAgentDiscoveryHandler({
119
+ documents: [await signAgentDocument(
120
+ createAgentDocument({ origin, publishedAt, version }),
121
+ signer
122
+ )]
123
+ })
124
+ `;
125
+ export const agentsGuide = `# Agent execution contract
126
+
127
+ This project uses the AbsoluteJS provider-neutral agent stack.
128
+
129
+ - Authenticate agents and bind every delegation to a user with
130
+ \`@absolutejs/auth\`. Never treat model-provided identity as authenticated.
131
+ - Route every effectful tool through \`agency\` in \`src/backend/agent.ts\`.
132
+ Approval is exact-input-bound; execution requires a fresh single-use lease.
133
+ - Declare tool effects, scopes, approval policy, idempotency keys,
134
+ reversibility, destinations, and spend fields in manifest contract 2.
135
+ - Keep raw credentials host-side with \`@absolutejs/secrets\` credential
136
+ operations. Agents receive operation results, never secret values.
137
+ - Give agents bounded wallet allowances and signed mandates. The host resolves
138
+ ledger destinations; an agent never supplies the recipient account id.
139
+ - Bind MCP task handles to the authenticated actor on get, update, and cancel.
140
+ - Use \`@absolutejs/execution\` for idempotent effects and its transactional
141
+ PostgreSQL outbox before handing work to a durable queue.
142
+ - Publish and consume remote agents with \`@absolutejs/a2a\` using A2A 1.0;
143
+ preserve the authenticated tenant and actor binding at every task boundary.
144
+ - Route outbound HTTP through \`@absolutejs/egress\`. Authorize host, method,
145
+ resolved public IP, redirects, byte limits, and injected credentials host-side.
146
+ - Store immutable, digest-addressed policy revisions with \`@absolutejs/policy\`
147
+ and atomically activate only reviewed versions.
148
+ - Publish the signed descriptor in \`src/backend/agent-discovery.ts\` through
149
+ \`@absolutejs/agent-discovery\`. Keep capabilities, examples, tags, effects,
150
+ scopes, A2A/MCP interfaces, JSON-LD, agents.txt, and sitemap surfaces current.
151
+ - Run long-lived work through \`@absolutejs/agent-runtime\`; use its leases,
152
+ checkpoints, timers, budgets, cancellation, and crash-safe effect recovery.
153
+ - Authorize all HTTP/filesystem/process access with expiring
154
+ \`@absolutejs/agent-sandbox\` grants. There is no ambient agent authority.
155
+ - Preserve instruction/data separation and provenance taints with
156
+ \`@absolutejs/agent-trust\`; external content never becomes an instruction.
157
+ - Store scoped, expiring, provenance-bearing data with
158
+ \`@absolutejs/agent-memory\`, and validate writes against memory poisoning.
159
+ - Receive only verified events through \`@absolutejs/agent-inbox\`; durable
160
+ leases, retries, dead letters, and schedules do not require Redis.
161
+ - Use OpenID AuthZEN AARP for requestable approvals and COAZ mappings for
162
+ parameter-level MCP authorization. Approval always triggers re-evaluation.
163
+ - Protect operator actions with \`@absolutejs/agent-control\` scopes, a
164
+ kill-switch-first check, and leased idempotency records.
165
+ - Use \`@absolutejs/sync-bus-pg\` for durable framework channels. Redis is an
166
+ optional at-most-once fanout adapter, not a source of truth or work queue.
167
+ - Run \`@absolutejs/agent-conformance\` suites for every new action, capability,
168
+ credential, wallet, egress, execution, control, and task adapter.
169
+ - Use the control plane kill switch for incident response. It blocks new
170
+ requests, lease issuance, and execution before downstream revocation fans out.
171
+
172
+ Memory stores are for local development only. Production stores must be
173
+ durable and enforce lease/capability consumption atomically. Apply each
174
+ package's exported PostgreSQL schema in a migration before enabling traffic.
175
+ `;
176
+ export const scaffoldAgentic = ({ backendDirectory, projectName }) => {
177
+ mkdirSync(backendDirectory, { recursive: true });
178
+ writeFileSync(join(backendDirectory, 'agent.ts'), agentRuntimeSource);
179
+ writeFileSync(join(backendDirectory, 'agent-discovery.ts'), agentDiscoverySource);
180
+ writeFileSync(join(projectName, 'AGENTS.md'), agentsGuide);
181
+ };
@@ -10,5 +10,5 @@ type DebugMessageProps = {
10
10
  response: CreateConfiguration;
11
11
  packageManager: string;
12
12
  };
13
- export declare const getDebugMessage: ({ response: { projectName, codeQualityTool, directoryConfig, useTailwind, tailwind, frontends, includeExamples, useHTMLScripts, frontendDirectories, buildDirectory, assetsDirectory, databaseEngine, databaseHost, databaseDirectory, orm, authOption, plugins, initializeGitNow, installDependenciesNow }, packageManager }: DebugMessageProps) => string;
13
+ export declare const getDebugMessage: ({ response: { agentic, projectName, codeQualityTool, directoryConfig, useTailwind, tailwind, frontends, includeExamples, useHTMLScripts, frontendDirectories, buildDirectory, assetsDirectory, databaseEngine, databaseHost, databaseDirectory, orm, authOption, plugins, initializeGitNow, installDependenciesNow }, packageManager }: DebugMessageProps) => string;
14
14
  export {};
package/dist/messages.js CHANGED
@@ -12,6 +12,7 @@ Options:
12
12
  ${cyan('--debug, -d')} Display a summary of the project configuration after creation
13
13
 
14
14
  ${cyan('--abs-provider')} A provider for Absolute-Auth (eg. 'google', 'github', 'discord') the full list is available at https://absolutejs.com/documentation/absolute-auth
15
+ ${cyan('--agentic')} Add provider-neutral agent auth, actions, MCP, wallet, credential, and conformance scaffolding
15
16
  ${cyan('--angular')} Include an Angular frontend
16
17
  ${cyan('--angular-dir')} ${dim(cyan('<directory>'))} Specify the directory for and use the Angular frontend
17
18
  ${cyan('--assets')} ${dim(cyan('<directory>'))} Directory name for your static assets
@@ -49,7 +50,7 @@ export const getOutroMessage = ({ projectName, packageManager, installDependenci
49
50
  `${cyan('cd')} ${projectName}\n` +
50
51
  `${installDependenciesNow ? '' : `${cyan(`${packageManager} install`)}\n`}` +
51
52
  `${cyan(`${packageManager} dev`)}`; // TODO: Some package managers need run
52
- export const getDebugMessage = ({ response: { projectName, codeQualityTool, directoryConfig, useTailwind, tailwind, frontends, includeExamples, useHTMLScripts, frontendDirectories, buildDirectory, assetsDirectory, databaseEngine, databaseHost, databaseDirectory, orm, authOption, plugins, initializeGitNow, installDependenciesNow }, packageManager }) => {
53
+ export const getDebugMessage = ({ response: { agentic, projectName, codeQualityTool, directoryConfig, useTailwind, tailwind, frontends, includeExamples, useHTMLScripts, frontendDirectories, buildDirectory, assetsDirectory, databaseEngine, databaseHost, databaseDirectory, orm, authOption, plugins, initializeGitNow, installDependenciesNow }, packageManager }) => {
53
54
  const htmlScriptingValue = useHTMLScripts
54
55
  ? blueBright('TypeScript')
55
56
  : dim('None');
@@ -63,6 +64,7 @@ export const getDebugMessage = ({ response: { projectName, codeQualityTool, dire
63
64
  /* prettier-ignore */
64
65
  const lines = [
65
66
  ['Project Name', projectName],
67
+ ['Agent-first Stack', agentic ? green('Yes') : dim('No')],
66
68
  ['Package Manager', packageManager],
67
69
  ['Config Type', isCustomConfig ? green('Custom') : dim('Default')],
68
70
  ['Linting', codeQualityTool === 'eslint+prettier' ? 'ESLint + Prettier' : 'Biome'],
package/dist/prompt.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { getAuthOption } from './questions/authOption';
2
+ import { getAgentic } from './questions/agentic';
2
3
  import { getCodeQualityTool } from './questions/codeQualityTool';
3
4
  import { getConfigurationType } from './questions/configurationType';
4
5
  import { getDatabaseEngine } from './questions/databaseEngine';
@@ -18,11 +19,14 @@ import { getUseTailwind } from './questions/useTailwind';
18
19
  import { orPrompt } from './utils/interactive';
19
20
  export const prompt = async (argumentConfiguration) => {
20
21
  // 1. Project name
21
- const projectName = argumentConfiguration.projectName ?? (await orPrompt('a project name', getProjectName));
22
+ const projectName = argumentConfiguration.projectName ??
23
+ (await orPrompt('a project name', getProjectName));
22
24
  // 2. Linting/formatting tool
23
- const codeQualityTool = argumentConfiguration.codeQualityTool ?? (await orPrompt('--eslint+prettier/--biome', getCodeQualityTool));
25
+ const codeQualityTool = argumentConfiguration.codeQualityTool ??
26
+ (await orPrompt('--eslint+prettier/--biome', getCodeQualityTool));
24
27
  // 3. Tailwind support?
25
- const useTailwind = argumentConfiguration.useTailwind ?? (await orPrompt('--tailwind/--no-tailwind', getUseTailwind));
28
+ const useTailwind = argumentConfiguration.useTailwind ??
29
+ (await orPrompt('--tailwind/--no-tailwind', getUseTailwind));
26
30
  // 4. Frontend(s)
27
31
  const frontends = argumentConfiguration.frontends?.filter((frontend) => frontend !== undefined) ?? (await orPrompt('--react/--vue/--svelte/…', getFrontends));
28
32
  // 5. HTML scripting option (if HTML was selected)
@@ -31,18 +35,22 @@ export const prompt = async (argumentConfiguration) => {
31
35
  (await orPrompt('--html-scripts/--no-html-scripts', getHtmlScriptingOption)))
32
36
  : false;
33
37
  // 5b. Include example pages/components, or generate a bare skeleton
34
- const includeExamples = argumentConfiguration.includeExamples ?? (await orPrompt('--examples/--no-examples', getIncludeExamples));
38
+ const includeExamples = argumentConfiguration.includeExamples ??
39
+ (await orPrompt('--examples/--no-examples', getIncludeExamples));
35
40
  // 6. Database engine
36
- const databaseEngine = argumentConfiguration.databaseEngine ?? (await orPrompt('--db', getDatabaseEngine));
41
+ const databaseEngine = argumentConfiguration.databaseEngine ??
42
+ (await orPrompt('--db', getDatabaseEngine));
37
43
  // 7. Database host
38
44
  const databaseHost = argumentConfiguration.databaseHost ??
39
45
  (await orPrompt('--db-host', () => getDatabaseHost(databaseEngine)));
40
46
  // 8. ORM choice
41
47
  const orm = databaseEngine !== undefined && databaseEngine !== 'none'
42
- ? (argumentConfiguration.orm ?? (await orPrompt('--orm', () => getORM(databaseEngine))))
48
+ ? (argumentConfiguration.orm ??
49
+ (await orPrompt('--orm', () => getORM(databaseEngine))))
43
50
  : undefined;
44
51
  // 9. Configuration type
45
- let directoryConfig = argumentConfiguration.directoryConfig ?? (await orPrompt('--directory', getConfigurationType));
52
+ let directoryConfig = argumentConfiguration.directoryConfig ??
53
+ (await orPrompt('--directory', getConfigurationType));
46
54
  // 10. Directory configurations
47
55
  const { buildDirectory, assetsDirectory, tailwind, databaseDirectory } = await getDirectoryConfiguration({
48
56
  argumentConfiguration,
@@ -56,11 +64,16 @@ export const prompt = async (argumentConfiguration) => {
56
64
  if (argumentConfiguration.frontendDirectories !== undefined)
57
65
  directoryConfig = 'custom';
58
66
  // 12. Auth provider
59
- const authOption = argumentConfiguration.authOption ?? (await orPrompt('--auth', getAuthOption));
67
+ const authOption = argumentConfiguration.authOption ??
68
+ (await orPrompt('--auth', getAuthOption));
69
+ // 12b. Agent-first action/auth/MCP/wallet/credential stack
70
+ const agentic = argumentConfiguration.agentic ??
71
+ (await orPrompt('--agentic/--no-agentic', getAgentic));
60
72
  // 13. Additional plugins
61
73
  const plugins = argumentConfiguration.plugins?.filter((plugin) => plugin !== undefined) ?? (await orPrompt('--plugin', getPlugins));
62
74
  // 14. Initialize Git repository
63
- const initializeGitNow = argumentConfiguration.initializeGitNow ?? (await orPrompt('--git/--no-git', getInitializeGit));
75
+ const initializeGitNow = argumentConfiguration.initializeGitNow ??
76
+ (await orPrompt('--git/--no-git', getInitializeGit));
64
77
  // 14b. Optionally connect the new project to GitHub
65
78
  const resolveGithubLink = async () => {
66
79
  if (!initializeGitNow) {
@@ -84,6 +97,7 @@ export const prompt = async (argumentConfiguration) => {
84
97
  const installDependenciesNow = argumentConfiguration.installDependenciesNow ??
85
98
  (await orPrompt('--install/--no-install', getInstallDependencies));
86
99
  const values = {
100
+ agentic,
87
101
  absProviders: argumentConfiguration.absProviders?.filter((provider) => provider !== undefined),
88
102
  assetsDirectory,
89
103
  authOption,
@@ -0,0 +1 @@
1
+ export declare const getAgentic: () => Promise<boolean>;
@@ -0,0 +1,11 @@
1
+ import { confirm, isCancel } from '@clack/prompts';
2
+ import { abort } from '../utils/abort';
3
+ export const getAgentic = async () => {
4
+ const agentic = await confirm({
5
+ initialValue: false,
6
+ message: 'Add the agent-first stack (auth, actions, MCP, wallet, credentials, and conformance)?'
7
+ });
8
+ if (isCancel(agentic))
9
+ abort();
10
+ return agentic;
11
+ };
@@ -5,7 +5,7 @@ type ScaffoldProps = {
5
5
  latest: boolean;
6
6
  envVariables: string[] | undefined;
7
7
  };
8
- export declare const scaffold: ({ response: { projectName, codeQualityTool, initializeGitNow, githubLink, githubRepoUrl, githubVisibility, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, absProviders, includeExamples, orm, frontends, plugins, authOption, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, envVariables, packageManager }: ScaffoldProps) => Promise<{
8
+ export declare const scaffold: ({ response: { agentic, projectName, codeQualityTool, initializeGitNow, githubLink, githubRepoUrl, githubVisibility, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, absProviders, includeExamples, orm, frontends, plugins, authOption, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, envVariables, packageManager }: ScaffoldProps) => Promise<{
9
9
  dockerFreshInstall: boolean;
10
10
  }>;
11
11
  export {};
package/dist/scaffold.js CHANGED
@@ -10,7 +10,8 @@ import { scaffoldConfigurationFiles } from './generators/configurations/scaffold
10
10
  import { scaffoldDatabase } from './generators/db/scaffoldDatabase';
11
11
  import { scaffoldBackend } from './generators/project/scaffoldBackend';
12
12
  import { scaffoldFrontends } from './generators/project/scaffoldFrontends';
13
- export const scaffold = async ({ response: { projectName, codeQualityTool, initializeGitNow, githubLink, githubRepoUrl, githubVisibility, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, absProviders, includeExamples, orm, frontends, plugins, authOption, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, envVariables, packageManager }) => {
13
+ import { scaffoldAgentic } from './generators/project/scaffoldAgentic';
14
+ export const scaffold = async ({ response: { agentic, projectName, codeQualityTool, initializeGitNow, githubLink, githubRepoUrl, githubVisibility, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, absProviders, includeExamples, orm, frontends, plugins, authOption, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, envVariables, packageManager }) => {
14
15
  const __dirname = dirname(fileURLToPath(import.meta.url));
15
16
  const templatesDirectory = join(__dirname, '/templates');
16
17
  const { frontendDirectory, backendDirectory, projectAssetsDirectory, typesDirectory } = initalizeRoot(projectName, templatesDirectory);
@@ -27,6 +28,7 @@ export const scaffold = async ({ response: { projectName, codeQualityTool, initi
27
28
  templatesDirectory
28
29
  });
29
30
  await createPackageJson({
31
+ agentic,
30
32
  authOption,
31
33
  codeQualityTool,
32
34
  databaseEngine,
@@ -53,6 +55,8 @@ export const scaffold = async ({ response: { projectName, codeQualityTool, initi
53
55
  publicDirectory: 'public',
54
56
  tailwind
55
57
  });
58
+ if (agentic)
59
+ scaffoldAgentic({ backendDirectory, projectName });
56
60
  let dockerFreshInstall = false;
57
61
  if (databaseDirectory !== undefined &&
58
62
  databaseEngine !== 'none' &&
package/dist/types.d.ts CHANGED
@@ -43,6 +43,7 @@ export type TailwindConfig = {
43
43
  } | undefined;
44
44
  export type GithubLinkOption = 'existing' | 'create' | 'skip';
45
45
  export type CreateConfiguration = {
46
+ agentic: boolean;
46
47
  absProviders: ProviderOption[] | undefined;
47
48
  assetsDirectory: string;
48
49
  authOption: AuthOption;
@@ -12,6 +12,7 @@ export const parseCommandLineOptions = () => {
12
12
  args: argv.slice(DEFAULT_ARG_LENGTH),
13
13
  options: {
14
14
  'abs-provider': { multiple: true, type: 'string' },
15
+ agentic: { type: 'boolean' },
15
16
  angular: { type: 'boolean' },
16
17
  'angular-dir': { type: 'string' },
17
18
  assets: { type: 'string' },
@@ -131,7 +132,9 @@ export const parseCommandLineOptions = () => {
131
132
  ? values.directory
132
133
  : // --skip defaults every prompted axis (headless callers hang on
133
134
  // missing ones).
134
- (values.skip ? 'default' : undefined);
135
+ values.skip
136
+ ? 'default'
137
+ : undefined;
135
138
  if (values.directory !== undefined && directoryConfig === undefined) {
136
139
  errors.push(`Invalid directory configuration: "${values.directory}". Expected: [ ${availableDirectoryConfigurations.join(', ')} ]`);
137
140
  }
@@ -222,7 +225,8 @@ export const parseCommandLineOptions = () => {
222
225
  let tailwind = hasTailwindFiles
223
226
  ? { input: values['tailwind-input'], output: values['tailwind-output'] }
224
227
  : undefined;
225
- const useTailwind = values.tailwind ?? (hasTailwindFiles ? true : undefined);
228
+ const useTailwind = values.tailwind ??
229
+ (hasTailwindFiles ? true : values.skip ? false : undefined);
226
230
  if (useTailwind === false && hasTailwindFiles) {
227
231
  console.warn('Warning: Tailwind CSS input/output files are specified but Tailwind is disabled.');
228
232
  tailwind = undefined;
@@ -250,6 +254,7 @@ export const parseCommandLineOptions = () => {
250
254
  ? repoVisibility
251
255
  : undefined;
252
256
  const argumentConfiguration = {
257
+ agentic: values.agentic ?? (values.skip ? false : undefined),
253
258
  absProviders: absProviders.length ? absProviders : undefined,
254
259
  assetsDirectory: values.assets,
255
260
  authOption,
@@ -260,15 +265,19 @@ export const parseCommandLineOptions = () => {
260
265
  databaseHost,
261
266
  directoryConfig,
262
267
  frontendDirectories,
263
- frontends: selectedFrontends.length ? selectedFrontends : undefined,
268
+ frontends: selectedFrontends.length
269
+ ? selectedFrontends
270
+ : values.skip
271
+ ? []
272
+ : undefined,
264
273
  githubLink: isGithubLinkOption(values.github)
265
274
  ? values.github
266
275
  : undefined,
267
276
  githubRepoUrl: normalizeRepoInput(values.repo)?.httpsUrl,
268
277
  githubVisibility,
269
278
  includeExamples,
270
- initializeGitNow: values.git,
271
- installDependenciesNow: values.install,
279
+ initializeGitNow: values.git ?? (values.skip ? false : undefined),
280
+ installDependenciesNow: values.install ?? (values.skip ? false : undefined),
272
281
  orm,
273
282
  plugins,
274
283
  projectName,
@@ -4,8 +4,26 @@
4
4
  * Run `bun run check-versions` to compare against latest npm versions.
5
5
  */
6
6
  export declare const versions: {
7
- readonly '@absolutejs/absolute': "0.19.0-beta.1081";
8
- readonly '@absolutejs/auth': "0.22.7";
7
+ readonly '@absolutejs/absolute': "0.19.0-beta.1099";
8
+ readonly '@absolutejs/a2a': "0.1.0";
9
+ readonly '@absolutejs/agency': "0.4.0";
10
+ readonly '@absolutejs/agent-conformance': "0.3.0";
11
+ readonly '@absolutejs/agent-discovery': "0.1.0";
12
+ readonly '@absolutejs/agent-inbox': "0.1.0";
13
+ readonly '@absolutejs/agent-memory': "0.1.0";
14
+ readonly '@absolutejs/agent-runtime': "0.1.0";
15
+ readonly '@absolutejs/agent-sandbox': "0.1.0";
16
+ readonly '@absolutejs/agent-trust': "0.1.0";
17
+ readonly '@absolutejs/agent-control': "0.1.0";
18
+ readonly '@absolutejs/auth': "0.54.9";
19
+ readonly '@absolutejs/egress': "0.1.0";
20
+ readonly '@absolutejs/execution': "0.2.0";
21
+ readonly '@absolutejs/manifest': "0.3.0";
22
+ readonly '@absolutejs/mcp': "0.9.0";
23
+ readonly '@absolutejs/policy': "0.2.0";
24
+ readonly '@absolutejs/secrets': "0.7.0";
25
+ readonly '@absolutejs/sync-bus-pg': "0.2.0";
26
+ readonly '@absolutejs/wallet': "0.3.0";
9
27
  readonly '@angular/common': "21.2.0";
10
28
  readonly '@angular/compiler': "21.2.0";
11
29
  readonly '@angular/compiler-cli': "21.2.0";
@@ -18,7 +36,7 @@ export declare const versions: {
18
36
  readonly '@elysiajs/static': "1.4.7";
19
37
  readonly '@elysiajs/swagger': "1.3.1";
20
38
  readonly '@eslint/compat': "2.0.2";
21
- readonly '@eslint/js': "10.0.1";
39
+ readonly '@eslint/js': "9.39.2";
22
40
  readonly '@libsql/client': "0.17.0";
23
41
  readonly '@neondatabase/serverless': "1.0.2";
24
42
  readonly '@planetscale/database': "1.19.0";
@@ -33,7 +51,7 @@ export declare const versions: {
33
51
  readonly elysia: "1.4.28";
34
52
  readonly 'elysia-rate-limit': "4.5.0";
35
53
  readonly 'elysia-scoped-state': "0.1.1";
36
- readonly eslint: "10.0.0";
54
+ readonly eslint: "9.39.2";
37
55
  readonly 'eslint-plugin-absolute': "0.11.13";
38
56
  readonly 'eslint-plugin-import': "2.32.0";
39
57
  readonly 'eslint-plugin-jsx-a11y': "6.10.2";
package/dist/versions.js CHANGED
@@ -5,8 +5,26 @@
5
5
  */
6
6
  export const versions = {
7
7
  /* ── Core ─────────────────────────────────────────────── */
8
- '@absolutejs/absolute': '0.19.0-beta.1081',
9
- '@absolutejs/auth': '0.22.7',
8
+ '@absolutejs/absolute': '0.19.0-beta.1099',
9
+ '@absolutejs/a2a': '0.1.0',
10
+ '@absolutejs/agency': '0.4.0',
11
+ '@absolutejs/agent-conformance': '0.3.0',
12
+ '@absolutejs/agent-discovery': '0.1.0',
13
+ '@absolutejs/agent-inbox': '0.1.0',
14
+ '@absolutejs/agent-memory': '0.1.0',
15
+ '@absolutejs/agent-runtime': '0.1.0',
16
+ '@absolutejs/agent-sandbox': '0.1.0',
17
+ '@absolutejs/agent-trust': '0.1.0',
18
+ '@absolutejs/agent-control': '0.1.0',
19
+ '@absolutejs/auth': '0.54.9',
20
+ '@absolutejs/egress': '0.1.0',
21
+ '@absolutejs/execution': '0.2.0',
22
+ '@absolutejs/manifest': '0.3.0',
23
+ '@absolutejs/mcp': '0.9.0',
24
+ '@absolutejs/policy': '0.2.0',
25
+ '@absolutejs/secrets': '0.7.0',
26
+ '@absolutejs/sync-bus-pg': '0.2.0',
27
+ '@absolutejs/wallet': '0.3.0',
10
28
  /* ── Angular ─────────────────────────────────────────── */
11
29
  '@angular/common': '21.2.0',
12
30
  '@angular/compiler': '21.2.0',
@@ -22,7 +40,7 @@ export const versions = {
22
40
  '@elysiajs/swagger': '1.3.1',
23
41
  /* ── ESLint + Prettier ────────────────────────────────── */
24
42
  '@eslint/compat': '2.0.2',
25
- '@eslint/js': '10.0.1',
43
+ '@eslint/js': '9.39.2',
26
44
  /* ── Database Hosts ───────────────────────────────────── */
27
45
  '@libsql/client': '0.17.0',
28
46
  '@neondatabase/serverless': '1.0.2',
@@ -42,7 +60,7 @@ export const versions = {
42
60
  elysia: '1.4.28',
43
61
  'elysia-rate-limit': '4.5.0',
44
62
  'elysia-scoped-state': '0.1.1',
45
- eslint: '10.0.0',
63
+ eslint: '9.39.2',
46
64
  'eslint-plugin-absolute': '0.11.13',
47
65
  'eslint-plugin-import': '2.32.0',
48
66
  /* ── ESLint React ─────────────────────────────────────── */
package/package.json CHANGED
@@ -54,5 +54,5 @@
54
54
  "typecheck": "bun run tsc --noEmit"
55
55
  },
56
56
  "type": "module",
57
- "version": "0.15.2"
57
+ "version": "0.15.3"
58
58
  }