From 18044ed5755a00edac5d8ba7bd097e3d8fcc9ceb Mon Sep 17 00:00:00 2001 From: hbrooks Date: Fri, 24 Jul 2026 10:58:53 -0400 Subject: [PATCH] session: emit budget.session for --budget after the server limits rename PR ellipsis#5846 renamed the AgentConfig spend-limit field from limits.run to budget.session, and AgentConfig is extra=forbid, so every `agent session start --budget ` now fails with a 400 ("limits: Extra inputs are not permitted"). Map --budget to sugar.budget = { session: N } and update the stale limits.run examples in the help strings, README, and ellipsis skill. --- README.md | 2 +- skills/ellipsis/SKILL.md | 4 ++-- src/commands/session.tsx | 6 +++--- test/session.test.ts | 18 +++++++++--------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 2bee8ee..aaeb4b3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ agent host delete beta # remove a host and its stored token agent session start --config # start a session from a saved config agent session start --config-file f.json # ...or from an inline config agent session start --template welcome-to-ellipsis # ...or from a maintained template -agent session start --config --config-override "limits:\n run: 5" # override config fields for this session +agent session start --config --config-override "budget:\n session: 5" # override config fields for this session agent session start --config --watch # start and immediately stream it agent session list --limit 20 # list recent sessions (filter by --source, --author, --days, …) agent session search "webhook retries" # search session history: transcripts, recaps, created PRs, similarity diff --git a/skills/ellipsis/SKILL.md b/skills/ellipsis/SKILL.md index 55bb736..86b8fc3 100644 --- a/skills/ellipsis/SKILL.md +++ b/skills/ellipsis/SKILL.md @@ -241,8 +241,8 @@ sandbox: repositories: - name: api -limits: - run: 5.00 +budget: + session: 5.00 ``` ## Inside an Ellipsis sandbox diff --git a/src/commands/session.tsx b/src/commands/session.tsx index d9c7b2a..3f3aa5d 100644 --- a/src/commands/session.tsx +++ b/src/commands/session.tsx @@ -106,7 +106,7 @@ export function registerSession(program: Command): void { ) .option( '-o, --config-override ', - 'partial agent config (YAML/JSON) merged onto the chosen config for this session, e.g. "limits:\\n run: 5"', + 'partial agent config (YAML/JSON) merged onto the chosen config for this session, e.g. "budget:\\n session: 5"', ) .option( '--config-override-file ', @@ -127,7 +127,7 @@ export function registerSession(program: Command): void { '--rebuild', 'skip the sandbox image cache: fresh full build (image layers, clones, image.setup), whose snapshot refreshes the cache', ) - .option('--budget ', 'per-run spend limit in USD for this session (limits.run)', toNumber) + .option('--budget ', 'spend limit in USD for this session (budget.session)', toNumber) .option( '-p, --prompt ', "the session prompt, appended to the agent's initial user query (or pass it positionally)", @@ -1029,7 +1029,7 @@ export function buildStartOverride(opts: { if (opts.repo && opts.repo.length) sandbox.repositories = opts.repo.map(parseRepo) if (Object.keys(sandbox).length) sugar.sandbox = sandbox - if (opts.budget !== undefined) sugar.limits = { run: opts.budget } + if (opts.budget !== undefined) sugar.budget = { session: opts.budget } const merged = deepMerge(base, sugar) return Object.keys(merged).length ? merged : undefined diff --git a/test/session.test.ts b/test/session.test.ts index cc4ba77..7d4d261 100644 --- a/test/session.test.ts +++ b/test/session.test.ts @@ -103,8 +103,8 @@ describe('readConfigFile', () => { } it('parses a .yaml file', () => { - const path = write('cfg.yaml', 'name: demo\nlimits:\n run: 5\n') - expect(readConfigFile(path)).toEqual({ name: 'demo', limits: { run: 5 } }) + const path = write('cfg.yaml', 'name: demo\nbudget:\n session: 5\n') + expect(readConfigFile(path)).toEqual({ name: 'demo', budget: { session: 5 } }) }) it('parses a .yml file', () => { @@ -113,8 +113,8 @@ describe('readConfigFile', () => { }) it('parses a .json file', () => { - const path = write('cfg.json', '{"name":"demo","limits":{"run":5}}') - expect(readConfigFile(path)).toEqual({ name: 'demo', limits: { run: 5 } }) + const path = write('cfg.json', '{"name":"demo","budget":{"session":5}}') + expect(readConfigFile(path)).toEqual({ name: 'demo', budget: { session: 5 } }) }) it('falls back to YAML for unknown extensions (JSON is valid YAML)', () => { @@ -152,10 +152,10 @@ describe('applyConfigOverride', () => { }) it('reads and parses a file override into the structured mapping', () => { - const path = write('override.yaml', 'limits:\n run: 5\n') + const path = write('override.yaml', 'budget:\n session: 5\n') const req: { config_override?: Record; config_override_yaml?: string } = {} applyConfigOverride(req, { configOverrideFile: path }) - expect(req).toEqual({ config_override: { limits: { run: 5 } } }) + expect(req).toEqual({ config_override: { budget: { session: 5 } } }) }) it('rejects passing both inline and file forms', () => { @@ -214,7 +214,7 @@ describe('buildStartOverride', () => { compute: { cpu: 2, memory: '8GB', timeout: '30m' }, repositories: [{ owner: 'ellipsis-dev', name: 'ellipsis' }, { name: 'solo' }], }, - limits: { run: 0.5 }, + budget: { session: 0.5 }, }) }) @@ -231,9 +231,9 @@ describe('buildStartOverride', () => { }) it('uses a file override as the base', () => { - const path = write('base.yaml', 'limits:\n run: 1\n') + const path = write('base.yaml', 'budget:\n session: 1\n') expect(buildStartOverride({ configOverrideFile: path, budget: 5 })).toEqual({ - limits: { run: 5 }, + budget: { session: 5 }, }) })