codebase-cli 2.0.0-pre.3 → 2.0.0-pre.30

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 (77) hide show
  1. package/dist/agent/agent.js +10 -2
  2. package/dist/agent/agent.js.map +1 -1
  3. package/dist/agent/config.js +101 -20
  4. package/dist/agent/config.js.map +1 -1
  5. package/dist/agent/prompt-suggestion.js +145 -0
  6. package/dist/agent/prompt-suggestion.js.map +1 -0
  7. package/dist/agent/system-prompt.js +15 -0
  8. package/dist/agent/system-prompt.js.map +1 -1
  9. package/dist/app-server/protocol.js +7 -0
  10. package/dist/app-server/protocol.js.map +1 -0
  11. package/dist/app-server/server.js +241 -0
  12. package/dist/app-server/server.js.map +1 -0
  13. package/dist/auth/credentials.js +10 -0
  14. package/dist/auth/credentials.js.map +1 -1
  15. package/dist/auth/flow.js +145 -24
  16. package/dist/auth/flow.js.map +1 -1
  17. package/dist/cli.js +58 -6
  18. package/dist/cli.js.map +1 -1
  19. package/dist/commands/builtins.js +155 -5
  20. package/dist/commands/builtins.js.map +1 -1
  21. package/dist/commands/registry.js +46 -1
  22. package/dist/commands/registry.js.map +1 -1
  23. package/dist/glue/client.js +10 -1
  24. package/dist/glue/client.js.map +1 -1
  25. package/dist/headless/run.js +1 -1
  26. package/dist/headless/run.js.map +1 -1
  27. package/dist/hooks/manager.js +8 -2
  28. package/dist/hooks/manager.js.map +1 -1
  29. package/dist/permissions/store.js +4 -0
  30. package/dist/permissions/store.js.map +1 -1
  31. package/dist/projects/cli.js +92 -0
  32. package/dist/projects/cli.js.map +1 -0
  33. package/dist/projects/client.js +120 -0
  34. package/dist/projects/client.js.map +1 -0
  35. package/dist/projects/types.js +2 -0
  36. package/dist/projects/types.js.map +1 -0
  37. package/dist/skills/platform-loader.js +133 -38
  38. package/dist/skills/platform-loader.js.map +1 -1
  39. package/dist/tools/__test__/mock-tool-context.js +31 -0
  40. package/dist/tools/__test__/mock-tool-context.js.map +1 -0
  41. package/dist/tools/read-file.js +8 -2
  42. package/dist/tools/read-file.js.map +1 -1
  43. package/dist/ui/App.js +244 -17
  44. package/dist/ui/App.js.map +1 -1
  45. package/dist/ui/FirstRunSetup.js +66 -14
  46. package/dist/ui/FirstRunSetup.js.map +1 -1
  47. package/dist/ui/Input.js +270 -14
  48. package/dist/ui/Input.js.map +1 -1
  49. package/dist/ui/Markdown.js +286 -0
  50. package/dist/ui/Markdown.js.map +1 -0
  51. package/dist/ui/Message.js +604 -25
  52. package/dist/ui/Message.js.map +1 -1
  53. package/dist/ui/MessageList.js +100 -3
  54. package/dist/ui/MessageList.js.map +1 -1
  55. package/dist/ui/Permission.js +43 -20
  56. package/dist/ui/Permission.js.map +1 -1
  57. package/dist/ui/PixelC.js +25 -0
  58. package/dist/ui/PixelC.js.map +1 -0
  59. package/dist/ui/Status.js +213 -7
  60. package/dist/ui/Status.js.map +1 -1
  61. package/dist/ui/Throbber.js +11 -7
  62. package/dist/ui/Throbber.js.map +1 -1
  63. package/dist/ui/Welcome.js +59 -0
  64. package/dist/ui/Welcome.js.map +1 -0
  65. package/dist/ui/attachments.js +68 -0
  66. package/dist/ui/attachments.js.map +1 -0
  67. package/dist/ui/debug-input.js +44 -0
  68. package/dist/ui/debug-input.js.map +1 -0
  69. package/dist/ui/highlight.js +324 -0
  70. package/dist/ui/highlight.js.map +1 -0
  71. package/dist/ui/history-store.js +60 -0
  72. package/dist/ui/history-store.js.map +1 -0
  73. package/dist/ui/path-complete.js +102 -0
  74. package/dist/ui/path-complete.js.map +1 -0
  75. package/dist/ui/terminal-restore.js +83 -0
  76. package/dist/ui/terminal-restore.js.map +1 -0
  77. package/package.json +5 -1
@@ -0,0 +1,92 @@
1
+ import { defaultDownloadPath, NotAuthenticatedError, ProjectClient, ProjectClientError } from "./client.js";
2
+ /**
3
+ * Dispatch a `codebase project …` subcommand. Returns the exit code
4
+ * to surface from the parent process.
5
+ *
6
+ * Recognized argv (relative to the entry point — argv[0] is the
7
+ * "project" word that the dispatcher already matched):
8
+ * project → list (default)
9
+ * project list → list
10
+ * project pull <id> → pull project to ~/.codebase/pulls/<id>.zip
11
+ * project pull <id> <dest> → pull to <dest>
12
+ */
13
+ export async function runProjectSubcommand(argv, options = {}) {
14
+ const out = options.stdout ?? ((m) => process.stdout.write(`${m}\n`));
15
+ const err = options.stderr ?? ((m) => process.stderr.write(`${m}\n`));
16
+ const client = options.client ?? new ProjectClient();
17
+ const subcommand = argv[1] ?? "list";
18
+ try {
19
+ switch (subcommand) {
20
+ case "list":
21
+ case "ls":
22
+ return await listCmd(client, out);
23
+ case "pull":
24
+ return await pullCmd(client, argv[2], argv[3], out, err);
25
+ default:
26
+ err(`unknown subcommand: ${subcommand}`);
27
+ err("usage: codebase project [list | pull <id> [dest]]");
28
+ return 2;
29
+ }
30
+ }
31
+ catch (e) {
32
+ if (e instanceof NotAuthenticatedError) {
33
+ err(e.message);
34
+ return 1;
35
+ }
36
+ if (e instanceof ProjectClientError) {
37
+ err(`error: ${e.message}`);
38
+ return e.status === 404 ? 4 : 1;
39
+ }
40
+ err(`error: ${e instanceof Error ? e.message : String(e)}`);
41
+ return 1;
42
+ }
43
+ }
44
+ async function listCmd(client, out) {
45
+ const projects = await client.list();
46
+ if (projects.length === 0) {
47
+ out("(no projects yet — build one at https://codebase.design or pull an existing one)");
48
+ return 0;
49
+ }
50
+ out(`${projects.length} project${projects.length === 1 ? "" : "s"}:`);
51
+ out("");
52
+ for (const p of projects) {
53
+ out(formatProjectLine(p));
54
+ }
55
+ out("");
56
+ out("pull one with: codebase project pull <id>");
57
+ return 0;
58
+ }
59
+ async function pullCmd(client, projectId, dest, out, err) {
60
+ if (!projectId) {
61
+ err("usage: codebase project pull <id> [dest]");
62
+ return 2;
63
+ }
64
+ if (!client.hasCredentials()) {
65
+ throw new NotAuthenticatedError();
66
+ }
67
+ const target = dest ?? defaultDownloadPath(projectId);
68
+ out(`pulling ${projectId} → ${target}`);
69
+ const result = await client.pull(projectId, dest);
70
+ const kb = (result.bytes / 1024).toFixed(1);
71
+ out(`✓ wrote ${result.path} (${kb} KB)`);
72
+ out("");
73
+ out(`unzip with: unzip -d ./${projectId} ${result.path}`);
74
+ return 0;
75
+ }
76
+ function formatProjectLine(p) {
77
+ const id = p.id.padEnd(36);
78
+ const title = (p.title ?? "(untitled)").padEnd(28);
79
+ const sourceTag = p.source === "storage-only" ? " [storage]" : "";
80
+ const date = p.publishedAt
81
+ ? ` · published ${shortDate(p.publishedAt)}`
82
+ : p.createdAt
83
+ ? ` · created ${shortDate(p.createdAt)}`
84
+ : "";
85
+ return ` ${id} ${title}${sourceTag}${date}`;
86
+ }
87
+ function shortDate(iso) {
88
+ // Strip the time portion for the listing — full ISO is verbose
89
+ // and the user just wants to scan dates.
90
+ return iso.slice(0, 10);
91
+ }
92
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/projects/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAS5G;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAc,EAAE,UAA6B,EAAE;IACzF,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;IAErD,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAErC,IAAI,CAAC;QACJ,QAAQ,UAAU,EAAE,CAAC;YACpB,KAAK,MAAM,CAAC;YACZ,KAAK,IAAI;gBACR,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACnC,KAAK,MAAM;gBACV,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC1D;gBACC,GAAG,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;gBACzC,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBACzD,OAAO,CAAC,CAAC;QACX,CAAC;IACF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACZ,IAAI,CAAC,YAAY,qBAAqB,EAAE,CAAC;YACxC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACf,OAAO,CAAC,CAAC;QACV,CAAC;QACD,IAAI,CAAC,YAAY,kBAAkB,EAAE,CAAC;YACrC,GAAG,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3B,OAAO,CAAC,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjC,CAAC;QACD,GAAG,CAAC,UAAU,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5D,OAAO,CAAC,CAAC;IACV,CAAC;AACF,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,MAAqB,EAAE,GAA0B;IACvE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACrC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,GAAG,CAAC,kFAAkF,CAAC,CAAC;QACxF,OAAO,CAAC,CAAC;IACV,CAAC;IAED,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,WAAW,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IACtE,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAClD,OAAO,CAAC,CAAC;AACV,CAAC;AAED,KAAK,UAAU,OAAO,CACrB,MAAqB,EACrB,SAA6B,EAC7B,IAAwB,EACxB,GAA0B,EAC1B,GAA0B;IAE1B,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,0CAA0C,CAAC,CAAC;QAChD,OAAO,CAAC,CAAC;IACV,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,qBAAqB,EAAE,CAAC;IACnC,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,IAAI,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACtD,GAAG,CAAC,WAAW,SAAS,MAAM,MAAM,EAAE,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5C,GAAG,CAAC,WAAW,MAAM,CAAC,IAAI,KAAK,EAAE,MAAM,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,CAAC,CAAC;IACR,GAAG,CAAC,2BAA2B,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC;AACV,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAkB;IAC5C,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,YAAY,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;IAClE,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW;QACzB,CAAC,CAAC,gBAAgB,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;QAC5C,CAAC,CAAC,CAAC,CAAC,SAAS;YACZ,CAAC,CAAC,cAAc,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,KAAK,EAAE,KAAK,KAAK,GAAG,SAAS,GAAG,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC7B,+DAA+D;IAC/D,yCAAyC;IACzC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,120 @@
1
+ import { createWriteStream, mkdirSync, statSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { Readable } from "node:stream";
5
+ import { pipeline } from "node:stream/promises";
6
+ import { CredentialsStore } from "../auth/credentials.js";
7
+ const DEFAULT_BASE = "https://codebase.design";
8
+ export class NotAuthenticatedError extends Error {
9
+ constructor() {
10
+ super("not signed in to codebase.design. Run `codebase auth login`, or use BYOK by setting an *_API_KEY env var.");
11
+ this.name = "NotAuthenticatedError";
12
+ }
13
+ }
14
+ export class ProjectClientError extends Error {
15
+ status;
16
+ constructor(message, status) {
17
+ super(message);
18
+ this.status = status;
19
+ this.name = "ProjectClientError";
20
+ }
21
+ }
22
+ /**
23
+ * Read-only client for the `/cli/projects` endpoints on
24
+ * codebase.design. Both endpoints require the `projects` scope on
25
+ * the access token — already requested by the OAuth flow's default
26
+ * scopes (`inference projects credits`).
27
+ */
28
+ export class ProjectClient {
29
+ baseUrl;
30
+ credStore;
31
+ fetchFn;
32
+ constructor(opts = {}) {
33
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE).replace(/\/+$/, "");
34
+ this.credStore = opts.credentials ?? new CredentialsStore();
35
+ this.fetchFn = opts.fetchFn ?? globalThis.fetch.bind(globalThis);
36
+ }
37
+ /**
38
+ * List the user's projects. Merges the Convex-sourced list with
39
+ * raw storage-only entries the backend reports separately, so the
40
+ * CLI sees both indexed-and-published projects and any work-in-
41
+ * progress trees that haven't been published yet.
42
+ */
43
+ async list() {
44
+ const token = this.requireToken();
45
+ const res = await this.fetchFn(`${this.baseUrl}/api/cli/projects`, {
46
+ headers: { Authorization: `Bearer ${token}` },
47
+ });
48
+ if (res.status === 401)
49
+ throw new NotAuthenticatedError();
50
+ if (!res.ok) {
51
+ throw new ProjectClientError(`list projects failed: ${res.status} ${await res.text().catch(() => "")}`.trim(), res.status);
52
+ }
53
+ const body = (await res.json());
54
+ const indexed = (body.projects ?? []).map((p) => ({
55
+ ...p,
56
+ source: "convex",
57
+ }));
58
+ const indexedIds = new Set(indexed.map((p) => p.id));
59
+ const storageOnly = [];
60
+ for (const id of body.s3Projects ?? []) {
61
+ if (indexedIds.has(id))
62
+ continue;
63
+ storageOnly.push({ id, source: "storage-only" });
64
+ }
65
+ return [...indexed, ...storageOnly];
66
+ }
67
+ /**
68
+ * Download a project as a ZIP and stream-write it to `destPath`
69
+ * (or `~/.codebase/pulls/<id>.zip` if not given). Returns the path
70
+ * the bytes were written to plus the file size on disk so the
71
+ * caller can surface it.
72
+ */
73
+ async pull(projectId, destPath) {
74
+ const token = this.requireToken();
75
+ const res = await this.fetchFn(`${this.baseUrl}/api/cli/projects/${encodeURIComponent(projectId)}/pull`, {
76
+ headers: { Authorization: `Bearer ${token}` },
77
+ });
78
+ if (res.status === 401)
79
+ throw new NotAuthenticatedError();
80
+ if (res.status === 404) {
81
+ throw new ProjectClientError(`project not found: ${projectId}`, 404);
82
+ }
83
+ if (!res.ok) {
84
+ throw new ProjectClientError(`pull failed: ${res.status} ${await res.text().catch(() => "")}`.trim(), res.status);
85
+ }
86
+ const finalPath = destPath ?? defaultPullPath(projectId);
87
+ mkdirSync(dirname(finalPath), { recursive: true });
88
+ if (!res.body) {
89
+ throw new ProjectClientError("pull response had no body", res.status);
90
+ }
91
+ await pipeline(Readable.fromWeb(res.body), createWriteStream(finalPath));
92
+ const bytes = statSync(finalPath).size;
93
+ return { path: finalPath, bytes };
94
+ }
95
+ /**
96
+ * Convenience: returns the loaded credential, or null if none.
97
+ * Useful for slash commands that want to gracefully degrade
98
+ * instead of throwing.
99
+ */
100
+ hasCredentials() {
101
+ const creds = this.credStore.load();
102
+ return !!creds && !this.credStore.isExpired(creds);
103
+ }
104
+ requireToken() {
105
+ const creds = this.credStore.load();
106
+ if (!creds || this.credStore.isExpired(creds)) {
107
+ throw new NotAuthenticatedError();
108
+ }
109
+ return creds.accessToken;
110
+ }
111
+ }
112
+ function defaultPullPath(projectId) {
113
+ const safe = projectId.replace(/[^a-zA-Z0-9._-]/g, "_");
114
+ return join(homedir(), ".codebase", "pulls", `${safe}.zip`);
115
+ }
116
+ /** Re-export so callers can pre-check the destination path. */
117
+ export function defaultDownloadPath(projectId) {
118
+ return defaultPullPath(projectId);
119
+ }
120
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/projects/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/projects/types.ts"],"names":[],"mappings":""}
@@ -1,15 +1,20 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { CredentialsStore } from "../auth/credentials.js";
5
+ const DEFAULT_BASE_URL = "https://codebase.design/api/cli";
6
+ const DEFAULT_CACHE_PATH = join(homedir(), ".codebase", "cache", "platform-assets.json");
7
+ const DEFAULT_TTL_MS = 60 * 60 * 1000; // 1 hour
1
8
  /**
2
- * Loader that fetches the user's curated skills, templates, and
3
- * prompts from their codebase.foundation account.
9
+ * Fetches the user's curated skills/templates/prompts from
10
+ * codebase.design and merges them into the AssetRegistry. Caches
11
+ * the response under ~/.codebase/cache/platform-assets.json so
12
+ * subsequent CLI launches don't pay the round trip.
4
13
  *
5
- * NOT YET IMPLEMENTED. This file exists as a contract anchor so the
6
- * AssetRegistry already knows about the platform path: when the
7
- * Phase 7+ implementation lands, it slots in here without further
8
- * surgery to the agent or App layer.
14
+ * Wire format (server returns one bundle, the loader fans it out
15
+ * into the three asset kinds):
9
16
  *
10
- * Wire format (planned):
11
- *
12
- * GET https://codebase.foundation/api/cli/skills
17
+ * GET ${baseUrl}/assets
13
18
  * Authorization: Bearer <accessToken>
14
19
  *
15
20
  * 200 OK
@@ -17,47 +22,137 @@
17
22
  * "templates": [ { id, name, description, body, files?, tags? }, … ],
18
23
  * "prompts": [ { id, name, description, body, tags? }, … ] }
19
24
  *
20
- * Cache the response under ~/.codebase/cache/platform-assets.json with
21
- * an ETag header so subsequent CLI launches don't pay the round trip.
22
- * Refresh on `codebase auth refresh` or after 1 hour, whichever is
23
- * sooner. Refresh failures fall back to the cached response — never
24
- * leave a session stranded because the platform is briefly down.
25
+ * Behavior matrix:
25
26
  *
26
- * Not authenticated → returns empty lists, never throws. The user just
27
- * sees their bundled + local assets, which is the correct
28
- * unauthenticated UX.
27
+ * not signed in → returns [] without a network call
28
+ * network error → returns the last cached body if any,
29
+ * else [] (silent — never crashes a session)
30
+ * 404 (endpoint TBD) → caches an empty bundle, returns []
31
+ * (no warning — the backend half is
32
+ * expected to land later, see
33
+ * docs/plans/2026-05-09-codebase-cli-
34
+ * oauth-server-side.md §3-4)
35
+ * 200 → caches body + ETag, returns shaped list
36
+ * 304 (ETag match) → bumps the cache timestamp, returns cached
29
37
  */
30
38
  export class PlatformLoader {
39
+ source = "platform";
31
40
  credentials;
32
41
  baseUrl;
33
- source = "platform";
34
- constructor(credentials, baseUrl = "https://codebase.foundation/api/cli") {
35
- this.credentials = credentials;
36
- this.baseUrl = baseUrl;
42
+ cachePath;
43
+ ttlMs;
44
+ fetchFn;
45
+ now;
46
+ inFlight = null;
47
+ constructor(options = {}) {
48
+ this.credentials = options.credentials ?? new CredentialsStore();
49
+ this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
50
+ this.cachePath = options.cachePath ?? DEFAULT_CACHE_PATH;
51
+ this.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
52
+ this.fetchFn = options.fetchFn ?? globalThis.fetch.bind(globalThis);
53
+ this.now = options.now ?? Date.now;
37
54
  }
38
55
  async listSkills() {
39
- void this.fetchOrEmpty;
40
- return [];
56
+ const bundle = await this.bundle();
57
+ return (bundle.skills ?? []).map((s) => ({ ...s, kind: "skill", source: this.source }));
41
58
  }
42
59
  async listTemplates() {
43
- return [];
60
+ const bundle = await this.bundle();
61
+ return (bundle.templates ?? []).map((t) => ({ ...t, kind: "template", source: this.source }));
44
62
  }
45
63
  async listPrompts() {
46
- return [];
47
- }
48
- /**
49
- * Placeholder for the real fetch path. Implementation steps:
50
- * 1. Read credentials; if absent or expired, return null.
51
- * 2. GET ${baseUrl}/skills with Authorization: Bearer …
52
- * 3. On 401, trigger refresh via OAuthFlow.refreshAccessToken.
53
- * 4. On success, cache under ~/.codebase/cache/platform-assets.json.
54
- * 5. On any failure post-401-retry, return cached response if any
55
- * and log a one-line warning.
56
- */
57
- async fetchOrEmpty() {
58
- void this.credentials;
59
- void this.baseUrl;
64
+ const bundle = await this.bundle();
65
+ return (bundle.prompts ?? []).map((p) => ({ ...p, kind: "prompt", source: this.source }));
66
+ }
67
+ /** Force the next list call to re-fetch instead of using the cache. */
68
+ invalidate() {
69
+ try {
70
+ if (existsSync(this.cachePath)) {
71
+ writeFileSync(this.cachePath, JSON.stringify({ fetchedAt: 0, body: {} }));
72
+ }
73
+ }
74
+ catch {
75
+ // non-fatal
76
+ }
77
+ }
78
+ async bundle() {
79
+ // Coalesce concurrent calls — listSkills + listTemplates + listPrompts
80
+ // from a single registry pass should share one fetch.
81
+ if (this.inFlight)
82
+ return this.inFlight;
83
+ this.inFlight = this.bundleOnce().finally(() => {
84
+ this.inFlight = null;
85
+ });
86
+ return this.inFlight;
87
+ }
88
+ async bundleOnce() {
89
+ // Not signed in → never fetch, never cache, never warn.
90
+ const creds = this.credentials.load();
91
+ if (!creds || this.credentials.isExpired(creds))
92
+ return {};
93
+ const cached = readCache(this.cachePath);
94
+ const fresh = cached && this.now() - cached.fetchedAt < this.ttlMs;
95
+ if (fresh)
96
+ return cached.body;
97
+ try {
98
+ const headers = {
99
+ Authorization: `Bearer ${creds.accessToken}`,
100
+ Accept: "application/json",
101
+ };
102
+ if (cached?.etag)
103
+ headers["If-None-Match"] = cached.etag;
104
+ const res = await this.fetchFn(`${this.baseUrl}/assets`, { headers });
105
+ if (res.status === 304 && cached) {
106
+ // ETag match — bump the cache timestamp, return cached body.
107
+ writeCache(this.cachePath, { ...cached, fetchedAt: this.now() });
108
+ return cached.body;
109
+ }
110
+ if (res.status === 404) {
111
+ // Endpoint TBD. Cache an empty bundle so we don't hammer the
112
+ // server until the next TTL window.
113
+ const empty = { fetchedAt: this.now(), body: {} };
114
+ writeCache(this.cachePath, empty);
115
+ return empty.body;
116
+ }
117
+ if (res.status === 401 || !res.ok) {
118
+ // Auth blip or transient 5xx — fall back to whatever's cached.
119
+ return cached?.body ?? {};
120
+ }
121
+ const body = (await res.json());
122
+ const etag = res.headers.get("ETag") ?? undefined;
123
+ writeCache(this.cachePath, { fetchedAt: this.now(), etag, body });
124
+ return body;
125
+ }
126
+ catch {
127
+ // Network failures degrade to cached. Never throw — a flaky
128
+ // platform shouldn't take the agent down.
129
+ return cached?.body ?? {};
130
+ }
131
+ }
132
+ }
133
+ function readCache(path) {
134
+ if (!existsSync(path))
135
+ return null;
136
+ try {
137
+ const raw = readFileSync(path, "utf8");
138
+ const parsed = JSON.parse(raw);
139
+ if (typeof parsed.fetchedAt !== "number")
140
+ return null;
141
+ if (!parsed.body || typeof parsed.body !== "object")
142
+ return null;
143
+ return parsed;
144
+ }
145
+ catch {
60
146
  return null;
61
147
  }
62
148
  }
149
+ function writeCache(path, bundle) {
150
+ try {
151
+ mkdirSync(dirname(path), { recursive: true });
152
+ writeFileSync(path, JSON.stringify(bundle));
153
+ }
154
+ catch {
155
+ // non-fatal — the in-memory result still serves the current process
156
+ }
157
+ }
63
158
  //# sourceMappingURL=platform-loader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform-loader.js","sourceRoot":"","sources":["../../src/skills/platform-loader.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,cAAc;IAIR;IACA;IAJT,MAAM,GAAG,UAAmB,CAAC;IAEtC,YACkB,WAA6B,EAC7B,UAAkB,qCAAqC;QADvD,gBAAW,GAAX,WAAW,CAAkB;QAC7B,YAAO,GAAP,OAAO,CAAgD;IACtE,CAAC;IAEJ,KAAK,CAAC,UAAU;QACf,KAAK,IAAI,CAAC,YAAY,CAAC;QACvB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,KAAK,CAAC,aAAa;QAClB,OAAO,EAAE,CAAC;IACX,CAAC;IAED,KAAK,CAAC,WAAW;QAChB,OAAO,EAAE,CAAC;IACX,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,YAAY;QACzB,KAAK,IAAI,CAAC,WAAW,CAAC;QACtB,KAAK,IAAI,CAAC,OAAO,CAAC;QAClB,OAAO,IAAI,CAAC;IACb,CAAC;CACD"}
1
+ {"version":3,"file":"platform-loader.js","sourceRoot":"","sources":["../../src/skills/platform-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Typed factory for a ToolContext suitable for unit tests. Uses real
3
+ * instances of the in-memory stores (they're cheap to construct) so
4
+ * tests catch interface-shape drift the moment a field is added to
5
+ * ToolContext — previously this was `{} as any` for every field, which
6
+ * meant adding a new required member to ToolContext compiled green
7
+ * while every test was secretly missing it.
8
+ */
9
+ import { MemoryStore } from "../../memory/store.js";
10
+ import { PlanModeStore } from "../../plan/store.js";
11
+ import { UserQueryStore } from "../../user-queries/store.js";
12
+ import { FileStateCache } from "../file-state-cache.js";
13
+ import { TaskStore } from "../task-store.js";
14
+ export function makeMockToolContext(cwd) {
15
+ return {
16
+ cwd,
17
+ fileStateCache: new FileStateCache(),
18
+ tasks: new TaskStore(),
19
+ userQueries: new UserQueryStore(),
20
+ planMode: new PlanModeStore(),
21
+ memory: new MemoryStore({ cwd }),
22
+ // spawnSubagent is the only field a test can't supply a real
23
+ // implementation for (it depends on the live agent factory).
24
+ // We throw to make the boundary explicit: any test that calls a
25
+ // subagent-spawning tool needs to provide its own stub.
26
+ spawnSubagent: () => {
27
+ throw new Error("mock-tool-context: spawnSubagent not stubbed — provide one in the test if you need it");
28
+ },
29
+ };
30
+ }
31
+ //# sourceMappingURL=mock-tool-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-tool-context.js","sourceRoot":"","sources":["../../../src/tools/__test__/mock-tool-context.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAG7C,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC9C,OAAO;QACN,GAAG;QACH,cAAc,EAAE,IAAI,cAAc,EAAE;QACpC,KAAK,EAAE,IAAI,SAAS,EAAE;QACtB,WAAW,EAAE,IAAI,cAAc,EAAE;QACjC,QAAQ,EAAE,IAAI,aAAa,EAAE;QAC7B,MAAM,EAAE,IAAI,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;QAChC,6DAA6D;QAC7D,6DAA6D;QAC7D,gEAAgE;QAChE,wDAAwD;QACxD,aAAa,EAAE,GAAG,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;QAC1G,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -35,7 +35,7 @@ Arguments:
35
35
  - limit (optional): max lines to return. Default 2000, max 2000.
36
36
 
37
37
  Behavior:
38
- - Text files: returned line-numbered (six-column gutter, tab, content), suitable for the model to quote back into edit_file.
38
+ - Text files: returned line-numbered as \` N→content\` (six-column right-aligned line number, an arrow separator, then the line). When you quote a line into edit_file's old_string, quote only the part after the arrow.
39
39
  - Image files (.png, .jpg, .jpeg, .gif, .webp, .bmp): returned as a vision payload — works only with image-capable models.
40
40
  - Files > 5 MB are rejected; use shell head/tail/sed for huge files.
41
41
  - Binary text files are rejected.
@@ -100,7 +100,13 @@ export function createReadFile(ctx) {
100
100
  const endIdx = Math.min(startIdx + limit, totalLines);
101
101
  const isPartialView = startIdx > 0 || endIdx < totalLines;
102
102
  const slice = allLines.slice(startIdx, endIdx);
103
- const formatted = slice.map((line, i) => `${pad6(startIdx + i + 1)}\t${line}`).join("\n");
103
+ // Use a literal arrow instead of \t so the gutter renders tight in
104
+ // every terminal (TUI / pager / web echo). cat -n's tab gets
105
+ // expanded to the next tab stop by most renderers, producing the
106
+ // ugly 8-column gap users complained about. Matches Claude Code's
107
+ // `${num}→${content}` format, which models are already familiar
108
+ // with from training data.
109
+ const formatted = slice.map((line, i) => `${pad6(startIdx + i + 1)}→${line}`).join("\n");
104
110
  const tail = isPartialView ? `\n... (showing lines ${startIdx + 1}-${endIdx} of ${totalLines})` : "";
105
111
  ctx.fileStateCache.record({
106
112
  path: absPath,
@@ -1 +1 @@
1
- {"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"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"}