@twin3-ai/agent-id 0.3.21 → 0.3.23

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.
@@ -15,8 +15,8 @@ Usage:
15
15
  agent-id-b1-sync --orders ./crm-orders.json --source-id crm-main --url https://example.com
16
16
 
17
17
  Shared environment:
18
- SITE_AGENT_KEY Agent ID Site Agent Key
19
- AGENT_ID_ENDPOINT Parent Agent ID origin
18
+ SITE_AGENT_KEY xAgent ID Site Agent Key
19
+ AGENT_ID_ENDPOINT Parent xAgent ID origin
20
20
  AGENT_ID_B1_STATE Local cursor and retry state path
21
21
 
22
22
  GA4 environment:
@@ -17,12 +17,12 @@ Usage:
17
17
  agent-id-cloudflare-a1 --url https://example.com --status
18
18
 
19
19
  Required environment:
20
- SITE_AGENT_KEY Agent ID Site Agent Key
20
+ SITE_AGENT_KEY xAgent ID Site Agent Key
21
21
  CLOUDFLARE_API_TOKEN Read-only Cloudflare Analytics token
22
22
  CLOUDFLARE_ZONE_ID Website zone ID
23
23
 
24
24
  Optional environment:
25
- AGENT_ID_ENDPOINT Parent Agent ID origin
25
+ AGENT_ID_ENDPOINT Parent xAgent ID origin
26
26
  AGENT_ID_A1_STATE Local cursor and retry state path
27
27
  AGENT_ID_A1_INTERVAL_MS Minimum interval between successful syncs
28
28
  `);
package/bin/agent-id.js CHANGED
@@ -57,6 +57,22 @@ function readJsonFlag(argv, flag) {
57
57
  return idx >= 0 ? JSON.parse(fs.readFileSync(argv[idx + 1], "utf8")) : undefined;
58
58
  }
59
59
 
60
+ function detectPublicRootCandidates(projectRoot) {
61
+ // Conventional publish directories across the common static hosts and
62
+ // frameworks. Only ones that actually exist are offered, and we offer rather
63
+ // than choose: picking a directory to write into is the owner's decision.
64
+ const conventional = ["public", "dist", "build", "out", "_site", "www", "static", "docs"];
65
+ const found = [];
66
+ for (const name of conventional) {
67
+ try {
68
+ if (fs.statSync(path.join(projectRoot, name)).isDirectory()) found.push(`./${name}`);
69
+ } catch (_error) {
70
+ // Absent is the normal case; nothing to report.
71
+ }
72
+ }
73
+ return found;
74
+ }
75
+
60
76
  function readFlagValue(argv, flag) {
61
77
  const idx = argv.indexOf(flag);
62
78
  return idx >= 0 ? argv[idx + 1] : undefined;
@@ -152,7 +168,7 @@ function printReleaseResult(value) {
152
168
  const manifest = value.manifest || {};
153
169
  const packageInfo = manifest.package || {};
154
170
  const lines = [
155
- `Agent ID release: ${value.ok ? "READY" : "BLOCKED"}`,
171
+ `xAgent ID release: ${value.ok ? "READY" : "BLOCKED"}`,
156
172
  `API: ${manifest.api_origin || endpoint}`,
157
173
  `Package: ${packageInfo.name || "@twin3-ai/agent-id"}@${packageInfo.version || "unknown"}`,
158
174
  `Signature: ${value.signature_verified ? "verified" : "not verified"}`,
@@ -370,7 +386,7 @@ function printSignedInstallResult(value) {
370
386
  const enrollment = value.enrollment || {};
371
387
  const executableCommand = (enrollment.next_commands || [])[0];
372
388
  const lines = value.dry_run ? [
373
- "Agent ID signed installation plan",
389
+ "xAgent ID signed installation plan",
374
390
  `Site: ${plan.site_url || "unknown"}`,
375
391
  `Framework: ${plan.framework || "unknown"}`,
376
392
  "Identity: Ed25519, domain-bound",
@@ -378,7 +394,7 @@ function printSignedInstallResult(value) {
378
394
  "Copy and run:",
379
395
  value.next_command,
380
396
  ] : [
381
- "Agent ID signed installation started",
397
+ "xAgent ID signed installation started",
382
398
  `Site: ${plan.site_url || "unknown"}`,
383
399
  "Signed identity: created",
384
400
  `Domain proof: ${enrollment.proof_receipt?.relative_path || "pending"}`,
@@ -388,7 +404,7 @@ function printSignedInstallResult(value) {
388
404
  lines.push(`Deploy ${enrollment.proof_receipt?.relative_path || "the domain proof"}, then run:`);
389
405
  lines.push(executableCommand);
390
406
  } else {
391
- lines.push("Next action: publish the domain proof, then verify the domain with Agent ID.");
407
+ lines.push("Next action: publish the domain proof, then verify the domain with xAgent ID.");
392
408
  }
393
409
  }
394
410
  lines.push("Use --json for the complete machine-readable result.");
@@ -1349,7 +1365,7 @@ async function runCli(argv) {
1349
1365
  const [cmd, url] = argv;
1350
1366
  if (!cmd || cmd === "help" || cmd === "--help") {
1351
1367
  print([
1352
- "Agent ID",
1368
+ "xAgent ID",
1353
1369
  "",
1354
1370
  "Commands:",
1355
1371
  "",
@@ -2809,15 +2825,37 @@ async function runCli(argv) {
2809
2825
  const projectRoot = readFlagValue(argv, "--project-root") || process.cwd();
2810
2826
  const modules = readCsvFlag(argv, "--modules");
2811
2827
  const grantedPermissions = readCsvFlag(argv, "--grant");
2828
+ // Existence is checked before the plan is built. buildInstallPlan reports a
2829
+ // missing directory as PROJECT_ROOT_NOT_SITE -- "not a recognizable website
2830
+ // project" -- which sends someone looking for the wrong problem when the
2831
+ // path simply is not there.
2832
+ let realProjectRoot;
2833
+ try {
2834
+ realProjectRoot = fs.realpathSync(path.resolve(projectRoot));
2835
+ } catch (_error) {
2836
+ throw new Error(
2837
+ `INVALID_PROJECT_ROOT: ${path.resolve(projectRoot)} does not exist. ` +
2838
+ "Run this from your website's project directory, or pass --project-root <path>."
2839
+ );
2840
+ }
2812
2841
  const detectedPlan = await buildInstallPlan({ url, projectRoot, endpoint, modules, grantedPermissions });
2813
2842
  const publicRoot = path.resolve(readFlagValue(argv, "--public-root") || projectRoot);
2814
- let realProjectRoot;
2815
2843
  let realPublicRoot;
2816
2844
  try {
2817
- realProjectRoot = fs.realpathSync(path.resolve(projectRoot));
2818
2845
  realPublicRoot = fs.realpathSync(publicRoot);
2819
2846
  } catch (_error) {
2820
- throw new Error("INVALID_PUBLIC_ROOT: Project root and public root must already exist.");
2847
+ // The first command a new user pastes fails here whenever their publish
2848
+ // directory is not named "public". Naming the candidates we can see beats
2849
+ // making them guess, and beats guessing on their behalf.
2850
+ const candidates = detectPublicRootCandidates(realProjectRoot);
2851
+ const hint = candidates.length
2852
+ ? `Directories here that look like a publish root: ${candidates.join(", ")}.`
2853
+ : "No conventional publish directory was found here. If the site publishes " +
2854
+ "from the project root itself, pass --public-root .";
2855
+ throw new Error(
2856
+ `INVALID_PUBLIC_ROOT: ${publicRoot} does not exist. ${hint} ` +
2857
+ "Pass --public-root <path> pointing at the directory your site publishes."
2858
+ );
2821
2859
  }
2822
2860
  const relativePublicRoot = path.relative(realProjectRoot, realPublicRoot);
2823
2861
  if (relativePublicRoot.startsWith("..") || path.isAbsolute(relativePublicRoot)) {
package/domain-proof.js CHANGED
@@ -215,7 +215,7 @@ function buildSiteAgentVerificationDocument(registration) {
215
215
  const host = exactHostname(registration.host);
216
216
  const verificationToken = requiredString(registration.verification.token, "verification.token");
217
217
  if (!verificationToken.startsWith("av_")) {
218
- throw proofError("invalid_site_registration", "verification.token must be an Agent ID verification token");
218
+ throw proofError("invalid_site_registration", "verification.token must be an xAgent ID verification token");
219
219
  }
220
220
  return {
221
221
  schema: SITE_VERIFICATION_SCHEMA,
package/installer.js CHANGED
@@ -32,7 +32,7 @@ function normalizeInstallSelection(modules, grantedPermissions) {
32
32
  const selected = [...new Set((Array.isArray(modules) && modules.length ? modules : DEFAULT_INSTALL_MODULES).map(String))];
33
33
  const unknown = selected.filter((name) => !INSTALL_MODULES[name]);
34
34
  if (unknown.length) throw installError("INVALID_INSTALL_MODULE", `Unknown install modules: ${unknown.join(", ")}`);
35
- if (!selected.includes("identity")) throw installError("INSTALL_IDENTITY_REQUIRED", "The identity module is required for every Agent ID installation.");
35
+ if (!selected.includes("identity")) throw installError("INSTALL_IDENTITY_REQUIRED", "The identity module is required for every xAgent ID installation.");
36
36
  const granted = [...new Set((Array.isArray(grantedPermissions) ? grantedPermissions : selected.map((name) => INSTALL_MODULES[name].permission)).map(String))];
37
37
  const missing = selected.filter((name) => !granted.includes(INSTALL_MODULES[name].permission));
38
38
  if (missing.length) throw installError("INSTALL_PERMISSION_REQUIRED", `Missing permissions for modules: ${missing.join(", ")}`);
@@ -226,7 +226,7 @@ async function call(action, payload = {}) {
226
226
  let body;
227
227
  try { body = JSON.parse(text || "{}"); } catch (_error) { body = { text }; }
228
228
  if (!response.ok || body.ok === false) {
229
- const error = new Error("Agent ID sync failed: " + response.status);
229
+ const error = new Error("xAgent ID sync failed: " + response.status);
230
230
  error.status = response.status;
231
231
  error.body = redact(body);
232
232
  throw error;
@@ -235,7 +235,7 @@ async function call(action, payload = {}) {
235
235
  }
236
236
 
237
237
  async function main() {
238
- if (!AGENT_ID_ENDPOINT) throw new Error("AGENT_ID_ENDPOINT is required. Use the stable Agent ID API domain supplied by the service owner.");
238
+ if (!AGENT_ID_ENDPOINT) throw new Error("AGENT_ID_ENDPOINT is required. Use the stable xAgent ID API domain supplied by the service owner.");
239
239
  if (!SITE_AGENT_KEY) throw new Error("SITE_AGENT_KEY is required in the customer-owned runner environment.");
240
240
  if (!["heartbeat", "monthly", "full"].includes(SYNC_MODE)) throw new Error("AGENT_ID_SYNC_MODE must be heartbeat, monthly, or full.");
241
241
  const observedAt = new Date().toISOString();
@@ -279,7 +279,7 @@ main().catch((error) => {
279
279
 
280
280
  function staticWorkflowTemplate(siteUrl) {
281
281
  return [
282
- "name: Agent ID website sync",
282
+ "name: xAgent ID website sync",
283
283
  "",
284
284
  "on:",
285
285
  " workflow_dispatch:",
@@ -299,7 +299,7 @@ function staticWorkflowTemplate(siteUrl) {
299
299
  " - uses: actions/setup-node@v4",
300
300
  " with:",
301
301
  " node-version: '20'",
302
- " - name: Pull verified insights from Agent ID",
302
+ " - name: Pull verified insights from xAgent ID",
303
303
  " run: node .agent-id/runner.cjs",
304
304
  " env:",
305
305
  ` SITE_URL: ${siteUrl}`,
@@ -320,7 +320,7 @@ function staticWorkflowTemplate(siteUrl) {
320
320
 
321
321
  function readmeTemplate(siteUrl, framework, packageManager, endpoint) {
322
322
  if (framework === "static") {
323
- return `# Agent ID Site Agent installation
323
+ return `# xAgent ID Site Agent installation
324
324
 
325
325
  - Site URL: ${siteUrl}
326
326
  - Parent service: ${endpoint}
@@ -328,17 +328,17 @@ function readmeTemplate(siteUrl, framework, packageManager, endpoint) {
328
328
 
329
329
  ## Required owner actions
330
330
 
331
- 1. Publish the domain verification document returned by Agent ID.
331
+ 1. Publish the domain verification document returned by xAgent ID.
332
332
  2. Verify domain ownership and obtain the Site Agent Key.
333
333
  3. Save the stable API origin as the repository variable \`AGENT_ID_ENDPOINT\`; do not use a Cloud Run revision URL.
334
334
  4. Save the key as the repository secret \`SITE_AGENT_KEY\`.
335
- 5. Run the \`Agent ID website sync\` workflow once. Keep the daily heartbeat and monthly insights schedules enabled.
335
+ 5. Run the \`xAgent ID website sync\` workflow once. Keep the daily heartbeat and monthly insights schedules enabled.
336
336
  6. Review the uploaded \`agent-id-sync-report\` artifact before approving website changes.
337
337
 
338
- The Runner sends a daily connection heartbeat. It pulls evidence-bound optimization insights on the first day of each month; a manual run performs both. It does not expose the key, commit code, deploy the site, or give Agent ID direct write access to this repository.
338
+ The Runner sends a daily connection heartbeat. It pulls evidence-bound optimization insights on the first day of each month; a manual run performs both. It does not expose the key, commit code, deploy the site, or give xAgent ID direct write access to this repository.
339
339
  `;
340
340
  }
341
- return `# Agent ID Site Agent installation
341
+ return `# xAgent ID Site Agent installation
342
342
 
343
343
  - Site URL: ${siteUrl}
344
344
  - Detected framework: ${framework}
@@ -346,13 +346,13 @@ The Runner sends a daily connection heartbeat. It pulls evidence-bound optimizat
346
346
 
347
347
  ## Next steps
348
348
 
349
- 1. Publish the domain verification file or DNS record returned by Agent ID.
349
+ 1. Publish the domain verification file or DNS record returned by xAgent ID.
350
350
  2. Run domain verification from the website owner environment.
351
351
  3. Install \`@twin3-ai/agent-id\` in the website server, Worker, CMS connector, or Agent runtime.
352
352
  4. Store the issued Site Agent Key as \`SITE_AGENT_KEY\` in the server secret store.
353
353
  5. Start \`agent-id-sync --url ${siteUrl} --once\` for a first evidence exchange.
354
354
 
355
- This directory contains only the local install state and a server-side helper template. It never contains a Site Agent Key, browser token, customer content, or deployment credentials. The Agent ID service does not receive direct write access to this website by installing this package.
355
+ This directory contains only the local install state and a server-side helper template. It never contains a Site Agent Key, browser token, customer content, or deployment credentials. The xAgent ID service does not receive direct write access to this website by installing this package.
356
356
  `;
357
357
  }
358
358
 
@@ -578,7 +578,7 @@ function validatePlan(plan) {
578
578
  for (const file of plan.files) {
579
579
  const allowedWorkflow = plan.framework === "static" && file && file.path === ".github/workflows/agent-id-sync.yml";
580
580
  if (!file || typeof file.path !== "string" || path.isAbsolute(file.path) || file.path.split(/[\\/]+/).includes("..") || (!file.path.startsWith(`${MANAGED_DIR}/`) && !allowedWorkflow)) {
581
- throw installError("UNSAFE_INSTALL_PATH", "Installation can only write managed Agent ID files and its dedicated GitHub Actions workflow.");
581
+ throw installError("UNSAFE_INSTALL_PATH", "Installation can only write managed xAgent ID files and its dedicated GitHub Actions workflow.");
582
582
  }
583
583
  }
584
584
  return root;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@twin3-ai/agent-id",
3
- "version": "0.3.21",
3
+ "version": "0.3.23",
4
4
  "description": "Domain-bound AgentX portable alias, AEO evidence, and website-Agent integration SDK.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/cis2042/agent-id.git"
9
+ "url": "git+https://github.com/twin3-ai/agent-id.git"
10
10
  },
11
11
  "files": [
12
12
  "bin",
@@ -52,5 +52,9 @@
52
52
  "agent-id-sync": "bin/agent-id-sync.js",
53
53
  "agent-id-cloudflare-a1": "bin/agent-id-cloudflare-a1.js",
54
54
  "agent-id-b1-sync": "bin/agent-id-b1-sync.js"
55
+ },
56
+ "homepage": "https://xagent.id",
57
+ "bugs": {
58
+ "url": "https://github.com/twin3-ai/agent-id/issues"
55
59
  }
56
60
  }
@@ -201,7 +201,7 @@ async function buildVerifiedArtifactPatch({ repositoryRoot = process.cwd(), arti
201
201
  changes: artifactBundle.artifacts.map((artifact) => ({
202
202
  path: artifact.path,
203
203
  content: artifact.content,
204
- reason: `Signed Agent ID artifact bundle ${verification.bundle_hash}`
204
+ reason: `Signed xAgent ID artifact bundle ${verification.bundle_hash}`
205
205
  }))
206
206
  });
207
207
  return {
package/site-agent.js CHANGED
@@ -322,7 +322,7 @@ function createSiteAgentClient(options = {}) {
322
322
  if (!res.ok || data.ok === false) {
323
323
  const error = siteAgentError(
324
324
  data.code || "AGENT_ID_PUBLIC_CALL_FAILED",
325
- data.error || data.message || `Agent ID public call failed with HTTP ${res.status}`
325
+ data.error || data.message || `xAgent ID public call failed with HTTP ${res.status}`
326
326
  );
327
327
  error.status = res.status;
328
328
  const retryAfter = res.headers && typeof res.headers.get === "function" ? res.headers.get("retry-after") : "";