waypoint-codex 0.1.6 → 0.1.8
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 +8 -3
- package/dist/src/cli.js +20 -1
- package/dist/src/upgrade.js +55 -0
- package/package.json +1 -1
- package/templates/.waypoint/scripts/prepare-context.mjs +194 -66
package/README.md
CHANGED
|
@@ -50,6 +50,7 @@ repo/
|
|
|
50
50
|
- `waypoint init` — scaffold or refresh the repo
|
|
51
51
|
- `waypoint doctor` — check for drift and missing pieces
|
|
52
52
|
- `waypoint sync` — rebuild `.waypoint/DOCS_INDEX.md` and sync optional automations/rules
|
|
53
|
+
- `waypoint upgrade` — update the global Waypoint CLI and refresh the current repo with its existing config
|
|
53
54
|
- `waypoint import-legacy` — import from an older repo layout
|
|
54
55
|
|
|
55
56
|
## Shipped skills
|
|
@@ -71,9 +72,13 @@ If you initialize with `--with-roles`, Waypoint scaffolds:
|
|
|
71
72
|
## Update
|
|
72
73
|
|
|
73
74
|
```bash
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
waypoint upgrade
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
If you only want to update the CLI without refreshing the repo:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
waypoint upgrade --skip-repo-refresh
|
|
77
82
|
```
|
|
78
83
|
|
|
79
84
|
## Learn more
|
package/dist/src/cli.js
CHANGED
|
@@ -4,7 +4,8 @@ import { readFileSync } from "node:fs";
|
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
|
-
import { doctorRepository, importLegacyRepo, initRepository, syncRepository } from "./core.js";
|
|
7
|
+
import { doctorRepository, importLegacyRepo, initRepository, loadWaypointConfig, syncRepository } from "./core.js";
|
|
8
|
+
import { upgradeWaypoint } from "./upgrade.js";
|
|
8
9
|
const VERSION = JSON.parse(readFileSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../package.json"), "utf8")).version;
|
|
9
10
|
function resolveRepo(input) {
|
|
10
11
|
return path.resolve(input ?? ".");
|
|
@@ -29,6 +30,7 @@ Commands:
|
|
|
29
30
|
init Initialize a repository with Waypoint scaffolding
|
|
30
31
|
doctor Validate repository health and report drift
|
|
31
32
|
sync Rebuild docs index and sync optional user-home artifacts
|
|
33
|
+
upgrade Update the global Waypoint CLI and refresh this repo using existing config
|
|
32
34
|
import-legacy Analyze a legacy repository layout and produce a Waypoint adoption report
|
|
33
35
|
`);
|
|
34
36
|
}
|
|
@@ -128,6 +130,23 @@ async function main() {
|
|
|
128
130
|
}
|
|
129
131
|
return 0;
|
|
130
132
|
}
|
|
133
|
+
if (command === "upgrade") {
|
|
134
|
+
const { values, positionals } = parseArgs({
|
|
135
|
+
args: argv.slice(1),
|
|
136
|
+
options: {
|
|
137
|
+
"skip-repo-refresh": { type: "boolean", default: false }
|
|
138
|
+
},
|
|
139
|
+
allowPositionals: true
|
|
140
|
+
});
|
|
141
|
+
const projectRoot = resolveRepo(positionals[0]);
|
|
142
|
+
const config = loadWaypointConfig(projectRoot);
|
|
143
|
+
return upgradeWaypoint({
|
|
144
|
+
projectRoot,
|
|
145
|
+
config,
|
|
146
|
+
cliEntry: process.argv[1] ? path.resolve(process.argv[1]) : fileURLToPath(import.meta.url),
|
|
147
|
+
skipRepoRefresh: values["skip-repo-refresh"],
|
|
148
|
+
});
|
|
149
|
+
}
|
|
131
150
|
console.error(`Unknown command: ${command}`);
|
|
132
151
|
printHelp();
|
|
133
152
|
return 2;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function npmBinaryForPlatform(platform = process.platform) {
|
|
5
|
+
return platform === "win32" ? "npm.cmd" : "npm";
|
|
6
|
+
}
|
|
7
|
+
export function buildInitArgs(projectRoot, config) {
|
|
8
|
+
const args = ["init", projectRoot];
|
|
9
|
+
if (config.profile === "app-friendly") {
|
|
10
|
+
args.push("--app-friendly");
|
|
11
|
+
}
|
|
12
|
+
const featureMap = config.features ?? {};
|
|
13
|
+
if (featureMap.roles) {
|
|
14
|
+
args.push("--with-roles");
|
|
15
|
+
}
|
|
16
|
+
if (featureMap.rules) {
|
|
17
|
+
args.push("--with-rules");
|
|
18
|
+
}
|
|
19
|
+
if (featureMap.automations) {
|
|
20
|
+
args.push("--with-automations");
|
|
21
|
+
}
|
|
22
|
+
return args;
|
|
23
|
+
}
|
|
24
|
+
function hasWaypointConfig(projectRoot) {
|
|
25
|
+
return existsSync(path.join(projectRoot, ".waypoint/config.toml"));
|
|
26
|
+
}
|
|
27
|
+
export function upgradeWaypoint(options) {
|
|
28
|
+
const nodeBinary = options.nodeBinary ?? process.execPath;
|
|
29
|
+
const npmBinary = options.npmBinary ?? process.env.WAYPOINT_NPM_COMMAND ?? npmBinaryForPlatform();
|
|
30
|
+
const stdio = options.stdio ?? "inherit";
|
|
31
|
+
const update = spawnSync(npmBinary, ["install", "-g", "waypoint-codex@latest"], {
|
|
32
|
+
stdio,
|
|
33
|
+
});
|
|
34
|
+
if ((update.status ?? 1) !== 0) {
|
|
35
|
+
return update.status ?? 1;
|
|
36
|
+
}
|
|
37
|
+
if (options.skipRepoRefresh) {
|
|
38
|
+
console.log("Waypoint CLI updated. Skipped repo refresh.");
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
if (!hasWaypointConfig(options.projectRoot)) {
|
|
42
|
+
console.log("Waypoint CLI updated. No repo-local Waypoint config found, so repo refresh was skipped.");
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
const init = spawnSync(nodeBinary, [options.cliEntry, ...buildInitArgs(options.projectRoot, options.config)], {
|
|
46
|
+
stdio,
|
|
47
|
+
});
|
|
48
|
+
if ((init.status ?? 1) !== 0) {
|
|
49
|
+
return init.status ?? 1;
|
|
50
|
+
}
|
|
51
|
+
const doctor = spawnSync(nodeBinary, [options.cliEntry, "doctor", options.projectRoot], {
|
|
52
|
+
stdio,
|
|
53
|
+
});
|
|
54
|
+
return doctor.status ?? 1;
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -23,18 +23,98 @@ function ensureDir(dirPath) {
|
|
|
23
23
|
mkdirSync(dirPath, { recursive: true });
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function
|
|
26
|
+
function runCommand(command, cwd) {
|
|
27
27
|
try {
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
return {
|
|
29
|
+
ok: true,
|
|
30
|
+
stdout: execFileSync(command[0], command.slice(1), {
|
|
31
|
+
cwd,
|
|
32
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
33
|
+
encoding: "utf8",
|
|
34
|
+
}).trim(),
|
|
35
|
+
stderr: "",
|
|
36
|
+
};
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return {
|
|
39
|
+
ok: false,
|
|
40
|
+
stdout: typeof error?.stdout === "string" ? error.stdout.trim() : "",
|
|
41
|
+
stderr:
|
|
42
|
+
typeof error?.stderr === "string" && error.stderr.trim().length > 0
|
|
43
|
+
? error.stderr.trim()
|
|
44
|
+
: error instanceof Error
|
|
45
|
+
? error.message
|
|
46
|
+
: "Unknown command failure",
|
|
47
|
+
};
|
|
35
48
|
}
|
|
36
49
|
}
|
|
37
50
|
|
|
51
|
+
function safeExec(command, cwd) {
|
|
52
|
+
const result = runCommand(command, cwd);
|
|
53
|
+
return result.ok ? result.stdout : "";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function escapeRegex(value) {
|
|
57
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function currentAuthorFilter(projectRoot) {
|
|
61
|
+
const email = runCommand(["git", "config", "user.email"], projectRoot);
|
|
62
|
+
if (email.ok && email.stdout) {
|
|
63
|
+
return {
|
|
64
|
+
label: email.stdout,
|
|
65
|
+
pattern: escapeRegex(email.stdout),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const name = runCommand(["git", "config", "user.name"], projectRoot);
|
|
70
|
+
if (name.ok && name.stdout) {
|
|
71
|
+
return {
|
|
72
|
+
label: name.stdout,
|
|
73
|
+
pattern: `^${escapeRegex(name.stdout)}\\s<`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function githubPullRequestContext(projectRoot) {
|
|
81
|
+
const repo = runCommand(["gh", "repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"], projectRoot);
|
|
82
|
+
if (!repo.ok || !repo.stdout) {
|
|
83
|
+
return {
|
|
84
|
+
ok: false,
|
|
85
|
+
error: repo.stderr || "Could not resolve GitHub repository from this checkout.",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const viewer = runCommand(["gh", "api", "user", "--jq", ".login"], projectRoot);
|
|
90
|
+
if (!viewer.ok || !viewer.stdout) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
error: viewer.stderr || "Could not resolve active GitHub user.",
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
ok: true,
|
|
99
|
+
repo: repo.stdout,
|
|
100
|
+
viewer: viewer.stdout,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function renderCommandBlock(result, emptyMessage) {
|
|
105
|
+
if (!result.ok) {
|
|
106
|
+
return `Command failed: ${result.stderr}`;
|
|
107
|
+
}
|
|
108
|
+
return result.stdout || emptyMessage;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function renderPullRequestBlock(result, emptyMessage) {
|
|
112
|
+
if (!result.ok) {
|
|
113
|
+
return `Command failed: ${result.error || result.stderr}`;
|
|
114
|
+
}
|
|
115
|
+
return result.stdout || emptyMessage;
|
|
116
|
+
}
|
|
117
|
+
|
|
38
118
|
const SESSION_DIR_NAMES = ["sessions", "archived_sessions"];
|
|
39
119
|
const SECRET_PATTERNS = [
|
|
40
120
|
/npm_[A-Za-z0-9]+/g,
|
|
@@ -242,6 +322,25 @@ function writeRecentThread(contextDir, projectRoot) {
|
|
|
242
322
|
return filePath;
|
|
243
323
|
}
|
|
244
324
|
|
|
325
|
+
if (!snapshot.selectedFromPreCompaction) {
|
|
326
|
+
writeFileSync(
|
|
327
|
+
filePath,
|
|
328
|
+
[
|
|
329
|
+
"# Recent Thread",
|
|
330
|
+
"",
|
|
331
|
+
`Generated by \`${path.relative(projectRoot, fileURLToPath(import.meta.url))}\` on ${generatedAt}.`,
|
|
332
|
+
"",
|
|
333
|
+
`- Source session: \`${path.relative(codexHome(), snapshot.path)}\``,
|
|
334
|
+
`- Session cwd: \`${snapshot.sessionCwd}\``,
|
|
335
|
+
`- Compactions in source session: ${snapshot.compactionCount}`,
|
|
336
|
+
"- No compaction was found in the latest matching local Codex session, so there is nothing to restore into startup context yet.",
|
|
337
|
+
"",
|
|
338
|
+
].join("\n"),
|
|
339
|
+
"utf8"
|
|
340
|
+
);
|
|
341
|
+
return filePath;
|
|
342
|
+
}
|
|
343
|
+
|
|
245
344
|
const selectedTurns = snapshot.turns.slice(-MAX_RECENT_TURNS);
|
|
246
345
|
const relSessionPath = path.relative(codexHome(), snapshot.path);
|
|
247
346
|
const lines = [
|
|
@@ -329,34 +428,49 @@ function main() {
|
|
|
329
428
|
contextDir,
|
|
330
429
|
"UNCOMMITTED_CHANGES.md",
|
|
331
430
|
"Uncommitted Changes",
|
|
332
|
-
|
|
333
|
-
"
|
|
334
|
-
"",
|
|
335
|
-
"
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
431
|
+
(() => {
|
|
432
|
+
const status = runCommand(["git", "status", "--short", "--branch"], projectRoot);
|
|
433
|
+
const unstaged = runCommand(["git", "diff", "--stat"], projectRoot);
|
|
434
|
+
const staged = runCommand(["git", "diff", "--stat", "--cached"], projectRoot);
|
|
435
|
+
return [
|
|
436
|
+
"## Status",
|
|
437
|
+
"",
|
|
438
|
+
"```",
|
|
439
|
+
renderCommandBlock(status, "No uncommitted changes."),
|
|
440
|
+
"```",
|
|
441
|
+
"",
|
|
442
|
+
"## Diff Stat",
|
|
443
|
+
"",
|
|
444
|
+
"```",
|
|
445
|
+
renderCommandBlock(unstaged, "No unstaged tracked diff."),
|
|
446
|
+
"```",
|
|
447
|
+
"",
|
|
448
|
+
"## Staged Diff Stat",
|
|
449
|
+
"",
|
|
450
|
+
"```",
|
|
451
|
+
renderCommandBlock(staged, "No staged diff."),
|
|
452
|
+
"```",
|
|
453
|
+
].join("\n");
|
|
454
|
+
})()
|
|
351
455
|
);
|
|
352
456
|
|
|
457
|
+
const authorFilter = currentAuthorFilter(projectRoot);
|
|
458
|
+
const recentCommitsResult = authorFilter
|
|
459
|
+
? runCommand(["git", "log", `--author=${authorFilter.pattern}`, "--format=%h%d %s (%cr)", "-20", "--all"], projectRoot)
|
|
460
|
+
: {
|
|
461
|
+
ok: false,
|
|
462
|
+
stdout: "",
|
|
463
|
+
stderr: "Could not determine current git author from local git config.",
|
|
464
|
+
};
|
|
353
465
|
const recentCommitsPath = writeContextFile(
|
|
354
466
|
contextDir,
|
|
355
467
|
"RECENT_COMMITS.md",
|
|
356
468
|
"Recent Commits",
|
|
357
469
|
[
|
|
470
|
+
authorFilter ? `Author filter: ${authorFilter.label}` : "Author filter: unavailable",
|
|
471
|
+
"",
|
|
358
472
|
"```",
|
|
359
|
-
|
|
473
|
+
renderCommandBlock(recentCommitsResult, "No recent commits found for the current author."),
|
|
360
474
|
"```",
|
|
361
475
|
].join("\n")
|
|
362
476
|
);
|
|
@@ -375,57 +489,71 @@ function main() {
|
|
|
375
489
|
nestedRepoSections.join("\n\n") || "No nested repositories found."
|
|
376
490
|
);
|
|
377
491
|
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
492
|
+
const prContext = githubPullRequestContext(projectRoot);
|
|
493
|
+
const openPrs =
|
|
494
|
+
prContext.ok
|
|
495
|
+
? runCommand(
|
|
496
|
+
[
|
|
497
|
+
"gh",
|
|
498
|
+
"pr",
|
|
499
|
+
"list",
|
|
500
|
+
"--repo",
|
|
501
|
+
prContext.repo,
|
|
502
|
+
"--state",
|
|
503
|
+
"open",
|
|
504
|
+
"--author",
|
|
505
|
+
prContext.viewer,
|
|
506
|
+
"--limit",
|
|
507
|
+
"5",
|
|
508
|
+
"--json",
|
|
509
|
+
"number,title,author,headRefName",
|
|
510
|
+
"--template",
|
|
511
|
+
"{{range .}}#{{.number}} {{.title}} ({{.author.login}}) [{{.headRefName}}]\n{{end}}",
|
|
512
|
+
],
|
|
513
|
+
projectRoot
|
|
514
|
+
)
|
|
515
|
+
: prContext;
|
|
516
|
+
const mergedPrs =
|
|
517
|
+
prContext.ok
|
|
518
|
+
? runCommand(
|
|
519
|
+
[
|
|
520
|
+
"gh",
|
|
521
|
+
"pr",
|
|
522
|
+
"list",
|
|
523
|
+
"--repo",
|
|
524
|
+
prContext.repo,
|
|
525
|
+
"--state",
|
|
526
|
+
"merged",
|
|
527
|
+
"--author",
|
|
528
|
+
prContext.viewer,
|
|
529
|
+
"--limit",
|
|
530
|
+
"5",
|
|
531
|
+
"--json",
|
|
532
|
+
"number,title,author,mergedAt",
|
|
533
|
+
"--template",
|
|
534
|
+
"{{range .}}#{{.number}} {{.title}} ({{.author.login}}) merged {{timeago .mergedAt}}\n{{end}}",
|
|
535
|
+
],
|
|
536
|
+
projectRoot
|
|
537
|
+
)
|
|
538
|
+
: prContext;
|
|
414
539
|
const prsPath = writeContextFile(
|
|
415
540
|
contextDir,
|
|
416
541
|
"PULL_REQUESTS.md",
|
|
417
542
|
"Pull Requests",
|
|
418
543
|
[
|
|
544
|
+
prContext.ok ? `GitHub viewer: ${prContext.viewer}` : `GitHub context: ${prContext.error}`,
|
|
545
|
+
prContext.ok ? `GitHub repo: ${prContext.repo}` : "",
|
|
546
|
+
"",
|
|
419
547
|
"## Open PRs",
|
|
420
548
|
"",
|
|
421
549
|
"```",
|
|
422
|
-
openPrs
|
|
550
|
+
renderPullRequestBlock(openPrs, "No open PRs found for the current GitHub user."),
|
|
423
551
|
"```",
|
|
424
552
|
"",
|
|
425
553
|
"## Recently Merged PRs",
|
|
426
554
|
"",
|
|
427
555
|
"```",
|
|
428
|
-
mergedPrs
|
|
556
|
+
renderPullRequestBlock(mergedPrs, "No recently merged PRs found for the current GitHub user."),
|
|
429
557
|
"```",
|
|
430
558
|
].join("\n")
|
|
431
559
|
);
|