run402 4.80.0 → 4.80.1

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 (59) hide show
  1. package/README.md +22 -4
  2. package/gitvault-surface.json +1 -1
  3. package/lib/command-manifest.mjs +4 -1
  4. package/lib/deploy-v2.mjs +18 -2
  5. package/lib/doctor.mjs +164 -30
  6. package/lib/functions.mjs +153 -42
  7. package/lib/gitvault-scaffold.mjs +19 -7
  8. package/lib/harness-context.mjs +6 -2
  9. package/lib/image.mjs +3 -1
  10. package/lib/init.mjs +5 -3
  11. package/lib/logs.mjs +125 -96
  12. package/lib/repos.mjs +40 -8
  13. package/lib/up.mjs +67 -21
  14. package/package.json +1 -1
  15. package/sdk/dist/actions.d.ts +27 -9
  16. package/sdk/dist/actions.d.ts.map +1 -1
  17. package/sdk/dist/errors.d.ts +1 -1
  18. package/sdk/dist/errors.d.ts.map +1 -1
  19. package/sdk/dist/errors.js.map +1 -1
  20. package/sdk/dist/index.d.ts +1 -1
  21. package/sdk/dist/index.d.ts.map +1 -1
  22. package/sdk/dist/index.js +1 -1
  23. package/sdk/dist/index.js.map +1 -1
  24. package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
  25. package/sdk/dist/namespaces/deploy.js +35 -3
  26. package/sdk/dist/namespaces/deploy.js.map +1 -1
  27. package/sdk/dist/namespaces/deploy.types.d.ts +15 -8
  28. package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
  29. package/sdk/dist/namespaces/deploy.types.js +1 -1
  30. package/sdk/dist/namespaces/deploy.types.js.map +1 -1
  31. package/sdk/dist/namespaces/functions.d.ts +17 -1
  32. package/sdk/dist/namespaces/functions.d.ts.map +1 -1
  33. package/sdk/dist/namespaces/functions.js +131 -2
  34. package/sdk/dist/namespaces/functions.js.map +1 -1
  35. package/sdk/dist/namespaces/functions.types.d.ts +62 -0
  36. package/sdk/dist/namespaces/functions.types.d.ts.map +1 -1
  37. package/sdk/dist/namespaces/gitvault.d.ts +38 -0
  38. package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
  39. package/sdk/dist/namespaces/gitvault.js +122 -14
  40. package/sdk/dist/namespaces/gitvault.js.map +1 -1
  41. package/sdk/dist/node/actions-node.d.ts.map +1 -1
  42. package/sdk/dist/node/actions-node.js +176 -16
  43. package/sdk/dist/node/actions-node.js.map +1 -1
  44. package/sdk/dist/node/client-detect.d.ts +16 -1
  45. package/sdk/dist/node/client-detect.d.ts.map +1 -1
  46. package/sdk/dist/node/client-detect.js +26 -9
  47. package/sdk/dist/node/client-detect.js.map +1 -1
  48. package/sdk/dist/node/deploy-manifest.d.ts +42 -0
  49. package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
  50. package/sdk/dist/node/deploy-manifest.js +175 -1
  51. package/sdk/dist/node/deploy-manifest.js.map +1 -1
  52. package/sdk/dist/node/index.d.ts +2 -2
  53. package/sdk/dist/node/index.d.ts.map +1 -1
  54. package/sdk/dist/node/index.js +1 -1
  55. package/sdk/dist/node/index.js.map +1 -1
  56. package/sdk/dist/scoped.d.ts +2 -1
  57. package/sdk/dist/scoped.d.ts.map +1 -1
  58. package/sdk/dist/scoped.js +3 -0
  59. package/sdk/dist/scoped.js.map +1 -1
package/lib/functions.mjs CHANGED
@@ -5,9 +5,71 @@ import { reportSdkError, fail } from "./sdk-errors.mjs";
5
5
  import { assertKnownFlags, hasHelp, normalizeArgv, parseIntegerFlag, resolveProjectSelector, validateRegularFile, failUnknownSubcommand } from "./argparse.mjs";
6
6
  import { cliCommandAction } from "./next-actions.mjs";
7
7
 
8
- const FUNCTION_LOG_REQUEST_ID_RE = /^(?:req|fnrun|fnatt)_[A-Za-z0-9_-]{4,128}$/;
8
+ export const FUNCTION_LOG_REQUEST_ID_RE = /^(?:req|fnrun|fnatt)_[A-Za-z0-9_-]{4,128}$/;
9
9
  const ISO_DATE_TIME_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
10
- const FUNCTION_LOG_TAIL_MAX = 1000;
10
+ export const FUNCTION_LOG_TAIL_MAX = 1000;
11
+
12
+ // Shared by `run402 functions logs` and the top-level `run402 logs` shortcut
13
+ // (cli/lib/logs.mjs) so the two commands validate identically.
14
+
15
+ /** `--since <iso|epoch_ms>` → ISO string, or a BAD_USAGE exit. */
16
+ export function parseLogSinceFlag(since) {
17
+ if (since === undefined || since === null) return undefined;
18
+ const raw = String(since).trim();
19
+ const ms = /^\d+$/.test(raw)
20
+ ? Number(raw)
21
+ : ISO_DATE_TIME_RE.test(raw)
22
+ ? Date.parse(raw)
23
+ : Number.NaN;
24
+ if (!Number.isSafeInteger(ms) || ms < 0) {
25
+ fail({
26
+ code: "BAD_USAGE",
27
+ message: `Invalid --since value: ${since}`,
28
+ details: { flag: "--since", value: since },
29
+ });
30
+ }
31
+ return new Date(ms).toISOString();
32
+ }
33
+
34
+ /** `--request-id <id>` must be a req_ / fnrun_ / fnatt_ correlation id. */
35
+ export function assertLogRequestIdFlag(requestId) {
36
+ if (requestId !== undefined && !FUNCTION_LOG_REQUEST_ID_RE.test(requestId)) {
37
+ fail({
38
+ code: "BAD_USAGE",
39
+ message: `Invalid --request-id value: ${requestId}`,
40
+ details: { flag: "--request-id", value: requestId, expected: "req_|fnrun_|fnatt_ + 4-128 url-safe chars" },
41
+ });
42
+ }
43
+ }
44
+
45
+ /**
46
+ * `--app` (default) / `--platform` / `--all` → the SDK origin filter. Lambda
47
+ * runtime lines (INIT_START / START / END / REPORT …) are `platform`; the
48
+ * function's own output is `app`. More than one flag is a usage error.
49
+ */
50
+ export function resolveLogOriginFlag(args) {
51
+ const chosen = ["--app", "--platform", "--all"].filter((flag) => args.includes(flag));
52
+ if (chosen.length > 1) {
53
+ fail({
54
+ code: "BAD_USAGE",
55
+ message: `Pass only one of --app, --platform, --all (got: ${chosen.join(", ")})`,
56
+ details: { flags: chosen },
57
+ });
58
+ }
59
+ if (chosen[0] === "--platform") return "platform";
60
+ if (chosen[0] === "--all") return "all";
61
+ return "app";
62
+ }
63
+
64
+ /**
65
+ * The hint attached when the origin filter left an empty result but hid
66
+ * platform lines — so an agent learns the function DID run (INIT/REPORT
67
+ * exist) and simply wrote nothing, instead of reading "no logs".
68
+ */
69
+ export function platformHiddenHint(entries, hidden) {
70
+ if (!hidden || hidden.platform <= 0 || entries.length > 0) return undefined;
71
+ return `${hidden.platform} platform lines hidden (INIT_START/REPORT); pass --platform or --all to see them`;
72
+ }
11
73
 
12
74
  const HELP = `run402 functions — Manage serverless functions
13
75
 
@@ -23,8 +85,10 @@ Subcommands:
23
85
  --raw prints the response body verbatim
24
86
  (string body → text + newline, JSON
25
87
  body → pretty-printed JSON).
26
- logs <name> [--project <id>] [--tail <n>] [--since <ts>] [--request-id <req_...>] [--follow]
27
- Get function logs
88
+ logs [<name>] [--project <id>] [--tail <n>] [--since <ts>] [--request-id <id>] [--app|--platform|--all] [--follow]
89
+ Get function logs (app output by default;
90
+ omit <name> with --request-id to search
91
+ every function)
28
92
  runs <action> ... Create, inspect, cancel, redrive, and
29
93
  wait for durable function runs
30
94
  update <name> [--project <id>] [--schedule <cron>] [--schedule-remove] [--timeout <s>] [--memory <mb>]
@@ -48,6 +112,8 @@ Examples:
48
112
  run402 functions logs stripe-webhook --tail 100
49
113
  run402 functions logs stripe-webhook --since 2026-03-29T14:00:00Z
50
114
  run402 functions logs stripe-webhook --request-id req_abc123
115
+ run402 functions logs --request-id req_abc123 # every function in the project
116
+ run402 functions logs stripe-webhook --all # include INIT_START / REPORT lines
51
117
  run402 functions logs stripe-webhook --follow
52
118
  run402 functions runs create worker --event-type reminder.send --idempotency-key reminder:123 --delay 10m
53
119
  run402 functions runs get fnrun_abc123 --project prj_abc123
@@ -167,27 +233,42 @@ Examples:
167
233
 
168
234
  Usage:
169
235
  run402 functions logs <name> [--project <id>] [options]
236
+ run402 functions logs --request-id <id> [--project <id>] [options]
170
237
 
171
238
  Legacy (still supported):
172
239
  run402 functions logs <project_id> <name> [options]
173
240
 
174
241
  Arguments:
175
- <name> Function name
242
+ <name> Function name. Optional when --request-id is given: the
243
+ search then fans out across every function in the project
244
+ and each entry carries its "function".
176
245
 
177
246
  Options:
178
247
  --project <id> Target project ID (defaults to the active project)
179
- --tail <n> Number of most-recent entries (default 50, max 1000)
248
+ --tail <n> Number of most-recent entries (default 50, max 1000).
249
+ Bounds the read BEFORE the origin filter below.
180
250
  --since <ts> ISO timestamp or epoch ms; only entries after this
181
- --request-id <id> Only entries correlated to this req_, fnrun_, or fnatt_ id
251
+ --request-id <id> Only entries correlated to this req_ (the
252
+ x-run402-request-id response header), fnrun_, or fnatt_ id
253
+ --app Only the function's own output (default). Lambda runtime
254
+ lines (INIT_START, START/END/REPORT RequestId, billed
255
+ duration) are hidden; "hidden.platform" counts them and a
256
+ "hint" appears when hiding them left the result empty.
257
+ --platform Only the Lambda runtime lines
258
+ --all Both (the raw CloudWatch stream)
182
259
  --follow Poll every 3s and stream new entries (Ctrl-C to stop).
183
- Emits NDJSON: one JSON log entry per line, no wrapping
184
- "logs:" envelope (the wrapping object is only used in
185
- the non-follow batch mode).
260
+ Requires <name>. Emits NDJSON: one JSON log entry per
261
+ line, no wrapping "logs:" envelope (the wrapping object
262
+ is only used in the non-follow batch mode).
263
+
264
+ Every entry carries "origin": "app" | "platform".
186
265
 
187
266
  Examples:
188
267
  run402 functions logs prj_abc123 stripe-webhook --tail 100
189
268
  run402 functions logs prj_abc123 stripe-webhook --since 2026-03-29T14:00:00Z
190
269
  run402 functions logs prj_abc123 stripe-webhook --request-id req_abc123
270
+ run402 functions logs --request-id req_abc123 --project prj_abc123
271
+ run402 functions logs prj_abc123 stripe-webhook --all
191
272
  run402 functions logs prj_abc123 stripe-webhook --follow
192
273
  `,
193
274
  runs: `run402 functions runs — Manage durable function runs
@@ -451,8 +532,13 @@ function validateInvokeJsonBody(value, source, projectId, name) {
451
532
  }
452
533
 
453
534
  async function logs(projectId, name, args) {
454
- assertRequiredProjectAndName(projectId, name, "run402 functions logs <project_id> <name> [--tail <n>] [--request-id <req_...>]");
455
- assertKnownFlags(args, ["--tail", "--since", "--request-id", "--follow", "--help", "-h"], ["--tail", "--since", "--request-id"]);
535
+ const usage = "run402 functions logs <name> [--project <id>] [--tail <n>] [--since <ts>] [--request-id <id>] [--app|--platform|--all] [--follow] | run402 functions logs --request-id <id> [--project <id>]";
536
+ assertRequiredProject(projectId, usage);
537
+ assertKnownFlags(
538
+ args,
539
+ ["--tail", "--since", "--request-id", "--follow", "--app", "--platform", "--all", "--help", "-h"],
540
+ ["--tail", "--since", "--request-id"],
541
+ );
456
542
  let tail = 50;
457
543
  let since = undefined;
458
544
  let requestId = undefined;
@@ -463,52 +549,70 @@ async function logs(projectId, name, args) {
463
549
  if (args[i] === "--request-id" && args[i + 1]) requestId = args[++i];
464
550
  if (args[i] === "--follow") follow = true;
465
551
  }
552
+ const origin = resolveLogOriginFlag(args);
553
+
554
+ // Keep CLI-side validation so a bad `--since` / `--request-id` errors with
555
+ // a clear message before any network call.
556
+ let sinceIso = parseLogSinceFlag(since);
557
+ assertLogRequestIdFlag(requestId);
466
558
 
467
- // Parse since: accept ISO string or epoch ms — keep CLI-side validation
468
- // so a bad `--since` errors with a clear message rather than silently
469
- // being dropped by the SDK.
470
- let sinceIso = undefined;
471
- if (since !== undefined) {
472
- const raw = String(since).trim();
473
- const ms = /^\d+$/.test(raw)
474
- ? Number(raw)
475
- : ISO_DATE_TIME_RE.test(raw)
476
- ? Date.parse(raw)
477
- : Number.NaN;
478
- if (!Number.isSafeInteger(ms) || ms < 0) {
559
+ if (!name) {
560
+ if (!requestId) {
479
561
  fail({
480
562
  code: "BAD_USAGE",
481
- message: `Invalid --since value: ${since}`,
482
- details: { flag: "--since", value: since },
563
+ message: "Missing <name>.",
564
+ hint: `${usage} pass --request-id <req_...> to search every function without naming one.`,
483
565
  });
484
566
  }
485
- sinceIso = new Date(ms).toISOString();
486
- }
487
- if (requestId !== undefined && !FUNCTION_LOG_REQUEST_ID_RE.test(requestId)) {
488
- fail({
489
- code: "BAD_USAGE",
490
- message: `Invalid --request-id value: ${requestId}`,
491
- details: { flag: "--request-id", value: requestId, expected: "req_<4-128 url-safe chars>" },
492
- });
567
+ if (follow) {
568
+ fail({
569
+ code: "BAD_USAGE",
570
+ message: "--follow requires <name>; the request-id search across every function is a one-shot read.",
571
+ details: { flag: "--follow" },
572
+ });
573
+ }
574
+ try {
575
+ const result = await getSdk().functions.logsByRequestId(projectId, requestId, { tail, since: sinceIso, origin });
576
+ const hint = platformHiddenHint(result.entries, result.hidden);
577
+ console.log(JSON.stringify({
578
+ logs: result.entries,
579
+ request_id: result.request_id,
580
+ scanned: result.scanned,
581
+ ...(result.errors.length > 0 && { errors: result.errors }),
582
+ origin: result.origin,
583
+ ...(result.hidden && { hidden: result.hidden }),
584
+ ...(hint && { hint }),
585
+ }, null, 2));
586
+ } catch (err) {
587
+ reportSdkError(err);
588
+ }
589
+ return;
493
590
  }
494
591
 
495
592
  const fetchLogs = async () => {
496
593
  try {
497
- const data = await getSdk().functions.logs(projectId, name, {
594
+ return await getSdk().functions.logs(projectId, name, {
498
595
  tail,
499
596
  since: sinceIso,
500
597
  requestId,
598
+ origin,
501
599
  });
502
- return data.logs || [];
503
600
  } catch (err) {
504
601
  reportSdkError(err);
505
- return [];
602
+ return { logs: [], origin };
506
603
  }
507
604
  };
508
605
 
509
606
  if (!follow) {
510
- const entries = await fetchLogs();
511
- console.log(JSON.stringify({ logs: entries }, null, 2));
607
+ const result = await fetchLogs();
608
+ const entries = result.logs || [];
609
+ const hint = platformHiddenHint(entries, result.hidden);
610
+ console.log(JSON.stringify({
611
+ logs: entries,
612
+ origin: result.origin ?? origin,
613
+ ...(result.hidden && { hidden: result.hidden }),
614
+ ...(hint && { hint }),
615
+ }, null, 2));
512
616
  return;
513
617
  }
514
618
 
@@ -552,12 +656,12 @@ async function logs(projectId, name, args) {
552
656
  sinceIso = new Date(highWaterMs).toISOString();
553
657
  };
554
658
 
555
- printFreshEntries(await fetchLogs());
659
+ printFreshEntries((await fetchLogs()).logs || []);
556
660
 
557
661
  while (running) {
558
662
  await new Promise(r => setTimeout(r, 3000));
559
663
  if (!running) break;
560
- printFreshEntries(await fetchLogs());
664
+ printFreshEntries((await fetchLogs()).logs || []);
561
665
  }
562
666
  }
563
667
 
@@ -934,7 +1038,14 @@ export async function run(sub, args) {
934
1038
  switch (sub) {
935
1039
  case "deploy": { const { projectId, rest } = select(); await deploy(projectId, rest[0], rest.slice(1)); break; }
936
1040
  case "invoke": { const { projectId, rest } = select(); await invoke(projectId, rest[0], rest.slice(1)); break; }
937
- case "logs": { const { projectId, rest } = select(); await logs(projectId, rest[0], rest.slice(1)); break; }
1041
+ case "logs": {
1042
+ // <name> is optional when --request-id is given (project-wide search),
1043
+ // so a leading flag means "no name", not "the name is --request-id".
1044
+ const { projectId, rest } = select();
1045
+ const hasName = typeof rest[0] === "string" && !rest[0].startsWith("-");
1046
+ await logs(projectId, hasName ? rest[0] : undefined, hasName ? rest.slice(1) : rest);
1047
+ break;
1048
+ }
938
1049
  case "runs": await runs(args[0], args.slice(1)); break;
939
1050
  case "update": { const { projectId, rest } = select(); await update(projectId, rest[0], rest.slice(1)); break; }
940
1051
  case "rebuild": { const { projectId, rest } = select(); await rebuild(projectId, rest); break; }
@@ -15,9 +15,13 @@
15
15
  * did not ask to turn into a repository is left alone. The remote is always
16
16
  * `run402` and `origin` is never touched or claimed; a directory that lies
17
17
  * inside ANOTHER repository is reported `skipped` with the enclosing
18
- * toplevel named — that repository is never touched (first-deploy-agent-dx). Every
19
- * branch is non-fatal a missing git, an unresolvable org, or an
20
- * unreachable gateway all report and return, never throw.
18
+ * toplevel named — that repository is never touched (first-deploy-agent-dx)
19
+ * and the skip carries the SDK's `create_nested_repo` next_action; with
20
+ * `nested: true` the SDK makes the app root its own nested repository
21
+ * instead (the enclosing repository only gains one local
22
+ * `.git/info/exclude` line). Every branch is non-fatal — a missing git, an
23
+ * unresolvable org, or an unreachable gateway all report and return, never
24
+ * throw.
21
25
  */
22
26
  import { getSdk } from "./sdk.mjs";
23
27
  import { resolveOwningOrgId } from "./org-context.mjs";
@@ -28,9 +32,11 @@ import { resolveOwningOrgId } from "./org-context.mjs";
28
32
  * @param {string} options.projectId The project the remote should point at.
29
33
  * @param {string} [options.orgId] Explicit owning org. Resolved via `resolveOwningOrgId` when omitted.
30
34
  * @param {boolean} [options.createRepoIfMissing] Opt into `git init`-ing `repoDir` when it is not a repository yet.
31
- * @returns {Promise<{status: "scaffolded"|"skipped"|"error", reason?: string, toplevel?: string|null, gitvault: object|null, gitvault_skipped?: string, gitvault_error?: {code: string, message: string}}>}
35
+ * @param {boolean} [options.nested] Scaffold `repoDir` as its OWN repository even when it lies inside another one (`Gitvault.scaffoldRemote`'s `nested`).
36
+ * @param {string} [options.nestedCommand] The caller's own `--nested` spelling for the `create_nested_repo` next_action (default: the SDK's `run402 repos create --nested --project <id>`).
37
+ * @returns {Promise<{status: "scaffolded"|"skipped"|"error", reason?: string, toplevel?: string|null, next_actions?: object[], gitvault: object|null, gitvault_skipped?: string, gitvault_error?: {code: string, message: string}}>}
32
38
  */
33
- export async function scaffoldGitvaultRemote({ repoDir = process.cwd(), projectId, orgId, createRepoIfMissing = false } = {}) {
39
+ export async function scaffoldGitvaultRemote({ repoDir = process.cwd(), projectId, orgId, createRepoIfMissing = false, nested = false, nestedCommand } = {}) {
34
40
  const out = { gitvault: null, status: "skipped" };
35
41
  try {
36
42
  const { hardenedGit } = await import("#sdk/node");
@@ -51,13 +57,19 @@ export async function scaffoldGitvaultRemote({ repoDir = process.cwd(), projectI
51
57
  out.gitvault_skipped = `could not resolve the owning org for ${projectId} — the run402 remote was not added`;
52
58
  return out;
53
59
  }
54
- const remote = await getSdk().gitvault.scaffoldRemote({ repo_dir: repoDir, org_id: resolvedOrgId, project_id: projectId });
60
+ const remote = await getSdk().gitvault.scaffoldRemote({ repo_dir: repoDir, org_id: resolvedOrgId, project_id: projectId, ...(nested ? { nested: true } : {}) });
55
61
  if (remote.status === "skipped") {
56
62
  // The app root lies INSIDE some other repository (first-deploy-agent-dx
57
- // D3): that repository is never touched. Say which one, and why.
63
+ // D3): that repository is never touched. Say which one, why, and the
64
+ // way out — the SDK's `create_nested_repo` next_action, respelled to
65
+ // the caller's own `--nested` verb when it has one (`run402 up
66
+ // --nested`), so the command printed is the one the agent just ran.
58
67
  out.reason = "inside_other_repository";
59
68
  out.toplevel = remote.toplevel ?? null;
60
69
  out.gitvault_skipped = remote.reason;
70
+ out.next_actions = (remote.next_actions ?? []).map((action) =>
71
+ action.type === "create_nested_repo" && nestedCommand ? { ...action, command: nestedCommand } : action,
72
+ );
61
73
  return out;
62
74
  }
63
75
  // `allocated: false` is stated, not left to be inferred: this is local
@@ -95,7 +95,9 @@ export function resolveSessionKey({
95
95
  * env overrides first (`RUN402_PROGRAM`/`RUN402_MODEL`), then `program`
96
96
  * inferred from the SAME harness signals {@link resolveSessionKey} already
97
97
  * trusts (`CLAUDE_CODE_SESSION_ID` or `CLAUDECODE` -> `"claude-code"`;
98
- * `CODEX_THREAD_ID` -> `"codex"`; `GROK_SESSION_ID` or `GROK_AGENT` -> `"grok"`). `model` has no harness-exposed signal to
98
+ * `CODEX_THREAD_ID` -> `"codex"`; `CURSOR_TRACE_ID`/`CURSOR_SESSION_ID`/
99
+ * `CURSOR_AGENT` -> `"cursor"`; `GROK_CLI`/`GROK_SESSION_ID`/`GROK_AGENT`/
100
+ * `XAI_GROK`/`GROK_CODE` -> `"grok"`). `model` has no harness-exposed signal to
99
101
  * infer from today (open question in kygit-invite design.md) — it is
100
102
  * ALWAYS env-override-or-null, never guessed from `program`. Null stays
101
103
  * null in both fields: a placeholder label would be a Faithful breach.
@@ -109,7 +111,9 @@ export function resolveHarnessLabels({ env = process.env } = {}) {
109
111
  program = "claude-code";
110
112
  } else if (env.CODEX_THREAD_ID?.trim()) {
111
113
  program = "codex";
112
- } else if (env.GROK_SESSION_ID?.trim() || env.GROK_AGENT?.trim()) {
114
+ } else if (env.CURSOR_TRACE_ID?.trim() || env.CURSOR_SESSION_ID?.trim() || env.CURSOR_AGENT?.trim()) {
115
+ program = "cursor";
116
+ } else if (env.GROK_CLI?.trim() || env.GROK_SESSION_ID?.trim() || env.GROK_AGENT?.trim() || env.XAI_GROK?.trim() || env.GROK_CODE?.trim()) {
113
117
  program = "grok";
114
118
  }
115
119
  }
package/lib/image.mjs CHANGED
@@ -26,7 +26,9 @@ Output (without --output):
26
26
 
27
27
  Notes:
28
28
  - Requires a funded allowance (run402 allowance create && run402 allowance fund)
29
- - Payments are processed automatically via x402 micropayments (Base Sepolia USDC)
29
+ - Payments are processed automatically via x402 micropayments (USDC on the
30
+ network your allowance targets — Base Sepolia on the prototype tier, Base
31
+ mainnet on paid tiers) or over Lightning from a rail: lightning wallet
30
32
  - Use --output to save directly to a file instead of printing base64
31
33
  `;
32
34
 
package/lib/init.mjs CHANGED
@@ -44,9 +44,11 @@ Options:
44
44
  idempotent and does not need this flag.
45
45
  --name <name> Set this principal's display name (1-64 chars) — what promotion
46
46
  credit, \`run402 up\`'s room presence, and audit surfaces show
47
- for you. \`run402 up\` sets a detected default (claude-code,
48
- codex, cursor, or agent) when it is empty; change it any time
49
- with \`run402 org whoami --set-name <name>\`.
47
+ for you. When it is empty, \`run402 up\` sets the detected
48
+ client (claude-code, codex, cursor, or grok; RUN402_CLIENT=<name>
49
+ declares one that is not auto-detected) and otherwise writes
50
+ nothing; RUN402_AGENT_NAME=<name> sets or overrides it. Change
51
+ it any time with \`run402 org whoami --set-name <name>\`.
50
52
  --git-remote Also 'git init' the current directory when it is not a
51
53
  repository yet, so the gitvault remote can be added there.
52
54
  Opt-in on purpose: init is often run outside a project