Skip to content

Commit a7853bc

Browse files
Add provider project and environment context support
1 parent 47d15b1 commit a7853bc

29 files changed

Lines changed: 2210 additions & 229 deletions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@agentpond/files-sdk": minor
3+
"@agentpond/core": minor
4+
"agentpond": minor
5+
---
6+
7+
Add Files SDK span export and persistent bucket-backed CLI sync environments.

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ This repository uses Changesets to generate package changelogs.
3838
<!-- gitnexus:start -->
3939
# GitNexus — Code Intelligence
4040

41-
This project is indexed by GitNexus as **agentpond** (1333 symbols, 3159 relationships, 106 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
41+
This project is indexed by GitNexus as **agentpond** (1524 symbols, 3645 relationships, 121 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
4242

4343
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
4444

CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- gitnexus:start -->
22
# GitNexus — Code Intelligence
33

4-
This project is indexed by GitNexus as **agentpond** (1333 symbols, 3159 relationships, 106 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
4+
This project is indexed by GitNexus as **agentpond** (1524 symbols, 3645 relationships, 121 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
55

66
> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
77

apps/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@
3030
"@agentpond/duckdb": "workspace:*",
3131
"@agentpond/fastify-ingest": "workspace:*",
3232
"@agentpond/firebase": "workspace:*",
33+
"@agentpond/files-sdk": "workspace:*",
3334
"@agentpond/google": "workspace:*",
3435
"@agentpond/supabase": "workspace:*",
3536
"@agentpond/vercel": "workspace:*",
3637
"@duckdb/node-api": "^1.5.4-r.1",
3738
"@inquirer/prompts": "8.5.2",
3839
"commander": "15.0.0",
3940
"fastify": "^5.6.2",
41+
"files-sdk": "2.2.1",
4042
"protobufjs": "^7.6.5",
4143
"skills": "1.5.9",
4244
"zod": "^4.3.6"

apps/cli/src/commands/env.ts

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import { existsSync } from "node:fs";
22
import {
33
type AgentPondStoreType,
4+
type FilesSdkEnvironmentConfig,
45
initAgentPondEnvironment,
56
listAgentPondEnvironments,
67
parseEnvFileEntries,
78
readDevServerLock,
89
resolveAgentPondEnvironment,
910
selectAgentPondEnvironment,
1011
} from "@agentpond/core";
11-
import { select } from "@inquirer/prompts";
12+
import { input, select } from "@inquirer/prompts";
1213
import type { Command } from "commander";
14+
import { getProvider, PROVIDER_NAMES } from "files-sdk/providers";
1315
import { CliError, print } from "../cli-support.js";
1416
import { addGlobalOptions, type GlobalOptions } from "../command-support.js";
1517
import {
@@ -32,22 +34,33 @@ export type SelectPrompt<T extends string> = (config: {
3234
export type SelectEnvironmentPrompt = SelectPrompt<string>;
3335
export type AgentPondInitStore = AgentPondStoreType;
3436
export type SelectStorePrompt = SelectPrompt<AgentPondInitStore>;
37+
export type SelectFilesProviderPrompt = SelectPrompt<string>;
38+
export type InputPrompt = (config: {
39+
message: string;
40+
default?: string;
41+
}) => Promise<string>;
3542

3643
type EnvOptions = GlobalOptions & {
44+
bucket?: string;
3745
langfuse?: boolean;
3846
otel?: boolean;
47+
provider?: string;
3948
store?: string;
4049
};
4150

4251
export function registerEnvCommand(
4352
program: Command,
4453
options: {
4554
selectEnvironment?: SelectEnvironmentPrompt;
55+
selectFilesProvider?: SelectFilesProviderPrompt;
4656
selectStore?: SelectStorePrompt;
57+
inputBucket?: InputPrompt;
4758
} = {},
4859
): void {
4960
const promptSelect = options.selectEnvironment ?? select<string>;
5061
const promptStore = options.selectStore ?? select<AgentPondInitStore>;
62+
const promptFilesProvider = options.selectFilesProvider ?? select<string>;
63+
const promptBucket = options.inputBucket ?? input;
5164
const env = addGlobalOptions(
5265
program.command("env").description("select and manage environments"),
5366
);
@@ -100,7 +113,9 @@ export function registerEnvCommand(
100113

101114
addGlobalOptions(env.command("init <name>"))
102115
.description("initialize a manual environment")
103-
.option("--store <store>", "object store: s3, gcs, or local")
116+
.option("--store <store>", "object store: files-sdk, s3, gcs, or local")
117+
.option("--provider <provider>", "Files SDK bucket provider")
118+
.option("--bucket <bucket>", "Files SDK bucket name")
104119
.action(
105120
async (name: string, commandOptions: EnvOptions, command: Command) => {
106121
const globalOptions = command.optsWithGlobals<GlobalOptions>();
@@ -111,15 +126,25 @@ export function registerEnvCommand(
111126
const store =
112127
storeFromValue(commandOptions.store) ??
113128
(await promptForStore(promptStore));
129+
const filesSdk = await filesSdkConfigForStore(
130+
store,
131+
commandOptions,
132+
promptFilesProvider,
133+
promptBucket,
134+
);
114135
const environment = initAgentPondEnvironment(name, {
115136
cwd: context.rootDir,
116137
storeType: store,
138+
filesSdk: filesSdk?.config,
117139
});
118140
return print(
119141
{
142+
bucket: filesSdk?.config.bucket,
120143
name: environment.name,
121144
envFile: environment.envFilePath,
122145
dbPath: environment.dbPath,
146+
peerDependencies: filesSdk?.peerDependencies,
147+
provider: filesSdk?.config.provider,
123148
store,
124149
},
125150
Boolean(globalOptions.json),
@@ -178,10 +203,17 @@ function storeFromValue(
178203
value: string | undefined,
179204
): AgentPondInitStore | undefined {
180205
if (value === undefined) return undefined;
181-
if (value === "s3" || value === "gcs" || value === "local") {
206+
if (
207+
value === "files-sdk" ||
208+
value === "s3" ||
209+
value === "gcs" ||
210+
value === "local"
211+
) {
182212
return value;
183213
}
184-
throw new CliError(`--store must be s3, gcs, or local, got "${value}"`);
214+
throw new CliError(
215+
`--store must be files-sdk, s3, gcs, or local, got "${value}"`,
216+
);
185217
}
186218

187219
async function promptForStore(
@@ -193,13 +225,96 @@ async function promptForStore(
193225
return promptSelect({
194226
message: "Select AgentPond object store",
195227
choices: [
228+
{ name: "Files SDK bucket provider", value: "files-sdk" },
196229
{ name: "AWS S3 (or compatible)", value: "s3" },
197230
{ name: "Google Cloud Storage (GCS)", value: "gcs" },
198231
{ name: "Local filesystem", value: "local" },
199232
],
200233
});
201234
}
202235

236+
async function filesSdkConfigForStore(
237+
store: AgentPondInitStore,
238+
options: Pick<EnvOptions, "bucket" | "provider">,
239+
promptProvider: SelectFilesProviderPrompt,
240+
promptBucket: InputPrompt,
241+
): Promise<
242+
| {
243+
config: FilesSdkEnvironmentConfig;
244+
peerDependencies: readonly string[];
245+
}
246+
| undefined
247+
> {
248+
if (store !== "files-sdk") {
249+
if (options.provider !== undefined || options.bucket !== undefined) {
250+
throw new CliError("--provider and --bucket require --store files-sdk");
251+
}
252+
return undefined;
253+
}
254+
255+
const provider =
256+
options.provider ?? (await promptForFilesProvider(promptProvider));
257+
const definition = bucketProvider(provider);
258+
const bucket = (
259+
options.bucket ?? (await promptForFilesBucket(promptBucket))
260+
).trim();
261+
if (!bucket) throw new CliError("Missing --bucket");
262+
263+
return {
264+
config: { provider, bucket },
265+
peerDependencies: definition.peerDeps,
266+
};
267+
}
268+
269+
async function promptForFilesProvider(
270+
promptSelect: SelectFilesProviderPrompt,
271+
): Promise<string> {
272+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
273+
throw new CliError("Missing --provider");
274+
}
275+
return promptSelect({
276+
message: "Select Files SDK bucket provider",
277+
choices: bucketProviders().map(({ name, slug }) => ({
278+
name: `${name} (${slug})`,
279+
value: slug,
280+
})),
281+
});
282+
}
283+
284+
async function promptForFilesBucket(promptInput: InputPrompt): Promise<string> {
285+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
286+
throw new CliError("Missing --bucket");
287+
}
288+
return promptInput({
289+
message: "Files SDK bucket",
290+
default: "agentpond",
291+
});
292+
}
293+
294+
function bucketProvider(provider: string) {
295+
const definition = getProvider(provider);
296+
if (!definition) {
297+
throw new CliError(
298+
`Unknown Files SDK provider "${provider}". Bucket providers: ${bucketProviders()
299+
.map(({ slug }) => slug)
300+
.join(", ")}`,
301+
);
302+
}
303+
if (!definition.env.config?.includes("bucket")) {
304+
throw new CliError(
305+
`Files SDK provider "${provider}" is not bucket-backed and is not supported by AgentPond`,
306+
);
307+
}
308+
return definition;
309+
}
310+
311+
function bucketProviders() {
312+
return PROVIDER_NAMES.flatMap((provider) => {
313+
const definition = getProvider(provider);
314+
return definition?.env.config?.includes("bucket") ? [definition] : [];
315+
});
316+
}
317+
203318
async function promptForEnvironmentName(
204319
promptSelect: SelectEnvironmentPrompt,
205320
cwd: string,

apps/cli/src/environment-context.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
configFromEnv,
66
objectStoreForConfig as configuredObjectStoreForConfig,
77
} from "@agentpond/core";
8+
import { FilesObjectStore } from "@agentpond/files-sdk";
89
import { GcsObjectStore } from "@agentpond/google";
910
import { CliError } from "./cli-support.js";
1011
import { providerForCommand } from "./providers.js";
@@ -63,6 +64,7 @@ function defaultAgentPondEnvironmentContext(
6364
async resolveStorage() {
6465
return {
6566
store: configuredObjectStoreForConfig(config, {
67+
"files-sdk": FilesObjectStore.fromEnvironment,
6668
gcs: GcsObjectStore.fromEnvironment,
6769
s3: S3ObjectStore.fromEnvironment,
6870
}),

apps/cli/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import { CliError } from "./cli-support.js";
77
import { addGlobalOptions } from "./command-support.js";
88
import { registerDevCommand } from "./commands/dev.js";
99
import {
10+
type InputPrompt,
1011
registerEnvCommand,
1112
type SelectEnvironmentPrompt,
13+
type SelectFilesProviderPrompt,
1214
type SelectStorePrompt,
1315
} from "./commands/env.js";
1416
import { registerInitCommand, type SkillsInstaller } from "./commands/init.js";
@@ -30,8 +32,10 @@ const packageJson = require("../package.json") as { version: string };
3032
export const CLI_VERSION = packageJson.version;
3133

3234
export type ProgramOptions = {
35+
inputBucket?: InputPrompt;
3336
installSkills?: SkillsInstaller;
3437
selectEnvironment?: SelectEnvironmentPrompt;
38+
selectFilesProvider?: SelectFilesProviderPrompt;
3539
selectStore?: SelectStorePrompt;
3640
updateCheck?: CliUpdateCheckOptions | false;
3741
};
@@ -58,7 +62,9 @@ export function createProgram(options: ProgramOptions = {}): Command {
5862
registerInitCommand(program, { installSkills: options.installSkills });
5963
registerDevCommand(program);
6064
registerEnvCommand(program, {
65+
inputBucket: options.inputBucket,
6166
selectEnvironment: options.selectEnvironment,
67+
selectFilesProvider: options.selectFilesProvider,
6268
selectStore: options.selectStore,
6369
});
6470
registerSyncCommand(program);

0 commit comments

Comments
 (0)