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.
- package/README.md +22 -4
- package/gitvault-surface.json +1 -1
- package/lib/command-manifest.mjs +4 -1
- package/lib/deploy-v2.mjs +18 -2
- package/lib/doctor.mjs +164 -30
- package/lib/functions.mjs +153 -42
- package/lib/gitvault-scaffold.mjs +19 -7
- package/lib/harness-context.mjs +6 -2
- package/lib/image.mjs +3 -1
- package/lib/init.mjs +5 -3
- package/lib/logs.mjs +125 -96
- package/lib/repos.mjs +40 -8
- package/lib/up.mjs +67 -21
- package/package.json +1 -1
- package/sdk/dist/actions.d.ts +27 -9
- package/sdk/dist/actions.d.ts.map +1 -1
- package/sdk/dist/errors.d.ts +1 -1
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +1 -1
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js +1 -1
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +35 -3
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +15 -8
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js +1 -1
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/namespaces/functions.d.ts +17 -1
- package/sdk/dist/namespaces/functions.d.ts.map +1 -1
- package/sdk/dist/namespaces/functions.js +131 -2
- package/sdk/dist/namespaces/functions.js.map +1 -1
- package/sdk/dist/namespaces/functions.types.d.ts +62 -0
- package/sdk/dist/namespaces/functions.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.d.ts +38 -0
- package/sdk/dist/namespaces/gitvault.d.ts.map +1 -1
- package/sdk/dist/namespaces/gitvault.js +122 -14
- package/sdk/dist/namespaces/gitvault.js.map +1 -1
- package/sdk/dist/node/actions-node.d.ts.map +1 -1
- package/sdk/dist/node/actions-node.js +176 -16
- package/sdk/dist/node/actions-node.js.map +1 -1
- package/sdk/dist/node/client-detect.d.ts +16 -1
- package/sdk/dist/node/client-detect.d.ts.map +1 -1
- package/sdk/dist/node/client-detect.js +26 -9
- package/sdk/dist/node/client-detect.js.map +1 -1
- package/sdk/dist/node/deploy-manifest.d.ts +42 -0
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +175 -1
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/node/index.d.ts +2 -2
- package/sdk/dist/node/index.d.ts.map +1 -1
- package/sdk/dist/node/index.js +1 -1
- package/sdk/dist/node/index.js.map +1 -1
- package/sdk/dist/scoped.d.ts +2 -1
- package/sdk/dist/scoped.d.ts.map +1 -1
- package/sdk/dist/scoped.js +3 -0
- 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 <
|
|
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_
|
|
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
|
|
184
|
-
"logs:" envelope (the wrapping object
|
|
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
|
-
|
|
455
|
-
|
|
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
|
-
|
|
468
|
-
|
|
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:
|
|
482
|
-
|
|
563
|
+
message: "Missing <name>.",
|
|
564
|
+
hint: `${usage} — pass --request-id <req_...> to search every function without naming one.`,
|
|
483
565
|
});
|
|
484
566
|
}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
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
|
-
|
|
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
|
|
511
|
-
|
|
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": {
|
|
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)
|
|
19
|
-
*
|
|
20
|
-
*
|
|
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
|
-
* @
|
|
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
|
|
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
|
package/lib/harness-context.mjs
CHANGED
|
@@ -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"`; `
|
|
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.
|
|
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 (
|
|
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
|
|
48
|
-
codex, cursor, or
|
|
49
|
-
|
|
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
|