Skip to content

Commit d188f14

Browse files
Add the Agent Factories authoring surface
Agent Factories let a trusted extension declare a JavaScript closure that orchestrates a fleet of subagents, and invoke it by name. The runtime half shipped in copilot-agent-runtime#12953 and #13077; this is the SDK half. The feature is dark behind the runtime's `agent_factories` flag plus its billing gate, and every public type is marked `@experimental`. RPC surface - Bumps `@github/copilot` to ^1.0.75, the first published runtime whose schemas carry the full factory surface, and regenerates every language. - Generated wire types for the factory session methods (`run`, `resume`, `getRun`, `listRuns`, `getRunDetail`, `getRunProgress`, `cancel`), the reverse `factory.execute` / `factory.abort` calls, run envelopes, registration metadata, and the observability DTOs. - Fixes opaque-JSON codegen so a factory's args and result can be any JSON value rather than an object alone, which also lets a void factory complete without a result. Authoring harness - `defineFactory({ meta, run })` returns an opaque handle; an extension registers it through `joinSession({ factories: [...] })`. Only metadata crosses to the runtime — the closure stays in the extension process and is invoked over the reverse `factory.execute` RPC. - The `run()` context: `args`, the extension's full `session`, a per-run `signal`, `runId`, plus `agent()` (one single-turn subagent, optionally schema-constrained), `step()` (journal-backed memoization), `parallel()`, `pipeline()`, and `phase()` / `log()` progress markers. `factory()` throws, because nesting is forbidden. - `session.factory.*` friendly wrappers, including `resume(runId)`, which reuses the persisted name, arguments, journal, and accounting so a caller never re-sends them. - Declared limits (`maxConcurrentSubagents`, `maxTotalSubagents`, `timeoutSeconds`, `maxAiCredits`) validated at the authoring boundary. - Strict JSON validation shared by factory results and journaled `step()` producers, so a lossy value is rejected rather than silently mutating on a resumed replay. `run()` and `resume()` resolve with the run envelope for every outcome — completed, error, halted, or cancelled — and reject only when no run exists (an unknown factory, a declined approval, an already-active session). This keeps the signature stable for the planned background-only execution mode, which changes a run's timing and status but not its shape. Authoring documentation lives in `nodejs/docs/factories.md`, with a pattern library in `nodejs/docs/factory-patterns.md`.
1 parent aa4e707 commit d188f14

35 files changed

Lines changed: 15788 additions & 1379 deletions

dotnet/src/Generated/Rpc.cs

Lines changed: 2301 additions & 181 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dotnet/src/Generated/SessionEvents.cs

Lines changed: 137 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dotnet/src/SessionFsProvider.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,24 @@ async Task<SessionFsSqliteQueryResult> ISessionFsHandler.SqliteQueryAsync(Sessio
309309
}
310310
}
311311

312+
Task<SessionFsSqliteTransactionResult> ISessionFsHandler.SqliteTransactionAsync(SessionFsSqliteTransactionRequest request, CancellationToken cancellationToken)
313+
{
314+
// This SDK's provider interface exposes no atomic-transaction hook, so
315+
// the batch is refused outright rather than applied non-atomically.
316+
var message = this is ISessionFsSqliteProvider
317+
? "Atomic SQLite transactions are not supported by this SessionFs provider"
318+
: "SQLite is not supported by this SessionFs provider";
319+
320+
return Task.FromResult(new SessionFsSqliteTransactionResult
321+
{
322+
Error = new SessionFsSqliteTransactionError
323+
{
324+
ErrorClass = SessionFsSqliteTransactionErrorClass.Fatal,
325+
Message = message,
326+
},
327+
});
328+
}
329+
312330
async Task<SessionFsSqliteExistsResult> ISessionFsHandler.SqliteExistsAsync(SessionFsSqliteExistsRequest request, CancellationToken cancellationToken)
313331
{
314332
if (this is not ISessionFsSqliteProvider sqliteProvider)

0 commit comments

Comments
 (0)