From 7abfae0e6310ce67b3c610211d6297e74fae49c5 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 08:50:47 -0700 Subject: [PATCH 01/18] feat(daemon): add process-lifetime in-memory secret store Wire DualSecretStore so clients can SetSecret with store=MEMORY without persisting to the OS keychain. Enforces move-on-write exclusivity and fails closed if the other backend cannot be cleared (DR-047). --- docs/ARCHITECTURE.md | 8 +- docs/CONFIGURATION.md | 18 ++- docs/SECURITY.md | 4 + docs/decisions.md | 21 +++ packages/daemon/src/core/secrets.ts | 7 +- .../daemon/src/daemon/secrets/dual.test.ts | 133 +++++++++++++++ packages/daemon/src/daemon/secrets/dual.ts | 153 ++++++++++++++++++ .../src/daemon/server/abbenay-service.ts | 40 ++++- packages/daemon/src/daemon/state.ts | 6 +- .../daemon/src/daemon/web/api-schemas.test.ts | 15 ++ packages/daemon/src/daemon/web/api-schemas.ts | 6 + packages/daemon/src/daemon/web/server.ts | 52 ++++-- .../integration/grpc-real-service.test.ts | 41 +++++ .../daemon/tests/integration/web-sse.test.ts | 20 +++ 14 files changed, 503 insertions(+), 21 deletions(-) create mode 100644 packages/daemon/src/daemon/secrets/dual.test.ts create mode 100644 packages/daemon/src/daemon/secrets/dual.ts diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c09ac4e7..b6740664 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -32,7 +32,7 @@ Abbenay is a unified AI daemon and library written in TypeScript/Node.js that pr │ │ │ ┌─ daemon layer ────────────────────────────────────────────────────┐ │ │ │ DaemonState gRPC Server VS Code Backchannel │ │ -│ │ CLI (Commander) Web Dashboard (Express) KeychainSecretStore │ │ +│ │ CLI (Commander) Web Dashboard (Express) DualSecretStore │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────┬──────────────────────────────┘ @@ -88,6 +88,7 @@ Full application layer. Extends core with transport, UI, and CLI. | `daemon/web/openai-compat.ts` | OpenAI-compatible `/v1/*` routes (models, chat completions) | | `daemon/web/grpc-web-control.ts` | gRPC client for web server control | | `daemon/secrets/keychain.ts` | `KeychainSecretStore` (keytar native addon) | +| `daemon/secrets/dual.ts` | `DualSecretStore` (memory + keychain, move-on-write) | ## Components @@ -203,7 +204,10 @@ interface SecretStore { } ``` -`CoreState` accepts any `SecretStore` via constructor injection. `DaemonState` uses `KeychainSecretStore` (keytar-backed) by default. Tests and library consumers can use `MemorySecretStore`. +`CoreState` accepts any `SecretStore` via constructor injection. `DaemonState` +uses `DualSecretStore` (process-lifetime `MemorySecretStore` + keytar-backed +`KeychainSecretStore`) by default. Tests and library consumers can use +`MemorySecretStore` alone. ## Configuration diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 2533ca1a..7ec5c93f 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -387,6 +387,8 @@ Each provider can specify exactly ONE of these (mutually exclusive): - Key stored in system keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) - Specify the key name used in keychain - Set via web dashboard "API Key" toggle +- The name is a **logical lookup key** into the daemon secret store (keychain + or in-memory backend — see below) ```yaml providers: @@ -395,6 +397,19 @@ providers: api_key_keychain_name: "OPENAI_API_KEY" ``` +### Option 1b: In-memory (process-lifetime) via secrets API + +- Same logical key name as keychain (`api_key_keychain_name`) +- Client sets the value with gRPC `SetSecret` (`store=SECRET_STORE_MEMORY`) + or HTTP `POST /api/secrets` with `{ "store": "memory" }` +- Lives only while the daemon process is running; cleared on restart or + explicit delete/set by a consumer with the `secrets` capability +- Mutually exclusive with keychain for the same key name (writing one backend + removes the key from the other — DR-047) +- Default `store` (omitted / unspecified) remains **keychain** for backward + compatibility +- `SECRET_STORE_ENV` / `"store": "env"` is **not** writable via secrets APIs + ### Option 2: Environment Variable (`api_key_env_var_name`) - Key read from environment variable at runtime @@ -713,7 +728,8 @@ steal prompts/responses/keys — constrained by the | Config files mode `0600` | User-only read/write on disk | | HTTP Bearer auth (DR-030) | Unauthenticated callers cannot read/write secrets or configure providers | | gRPC consumer capabilities (DR-037) | On non-localhost binds, sensitive RPCs require token + capability (`secrets`, `providers`, `config`, `mcp_register`, …) | -| Secret API shape | HTTP `GET /api/secrets` returns key names + `hasValue` only — never secret values. gRPC `GetSecret` (value-returning) requires the `secrets` capability | +| Secret API shape | HTTP `GET /api/secrets` returns key names + `hasValue` (+ `store` when present) only — never secret values. gRPC `GetSecret` (value-returning) requires the `secrets` capability | +| In-memory secrets (DR-047) | Optional process-lifetime backend; never written to disk/keychain; same auth gates as keychain secrets; vanishes on daemon restart | | Secret / endpoint audit logs | `[Audit] secret changed` and `[Audit] provider endpoint changed` (never log secret values) | | Provider endpoint policy (DR-040) | Malformed / disallowed `base_url` values are rejected; changes are audited | | Localhost bind defaults | HTTP/gRPC default to loopback; non-loopback requires intentional opt-in | diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 473d3e13..59706d51 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -65,6 +65,10 @@ defaults (or stronger) in place. - `--host 0.0.0.0`, `ABBENAY_HTTP_AUTH=0`, and `--insecure` deliberately weaken posture. - Cloud providers still receive prompts if you configure them. - HTTP on loopback remains plaintext; use a TLS-terminating proxy when exposing beyond the machine. +- In-memory secrets (DR-047) are not written to disk or the OS keychain, but + they remain readable by any authenticated client with the `secrets` + capability for the life of the daemon process. Restart clears them; treat + RAM and process dumps accordingly. --- diff --git a/docs/decisions.md b/docs/decisions.md index 8a018ec8..0affbce5 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -828,3 +828,24 @@ matching request tool with `400`. When tools mode is `off`, ignore `tool_choice` to force or suppress tool use; dropping it silently made passthrough incomplete versus a real OpenAI-compatible endpoint (issue #77). Numbered DR-046 because main already shipped VS Code webview UX as DR-045. + +--- + +## DR-047: Process-lifetime in-memory secret store + +**Date:** 2026-08-12 +**Decision:** The daemon secret store is a dual backend (`DualSecretStore`): +OS keychain (persistent) and process-lifetime memory. Clients select the +backend via gRPC `SetSecretRequest.store` (`SECRET_STORE_MEMORY` / +`SECRET_STORE_KEYCHAIN`) or HTTP `store: "memory" | "keychain"` (default +keychain). The same key name lives in exactly one backend: writing to one +deletes that key from the other (move-on-write). Memory secrets survive +until consumer delete/set or daemon restart — no TTL and no clear-on- +disconnect. `SECRET_STORE_ENV` is rejected on write; env credentials remain +read-only via provider `api_key_env_var_name`. Configure / `addProvider` +continue to write keychain only. `api_key_keychain_name` remains a logical +lookup name into the composite store (not “must be OS keychain”). +**Rationale:** Ephemeral keys for clients that must not persist credentials +were already sketched (`MemorySecretStore`, proto `SECRET_STORE_MEMORY`) but +unused by the daemon. Mutual exclusivity avoids overlay/sync/refresh bugs. +Defaulting unspecified store to keychain preserves existing callers. diff --git a/packages/daemon/src/core/secrets.ts b/packages/daemon/src/core/secrets.ts index fcacb488..a91e6b19 100644 --- a/packages/daemon/src/core/secrets.ts +++ b/packages/daemon/src/core/secrets.ts @@ -2,7 +2,8 @@ * Secret store interface and in-memory implementation. * * Core consumers inject their own SecretStore implementation. - * The daemon uses KeychainSecretStore (keytar); tests use MemorySecretStore. + * The daemon uses DualSecretStore (MemorySecretStore + KeychainSecretStore); + * tests/library use MemorySecretStore. * * Credential aggregation (finding A1): one daemon may hold many provider keys. * Mutating APIs must stay auth-gated; use {@link auditSecretChange} so operators @@ -31,7 +32,7 @@ export interface SecretAuditEvent { /** Secret key name only — never the value */ key: string; op: 'set' | 'delete'; - /** http-secrets | grpc-secrets | http-configure | grpc-configure | core-add */ + /** http-secrets | http-secrets-memory | grpc-secrets | grpc-secrets-memory | http-configure | grpc-configure | core-add */ source: string; actor?: string; } @@ -39,6 +40,8 @@ export interface SecretAuditEvent { /** * Emit an audit log line for a secret mutation (A1 accountability). * Never logs the secret value. + * Sources include: http-secrets | http-secrets-memory | grpc-secrets | + * grpc-secrets-memory | http-configure | grpc-configure | core-add */ export function auditSecretChange(event: SecretAuditEvent): void { const safeKey = sanitizeForLog(event.key); diff --git a/packages/daemon/src/daemon/secrets/dual.test.ts b/packages/daemon/src/daemon/secrets/dual.test.ts new file mode 100644 index 00000000..b714522b --- /dev/null +++ b/packages/daemon/src/daemon/secrets/dual.test.ts @@ -0,0 +1,133 @@ +/** + * Unit tests for DualSecretStore (memory + keychain, move-on-write). + */ + +import { describe, it, expect } from 'vitest'; +import { MemorySecretStore, type SecretStore } from '../../core/secrets.js'; +import { + DualSecretStore, + parseSecretStoreChoice, + secretBackendToProto, +} from './dual.js'; + +function createDual() { + const memory = new MemorySecretStore(); + const keychain = new MemorySecretStore(); // stand-in for keychain in unit tests + const dual = new DualSecretStore(memory, keychain); + return { dual, memory, keychain }; +} + +describe('DualSecretStore', () => { + it('set defaults to keychain and clears memory for the same key', async () => { + const { dual, memory, keychain } = createDual(); + await memory.set('K', 'from-memory'); + await dual.set('K', 'from-keychain'); + + expect(await dual.get('K')).toBe('from-keychain'); + expect(await keychain.has('K')).toBe(true); + expect(await memory.has('K')).toBe(false); + expect(await dual.locate('K')).toBe('keychain'); + }); + + it('setIn memory moves the key out of keychain', async () => { + const { dual, memory, keychain } = createDual(); + await dual.setIn('keychain', 'K', 'persistent'); + await dual.setIn('memory', 'K', 'ephemeral'); + + expect(await dual.get('K')).toBe('ephemeral'); + expect(await memory.get('K')).toBe('ephemeral'); + expect(await keychain.has('K')).toBe(false); + expect(await dual.locate('K')).toBe('memory'); + }); + + it('get prefers memory when both somehow hold a value', async () => { + const { dual, memory, keychain } = createDual(); + // Bypass setIn to simulate inconsistent state + await memory.set('K', 'mem'); + await keychain.set('K', 'kc'); + expect(await dual.get('K')).toBe('mem'); + }); + + it('delete clears both backends', async () => { + const { dual, memory, keychain } = createDual(); + await memory.set('A', '1'); + await keychain.set('B', '2'); + expect(await dual.delete('A')).toBe(true); + expect(await dual.delete('B')).toBe(true); + expect(await dual.delete('missing')).toBe(false); + expect(await memory.has('A')).toBe(false); + expect(await keychain.has('B')).toBe(false); + }); + + it('has and locate reflect the active backend', async () => { + const { dual } = createDual(); + expect(await dual.has('K')).toBe(false); + expect(await dual.locate('K')).toBeNull(); + + await dual.setIn('memory', 'K', 'v'); + expect(await dual.has('K')).toBe(true); + expect(await dual.locate('K')).toBe('memory'); + + await dual.setIn('keychain', 'K', 'v2'); + expect(await dual.locate('K')).toBe('keychain'); + }); + + it('fails closed when the other backend still has the key after delete', async () => { + const sticky = new Map([['K', 'old-persistent']]); + const memory = new MemorySecretStore(); + const stickyKeychain: SecretStore = { + async get(key) { + return sticky.get(key) ?? null; + }, + async set(key, value) { + sticky.set(key, value); + }, + async delete() { + return false; // soft-fail like KeychainSecretStore on error + }, + async has(key) { + return sticky.has(key); + }, + }; + const dual = new DualSecretStore(memory, stickyKeychain); + + await expect(dual.setIn('memory', 'K', 'ephemeral')).rejects.toThrow(/Failed to clear/); + expect(await memory.has('K')).toBe(false); + expect(await stickyKeychain.has('K')).toBe(true); + }); +}); + +describe('parseSecretStoreChoice', () => { + it('defaults unspecified / keychain to keychain', () => { + for (const store of [undefined, null, '', 0, 'SECRET_STORE_UNSPECIFIED', 'keychain', 1]) { + expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'keychain' }); + } + }); + + it('accepts memory', () => { + for (const store of ['memory', 'SECRET_STORE_MEMORY', 3]) { + expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'memory' }); + } + }); + + it('rejects ENV writes', () => { + const result = parseSecretStoreChoice('SECRET_STORE_ENV'); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toMatch(/ENV/i); + } + }); + + it('rejects unknown stores', () => { + const result = parseSecretStoreChoice('vault'); + expect(result.ok).toBe(false); + }); +}); + +describe('secretBackendToProto', () => { + it('maps backends to proto enum numbers', () => { + expect(secretBackendToProto('keychain')).toBe(1); + expect(secretBackendToProto('memory')).toBe(3); + expect(secretBackendToProto(null)).toBe(0); + }); +}); diff --git a/packages/daemon/src/daemon/secrets/dual.ts b/packages/daemon/src/daemon/secrets/dual.ts new file mode 100644 index 00000000..2b787bec --- /dev/null +++ b/packages/daemon/src/daemon/secrets/dual.ts @@ -0,0 +1,153 @@ +/** + * Dual secret store: process-lifetime memory + OS keychain backends. + * + * Same key name lives in exactly one backend (move-on-write). Default + * {@link SecretStore.set} targets keychain for backward compatibility. + */ + +import type { SecretStore } from '../../core/secrets.js'; + +/** Writable secret backends (ENV is not a write target). */ +export type SecretBackend = 'memory' | 'keychain'; + +/** + * Composite store used by the daemon. + * + * - `set` → keychain (existing configure / addProvider callers) + * - `setIn('memory' | 'keychain', …)` → write target + delete from the other + * - `get` / `has` → memory first, then keychain (at most one hit) + * - `delete` → both backends + * - `locate` → which backend holds the key (for List / SecretInfo) + */ +export class DualSecretStore implements SecretStore { + constructor( + private readonly memory: SecretStore, + private readonly keychain: SecretStore, + ) {} + + /** Expose backends for tests that assert exclusivity. */ + get memoryStore(): SecretStore { + return this.memory; + } + + get keychainStore(): SecretStore { + return this.keychain; + } + + async get(key: string): Promise { + const fromMemory = await this.memory.get(key); + if (fromMemory !== null) return fromMemory; + return this.keychain.get(key); + } + + /** Default write path: keychain (persistent). */ + async set(key: string, value: string): Promise { + await this.setIn('keychain', key, value); + } + + /** + * Write to one backend and remove the same key from the other + * (mutual exclusivity — no overlay / sync). + * + * Fails closed if the other backend still holds the key after delete + * (e.g. keychain soft-fail), so callers cannot believe a memory write + * is ephemeral while an OS keychain residue remains. + */ + async setIn(backend: SecretBackend, key: string, value: string): Promise { + const primary = backend === 'memory' ? this.memory : this.keychain; + const other = backend === 'memory' ? this.keychain : this.memory; + const otherName = backend === 'memory' ? 'keychain' : 'memory'; + + await primary.set(key, value); + + try { + await other.delete(key); + } catch (error: unknown) { + // Roll back primary so we do not leave a dual-resident key. + try { + await primary.delete(key); + } catch { + /* ignore rollback errors */ + } + const msg = error instanceof Error ? error.message : String(error); + throw new Error( + `Failed to clear secret '${key}' from ${otherName} after write to ${backend}: ${msg}`, + ); + } + + if (await other.has(key)) { + try { + await primary.delete(key); + } catch { + /* ignore rollback errors */ + } + throw new Error( + `Failed to clear secret '${key}' from ${otherName} after write to ${backend}`, + ); + } + } + + async delete(key: string): Promise { + const fromMemory = await this.memory.delete(key); + const fromKeychain = await this.keychain.delete(key); + return fromMemory || fromKeychain; + } + + async has(key: string): Promise { + if (await this.memory.has(key)) return true; + return this.keychain.has(key); + } + + /** Which backend currently holds the key, if any. */ + async locate(key: string): Promise { + if (await this.memory.has(key)) return 'memory'; + if (await this.keychain.has(key)) return 'keychain'; + return null; + } +} + +export function isDualSecretStore(store: SecretStore): store is DualSecretStore { + return store instanceof DualSecretStore; +} + +/** + * Parse SetSecret / HTTP `store` field. + * Unspecified / omitted / keychain → keychain (default). + * ENV is rejected (env refs stay config-only). + */ +export function parseSecretStoreChoice( + store: unknown, +): { ok: true; backend: SecretBackend } | { ok: false; error: string } { + if ( + store === undefined || + store === null || + store === '' || + store === 0 || + store === '0' || + store === 'SECRET_STORE_UNSPECIFIED' || + store === 'keychain' || + store === 'SECRET_STORE_KEYCHAIN' || + store === 1 || + store === '1' + ) { + return { ok: true, backend: 'keychain' }; + } + if (store === 'memory' || store === 'SECRET_STORE_MEMORY' || store === 3 || store === '3') { + return { ok: true, backend: 'memory' }; + } + if (store === 'env' || store === 'SECRET_STORE_ENV' || store === 2 || store === '2') { + return { + ok: false, + error: + 'SECRET_STORE_ENV is not writable via SetSecret; use api_key_env_var_name in provider config', + }; + } + return { ok: false, error: `Unsupported secret store: ${String(store)}` }; +} + +/** Proto SecretStore enum numeric values for ListSecrets / SecretInfo. */ +export function secretBackendToProto(backend: SecretBackend | null): number { + if (backend === 'memory') return 3; // SECRET_STORE_MEMORY + if (backend === 'keychain') return 1; // SECRET_STORE_KEYCHAIN + return 0; // SECRET_STORE_UNSPECIFIED +} diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index 0afa6cc9..847bd2ce 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -25,6 +25,11 @@ import { type ConfigFile, type ProviderConfig as DaemonProviderConfig, type McpServerConfig, } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; +import { + isDualSecretStore, + parseSecretStoreChoice, + secretBackendToProto, +} from '../secrets/dual.js'; import { auditProviderEndpointChange, auditProviderEndpointConfigDiff, @@ -154,6 +159,8 @@ interface GetSecretRequestProto { interface SetSecretRequestProto { key: string; value: string; + /** Proto SecretStore enum: number or string name depending on codec. */ + store?: number | string; } interface DeleteSecretRequestProto { @@ -807,10 +814,26 @@ export function createAbbenayService( callback: grpc.sendUnaryData ): void { if (!requireCapability(call, 'secrets', authContext, callback)) return; - const { key, value } = call.request; - - state.secretStore.set(key, value).then(() => { - auditSecretChange({ key, op: 'set', source: 'grpc-secrets' }); + const { key, value, store } = call.request; + + const parsed = parseSecretStoreChoice(store); + if (!parsed.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: parsed.error, + }); + return; + } + + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + const write = dual + ? dual.setIn(parsed.backend, key, value) + : state.secretStore.set(key, value); + const auditSource = + parsed.backend === 'memory' ? 'grpc-secrets-memory' : 'grpc-secrets'; + + write.then(() => { + auditSecretChange({ key, op: 'set', source: auditSource }); callback(null, {}); // Notify VS Code that models may have changed (new API key) state.notifyModelsChanged('secret_updated'); @@ -851,10 +874,17 @@ export function createAbbenayService( if (!requireCapability(call, 'secrets', authContext, callback)) return; // Return known key names with availability status const engines = getEngines(); + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; const checks = engines.filter(e => e.requiresKey).map(async (e) => { const key = e.defaultEnvVar || `${e.id.toUpperCase()}_API_KEY`; const hasValue = await state.secretStore.has(key); - return { key, engine: e.id, has_value: hasValue }; + const backend = dual && hasValue ? await dual.locate(key) : null; + return { + key, + engine: e.id, + has_value: hasValue, + store: secretBackendToProto(backend), + }; }); Promise.all(checks).then((secrets) => { diff --git a/packages/daemon/src/daemon/state.ts b/packages/daemon/src/daemon/state.ts index b369bd18..a48ca009 100644 --- a/packages/daemon/src/daemon/state.ts +++ b/packages/daemon/src/daemon/state.ts @@ -9,6 +9,8 @@ import { v4 as uuidv4 } from 'uuid'; import { CoreState, type ChatToolOptions } from '../core/state.js'; import type { ChatChunk, ChatParams, ToolExecutor } from '../core/engines.js'; import type { PolicyConfig } from '../core/policies.js'; +import { MemorySecretStore } from '../core/secrets.js'; +import { DualSecretStore } from './secrets/dual.js'; import { KeychainSecretStore } from './secrets/keychain.js'; import { ToolRegistry } from '../core/tool-registry.js'; import { ToolRouter } from './tool-router.js'; @@ -82,7 +84,9 @@ export class DaemonState extends CoreState { public readonly sessionStore: SessionStore; constructor() { - super({ secretStore: new KeychainSecretStore() }); + super({ + secretStore: new DualSecretStore(new MemorySecretStore(), new KeychainSecretStore()), + }); // Initialize tool registry, router, MCP client pool, and MCP server this.toolRegistry = new ToolRegistry(); diff --git a/packages/daemon/src/daemon/web/api-schemas.test.ts b/packages/daemon/src/daemon/web/api-schemas.test.ts index efda9a20..a24ae540 100644 --- a/packages/daemon/src/daemon/web/api-schemas.test.ts +++ b/packages/daemon/src/daemon/web/api-schemas.test.ts @@ -124,6 +124,21 @@ describe('secret body schemas', () => { expect(PostSecretByKeyBodySchema.safeParse({ value: 'secret' }).success).toBe(true); expect(PostSecretByKeyBodySchema.safeParse({ value: '' }).success).toBe(false); }); + + it('accepts optional store memory|keychain|env', () => { + expect( + PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'memory' }).success, + ).toBe(true); + expect( + PostSecretByKeyBodySchema.safeParse({ value: 'v', store: 'keychain' }).success, + ).toBe(true); + expect( + PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'env' }).success, + ).toBe(true); + expect( + PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'vault' }).success, + ).toBe(false); + }); }); describe('MCP decision schemas', () => { diff --git a/packages/daemon/src/daemon/web/api-schemas.ts b/packages/daemon/src/daemon/web/api-schemas.ts index 40a78993..5b78a949 100644 --- a/packages/daemon/src/daemon/web/api-schemas.ts +++ b/packages/daemon/src/daemon/web/api-schemas.ts @@ -42,9 +42,13 @@ export const PostConfigBodySchema = z // ── Secrets ───────────────────────────────────────────────────────────── +const SecretStoreFieldSchema = z.enum(['memory', 'keychain', 'env']).optional(); + export const PostSecretByKeyBodySchema = z .object({ value: z.string().min(1), + /** Default: keychain (persistent). memory = process-lifetime only. */ + store: SecretStoreFieldSchema, }) .strict(); @@ -52,6 +56,8 @@ export const PostSecretBodySchema = z .object({ key: z.string().min(1), value: z.string().min(1), + /** Default: keychain (persistent). memory = process-lifetime only. */ + store: SecretStoreFieldSchema, }) .strict(); diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 5e5edeed..093b4f02 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -18,6 +18,7 @@ import { fileURLToPath } from 'node:url'; import { getDefaultSocketPath } from '../transport.js'; import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, type ConfigFile, type ProviderConfig } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; +import { isDualSecretStore, parseSecretStoreChoice } from '../secrets/dual.js'; import { auditProviderEndpointChange, auditProviderEndpointConfigDiff, @@ -1023,11 +1024,18 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): app.get('/api/secrets', async (req, res) => { try { const engines = getEngines(); + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; const secrets = await Promise.all( engines.filter(e => e.requiresKey).map(async (e) => { const key = e.defaultEnvVar || `${e.id.toUpperCase()}_API_KEY`; const hasValue = await state.secretStore.has(key); - return { key, engine: e.id, hasValue }; + const store = dual && hasValue ? await dual.locate(key) : null; + return { + key, + engine: e.id, + hasValue, + ...(store ? { store } : {}), + }; }) ); res.json({ secrets }); @@ -1040,7 +1048,7 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): /** * POST /api/secrets/:key - Set a specific secret (API key) - * Body: { value: string } + * Body: { value: string, store?: "memory" | "keychain" } */ app.post('/api/secrets/:key', async (req, res) => { try { @@ -1050,9 +1058,21 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - await state.secretStore.set(key, parsed.data.value); - auditSecretChange({ key, op: 'set', source: 'http-secrets' }); - res.json({ success: true }); + const storeChoice = parseSecretStoreChoice(parsed.data.store ?? 'keychain'); + if (!storeChoice.ok) { + sendBadRequest(res, storeChoice.error); + return; + } + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + if (dual) { + await dual.setIn(storeChoice.backend, key, parsed.data.value); + } else { + await state.secretStore.set(key, parsed.data.value); + } + const auditSource = + storeChoice.backend === 'memory' ? 'http-secrets-memory' : 'http-secrets'; + auditSecretChange({ key, op: 'set', source: auditSource }); + res.json({ success: true, store: storeChoice.backend }); state.notifyModelsChanged('secret_updated'); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); @@ -1060,10 +1080,10 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): res.status(500).json({ error: msg }); } }); - + /** * POST /api/secrets - Set a secret (API key) — legacy route - * Body: { key: string, value: string } + * Body: { key: string, value: string, store?: "memory" | "keychain" } */ app.post('/api/secrets', async (req, res) => { try { @@ -1072,9 +1092,21 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - await state.secretStore.set(parsed.data.key, parsed.data.value); - auditSecretChange({ key: parsed.data.key, op: 'set', source: 'http-secrets' }); - res.json({ success: true }); + const storeChoice = parseSecretStoreChoice(parsed.data.store ?? 'keychain'); + if (!storeChoice.ok) { + sendBadRequest(res, storeChoice.error); + return; + } + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + if (dual) { + await dual.setIn(storeChoice.backend, parsed.data.key, parsed.data.value); + } else { + await state.secretStore.set(parsed.data.key, parsed.data.value); + } + const auditSource = + storeChoice.backend === 'memory' ? 'http-secrets-memory' : 'http-secrets'; + auditSecretChange({ key: parsed.data.key, op: 'set', source: auditSource }); + res.json({ success: true, store: storeChoice.backend }); state.notifyModelsChanged('secret_updated'); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); diff --git a/packages/daemon/tests/integration/grpc-real-service.test.ts b/packages/daemon/tests/integration/grpc-real-service.test.ts index 871608c8..ce481cc5 100644 --- a/packages/daemon/tests/integration/grpc-real-service.test.ts +++ b/packages/daemon/tests/integration/grpc-real-service.test.ts @@ -282,6 +282,47 @@ describe('Real gRPC service: Secrets', () => { expect(res.secrets).toBeDefined(); expect(Array.isArray(res.secrets)).toBe(true); }); + + it('should store SECRET_STORE_MEMORY without writing keychain backend', async () => { + await callUnary(client, 'SetSecret', { + key: 'MEM_ONLY', + value: 'ephemeral-value', + store: 'SECRET_STORE_MEMORY', + }); + const got = await callUnary(client, 'GetSecret', { key: 'MEM_ONLY' }); + expect(got.value).toBe('ephemeral-value'); + // DaemonState uses DualSecretStore; mocked KeychainSecretStore is the keychain half. + // Memory-only writes must not land in the keychain Map. + expect(mockSecretStoreData.has('MEM_ONLY')).toBe(false); + }); + + it('should move a key from keychain to memory on SetSecret MEMORY', async () => { + await callUnary(client, 'SetSecret', { + key: 'MOVE_KEY', + value: 'persistent', + store: 'SECRET_STORE_KEYCHAIN', + }); + expect(mockSecretStoreData.get('MOVE_KEY')).toBe('persistent'); + + await callUnary(client, 'SetSecret', { + key: 'MOVE_KEY', + value: 'ephemeral', + store: 'SECRET_STORE_MEMORY', + }); + expect(mockSecretStoreData.has('MOVE_KEY')).toBe(false); + const got = await callUnary(client, 'GetSecret', { key: 'MOVE_KEY' }); + expect(got.value).toBe('ephemeral'); + }); + + it('should reject SECRET_STORE_ENV on SetSecret', async () => { + await expect( + callUnary(client, 'SetSecret', { + key: 'ENV_KEY', + value: 'nope', + store: 'SECRET_STORE_ENV', + }), + ).rejects.toMatchObject({ code: grpc.status.INVALID_ARGUMENT }); + }); }); describe('Real gRPC service: Chat streaming', () => { diff --git a/packages/daemon/tests/integration/web-sse.test.ts b/packages/daemon/tests/integration/web-sse.test.ts index 91e40f69..abde1a05 100644 --- a/packages/daemon/tests/integration/web-sse.test.ts +++ b/packages/daemon/tests/integration/web-sse.test.ts @@ -476,6 +476,26 @@ describe('Web API - Secrets Endpoints', () => { expect(body.success).toBe(true); }); + it('POST /api/secrets/:key should accept store=memory', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets/MEM_KEY`, { + value: 'ephemeral', + store: 'memory', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + expect(body.store).toBe('memory'); + }); + + it('POST /api/secrets should reject store=env', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets`, { + key: 'ENV_KEY', + value: 'nope', + store: 'env', + }); + expect(statusCode).toBe(400); + expect(body.error).toMatch(/ENV/i); + }); + it('POST /api/secrets/:key should reject missing value', async () => { const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets/TEST_KEY`, {}); expect(statusCode).toBe(400); From 3849ce7b89280955994da5a834c4bb3f5b21e45e Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 08:58:34 -0700 Subject: [PATCH 02/18] feat(daemon): let ConfigureProvider pick a named secret Add api_key_keychain_name so providers reference an existing SetSecret key (N:1). Raw api_key alone keeps the legacy invent-name shortcut. --- docs/CONFIGURATION.md | 13 + docs/decisions.md | 7 +- .../src/daemon/server/abbenay-service.ts | 35 +- .../daemon/src/daemon/web/api-schemas.test.ts | 19 ++ packages/daemon/src/daemon/web/api-schemas.ts | 16 + packages/daemon/src/daemon/web/server.ts | 17 +- .../tests/integration/consumer-auth.test.ts | 48 +++ packages/proto-ts/src/abbenay/v1/service.ts | 145 +++++++- .../abbenay_grpc/abbenay/v1/service_pb2.py | 318 +++++++++--------- .../abbenay_grpc/abbenay/v1/service_pb2.pyi | 20 +- .../vscode/src/proto/abbenay/v1/service.ts | 145 +++++++- proto/abbenay/v1/service.proto | 6 +- 12 files changed, 613 insertions(+), 176 deletions(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 7ec5c93f..d4b89f40 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -410,6 +410,19 @@ providers: compatibility - `SECRET_STORE_ENV` / `"store": "env"` is **not** writable via secrets APIs +### Recommended workflow (keys are N:1 with providers) + +Secrets and providers are separate. Many providers may share one named key. + +1. **Add a secret by name** — `SetSecret` / `POST /api/secrets` (optionally + `store=memory`). +2. **Configure the provider** — `ConfigureProvider` / `POST /api/provider/:id/configure` + with `api_key_keychain_name` / `apiKeyKeychainName` pointing at that name + (no value). The secret must already exist. +3. Optionally pass raw `api_key` **with** `api_key_keychain_name` to store the + value under an explicit name in one step. Raw `api_key` alone still invents + `${PROVIDER_ID}_API_KEY` (legacy 1:1 shortcut). + ### Option 2: Environment Variable (`api_key_env_var_name`) - Key read from environment variable at runtime diff --git a/docs/decisions.md b/docs/decisions.md index 0affbce5..1c70676e 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -845,7 +845,12 @@ disconnect. `SECRET_STORE_ENV` is rejected on write; env credentials remain read-only via provider `api_key_env_var_name`. Configure / `addProvider` continue to write keychain only. `api_key_keychain_name` remains a logical lookup name into the composite store (not “must be OS keychain”). +`ConfigureProvider` / HTTP configure accept `api_key_keychain_name` to +reference an existing named secret (N providers → 1 key). Raw `api_key` +alone remains a legacy shortcut that invents `${PROVIDER_ID}_API_KEY`. **Rationale:** Ephemeral keys for clients that must not persist credentials were already sketched (`MemorySecretStore`, proto `SECRET_STORE_MEMORY`) but unused by the daemon. Mutual exclusivity avoids overlay/sync/refresh bugs. -Defaulting unspecified store to keychain preserves existing callers. +Defaulting unspecified store to keychain preserves existing callers. Keys are +not 1:1 with providers — configure should pick a secret by name after +`SetSecret`, not invent a private key name per provider. diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index 847bd2ce..a847b156 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -322,6 +322,8 @@ interface ConfigureProviderRequestProto { target?: string; workspace_path?: string; workspacePath?: string; + api_key_keychain_name?: string; + apiKeyKeychainName?: string; } interface RemoveProviderRequestProto { @@ -1708,6 +1710,8 @@ export function createAbbenayService( const engine = call.request.engine; const apiKey = call.request.api_key || call.request.apiKey; const envVarName = call.request.env_var_name || call.request.envVarName; + const keychainNameRef = + call.request.api_key_keychain_name || call.request.apiKeyKeychainName; const baseUrl = call.request.base_url || call.request.baseUrl; const target = call.request.target || 'user'; const workspacePath = call.request.workspace_path || call.request.workspacePath; @@ -1758,12 +1762,41 @@ export function createAbbenayService( config.providers[providerId] = existing as DaemonProviderConfig; + if (apiKey && envVarName) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: 'Provide only one of api_key or env_var_name', + }); + return; + } + if (keychainNameRef && envVarName) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: 'Provide only one of api_key_keychain_name or env_var_name', + }); + return; + } + if (apiKey) { - const keychainName = `${providerId.toUpperCase()}_API_KEY`; + // Explicit name, or legacy invent from provider id (1:1 shortcut). + const keychainName = keychainNameRef || `${providerId.toUpperCase()}_API_KEY`; await state.secretStore.set(keychainName, apiKey); auditSecretChange({ key: keychainName, op: 'set', source: 'grpc-configure' }); config.providers[providerId].api_key_keychain_name = keychainName; delete config.providers[providerId].api_key_env_var_name; + } else if (keychainNameRef) { + // Reference an existing named secret (N:1 — many providers, one key). + const exists = await state.secretStore.has(keychainNameRef); + if (!exists) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: + `Secret "${keychainNameRef}" not found; SetSecret first or pass api_key`, + }); + return; + } + config.providers[providerId].api_key_keychain_name = keychainNameRef; + delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { config.providers[providerId].api_key_env_var_name = envVarName; delete config.providers[providerId].api_key_keychain_name; diff --git a/packages/daemon/src/daemon/web/api-schemas.test.ts b/packages/daemon/src/daemon/web/api-schemas.test.ts index a24ae540..d028a221 100644 --- a/packages/daemon/src/daemon/web/api-schemas.test.ts +++ b/packages/daemon/src/daemon/web/api-schemas.test.ts @@ -64,6 +64,25 @@ describe('PostProviderConfigureBodySchema', () => { }); expect(result.success).toBe(true); }); + + it('accepts apiKeyKeychainName to pick an existing secret', () => { + expect( + PostProviderConfigureBodySchema.safeParse({ + engine: 'openai', + apiKeyKeychainName: 'SHARED_OPENAI', + }).success, + ).toBe(true); + }); + + it('rejects apiKeyKeychainName together with envVarName', () => { + expect( + PostProviderConfigureBodySchema.safeParse({ + engine: 'openai', + apiKeyKeychainName: 'SHARED', + envVarName: 'OPENAI_API_KEY', + }).success, + ).toBe(false); + }); }); describe('PostPolicyBodySchema', () => { diff --git a/packages/daemon/src/daemon/web/api-schemas.ts b/packages/daemon/src/daemon/web/api-schemas.ts index 5b78a949..414158e0 100644 --- a/packages/daemon/src/daemon/web/api-schemas.ts +++ b/packages/daemon/src/daemon/web/api-schemas.ts @@ -108,6 +108,8 @@ export const PostProviderConfigureBodySchema = z .object({ engine: z.string().min(1).optional(), apiKey: z.string().min(1).optional(), + /** Logical secret name (SetSecret key). Prefer over inventing from provider id. */ + apiKeyKeychainName: z.string().min(1).optional(), envVarName: z.string().min(1).optional(), /** Format-checked here; host policy applied in the route with server config. */ baseUrl: ProviderBaseUrlSchema.optional(), @@ -123,6 +125,20 @@ export const PostProviderConfigureBodySchema = z path: ['workspacePath'], }); } + if (data.apiKey && data.envVarName) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Provide only one of apiKey or envVarName', + path: ['apiKey'], + }); + } + if (data.apiKeyKeychainName && data.envVarName) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: 'Provide only one of apiKeyKeychainName or envVarName', + path: ['apiKeyKeychainName'], + }); + } }); // ── Policies ──────────────────────────────────────────────────────────── diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 093b4f02..567d4ef6 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -1360,7 +1360,8 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - const { engine, apiKey, envVarName, baseUrl, target, workspacePath } = parsed.data; + const { engine, apiKey, apiKeyKeychainName, envVarName, baseUrl, target, workspacePath } = + parsed.data; let resolvedWorkspace: string | undefined; if (target === 'workspace' && workspacePath) { @@ -1411,11 +1412,23 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): config.providers[providerId] = existing as ProviderConfig; if (apiKey) { - const keychainName = `${providerId.toUpperCase()}_API_KEY`; + // Explicit name, or legacy invent from provider id (1:1 shortcut). + const keychainName = apiKeyKeychainName || `${providerId.toUpperCase()}_API_KEY`; await state.secretStore.set(keychainName, apiKey); auditSecretChange({ key: keychainName, op: 'set', source: 'http-configure' }); config.providers[providerId].api_key_keychain_name = keychainName; delete config.providers[providerId].api_key_env_var_name; + } else if (apiKeyKeychainName) { + // Reference an existing named secret (N:1 — many providers, one key). + const exists = await state.secretStore.has(apiKeyKeychainName); + if (!exists) { + res.status(400).json({ + error: `Secret "${apiKeyKeychainName}" not found; POST /api/secrets first or pass apiKey`, + }); + return; + } + config.providers[providerId].api_key_keychain_name = apiKeyKeychainName; + delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { config.providers[providerId].api_key_env_var_name = envVarName; delete config.providers[providerId].api_key_keychain_name; diff --git a/packages/daemon/tests/integration/consumer-auth.test.ts b/packages/daemon/tests/integration/consumer-auth.test.ts index a96b2d1d..5394c36e 100644 --- a/packages/daemon/tests/integration/consumer-auth.test.ts +++ b/packages/daemon/tests/integration/consumer-auth.test.ts @@ -270,6 +270,54 @@ describe('Consumer auth RPC gating', () => { expect(res.success).toBe(true); }); + it('ConfigureProvider references an existing named secret (N:1)', async () => { + await callUnary(client, 'SetSecret', { + key: 'SHARED_OPENAI', + value: 'sk-shared', + store: 'SECRET_STORE_MEMORY', + }, GOOD_TOKEN); + + const res = await callUnary(client, 'ConfigureProvider', { + provider_id: 'work-openai', + engine: 'mock', + api_key_keychain_name: 'SHARED_OPENAI', + }, GOOD_TOKEN); + expect(res.success).toBe(true); + + const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { + providers: { 'work-openai': { api_key_keychain_name?: string } }; + }; + expect(saved.providers['work-openai'].api_key_keychain_name).toBe('SHARED_OPENAI'); + // Reference path must not invent a provider-scoped key name or rewrite the secret. + expect(mockSecretStoreData.has('WORK-OPENAI_API_KEY')).toBe(false); + }); + + it('ConfigureProvider rejects missing api_key_keychain_name', async () => { + await expect( + callUnary(client, 'ConfigureProvider', { + provider_id: 'missing-key-provider', + engine: 'mock', + api_key_keychain_name: 'DOES_NOT_EXIST', + }, GOOD_TOKEN), + ).rejects.toMatchObject({ code: grpc.status.INVALID_ARGUMENT }); + }); + + it('ConfigureProvider stores api_key under an explicit keychain name', async () => { + const res = await callUnary(client, 'ConfigureProvider', { + provider_id: 'named-write', + engine: 'mock', + api_key: 'sk-explicit', + api_key_keychain_name: 'MY_EXPLICIT_KEY', + }, GOOD_TOKEN); + expect(res.success).toBe(true); + expect(mockSecretStoreData.get('MY_EXPLICIT_KEY')).toBe('sk-explicit'); + + const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { + providers: { 'named-write': { api_key_keychain_name?: string } }; + }; + expect(saved.providers['named-write'].api_key_keychain_name).toBe('MY_EXPLICIT_KEY'); + }); + it('denies Shutdown without shutdown capability', async () => { await expectPermissionDenied(callUnary(client, 'Shutdown', {}, 'chat-only')); }); diff --git a/packages/proto-ts/src/abbenay/v1/service.ts b/packages/proto-ts/src/abbenay/v1/service.ts index 44944e10..8f15baa8 100644 --- a/packages/proto-ts/src/abbenay/v1/service.ts +++ b/packages/proto-ts/src/abbenay/v1/service.ts @@ -1189,7 +1189,27 @@ export interface ConsumerCapabilitiesMsg { | boolean | undefined; /** Allow dynamic MCP server registration */ - mcpRegister?: boolean | undefined; + mcpRegister?: + | boolean + | undefined; + /** Allow secret read/write/list RPCs */ + secrets?: + | boolean + | undefined; + /** Allow GetConfig / UpdateConfig / policy / web control */ + config?: + | boolean + | undefined; + /** Allow ConfigureProvider / RemoveProvider / DiscoverModels */ + providers?: + | boolean + | undefined; + /** Allow Shutdown RPC */ + shutdown?: + | boolean + | undefined; + /** Allow Chat / SessionChat */ + chat?: boolean | undefined; } export interface UpdateConfigRequest { @@ -1207,7 +1227,7 @@ export interface ConfigureProviderRequest { engine?: | string | undefined; - /** Raw API key (daemon stores in keychain) */ + /** Raw API key value (optional with api_key_keychain_name) */ apiKey?: | string | undefined; @@ -1224,7 +1244,15 @@ export interface ConfigureProviderRequest { | string | undefined; /** Required if target is "workspace" */ - workspacePath?: string | undefined; + workspacePath?: + | string + | undefined; + /** + * Logical secret name (SetSecret key). Prefer this over inventing a name from + * provider_id. With api_key: store the value under this name. Without api_key: + * reference an existing secret (N providers may share one key). + */ + apiKeyKeychainName?: string | undefined; } export interface ConfigureProviderResponse { @@ -12059,7 +12087,15 @@ export const ConsumerConfigMsg: MessageFns = { }; function createBaseConsumerCapabilitiesMsg(): ConsumerCapabilitiesMsg { - return { inlinePolicy: undefined, mcpRegister: undefined }; + return { + inlinePolicy: undefined, + mcpRegister: undefined, + secrets: undefined, + config: undefined, + providers: undefined, + shutdown: undefined, + chat: undefined, + }; } export const ConsumerCapabilitiesMsg: MessageFns = { @@ -12070,6 +12106,21 @@ export const ConsumerCapabilitiesMsg: MessageFns = { if (message.mcpRegister !== undefined) { writer.uint32(16).bool(message.mcpRegister); } + if (message.secrets !== undefined) { + writer.uint32(24).bool(message.secrets); + } + if (message.config !== undefined) { + writer.uint32(32).bool(message.config); + } + if (message.providers !== undefined) { + writer.uint32(40).bool(message.providers); + } + if (message.shutdown !== undefined) { + writer.uint32(48).bool(message.shutdown); + } + if (message.chat !== undefined) { + writer.uint32(56).bool(message.chat); + } return writer; }, @@ -12096,6 +12147,46 @@ export const ConsumerCapabilitiesMsg: MessageFns = { message.mcpRegister = reader.bool(); continue; } + case 3: { + if (tag !== 24) { + break; + } + + message.secrets = reader.bool(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.config = reader.bool(); + continue; + } + case 5: { + if (tag !== 40) { + break; + } + + message.providers = reader.bool(); + continue; + } + case 6: { + if (tag !== 48) { + break; + } + + message.shutdown = reader.bool(); + continue; + } + case 7: { + if (tag !== 56) { + break; + } + + message.chat = reader.bool(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -12117,6 +12208,11 @@ export const ConsumerCapabilitiesMsg: MessageFns = { : isSet(object.mcp_register) ? globalThis.Boolean(object.mcp_register) : undefined, + secrets: isSet(object.secrets) ? globalThis.Boolean(object.secrets) : undefined, + config: isSet(object.config) ? globalThis.Boolean(object.config) : undefined, + providers: isSet(object.providers) ? globalThis.Boolean(object.providers) : undefined, + shutdown: isSet(object.shutdown) ? globalThis.Boolean(object.shutdown) : undefined, + chat: isSet(object.chat) ? globalThis.Boolean(object.chat) : undefined, }; }, @@ -12128,6 +12224,21 @@ export const ConsumerCapabilitiesMsg: MessageFns = { if (message.mcpRegister !== undefined) { obj.mcpRegister = message.mcpRegister; } + if (message.secrets !== undefined) { + obj.secrets = message.secrets; + } + if (message.config !== undefined) { + obj.config = message.config; + } + if (message.providers !== undefined) { + obj.providers = message.providers; + } + if (message.shutdown !== undefined) { + obj.shutdown = message.shutdown; + } + if (message.chat !== undefined) { + obj.chat = message.chat; + } return obj; }, @@ -12138,6 +12249,11 @@ export const ConsumerCapabilitiesMsg: MessageFns = { const message = createBaseConsumerCapabilitiesMsg(); message.inlinePolicy = object.inlinePolicy ?? undefined; message.mcpRegister = object.mcpRegister ?? undefined; + message.secrets = object.secrets ?? undefined; + message.config = object.config ?? undefined; + message.providers = object.providers ?? undefined; + message.shutdown = object.shutdown ?? undefined; + message.chat = object.chat ?? undefined; return message; }, }; @@ -12229,6 +12345,7 @@ function createBaseConfigureProviderRequest(): ConfigureProviderRequest { baseUrl: undefined, target: undefined, workspacePath: undefined, + apiKeyKeychainName: undefined, }; } @@ -12255,6 +12372,9 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { writer.uint32(58).string(message.workspacePath); } + if (message.apiKeyKeychainName !== undefined) { + writer.uint32(66).string(message.apiKeyKeychainName); + } return writer; }, @@ -12321,6 +12441,14 @@ export const ConfigureProviderRequest: MessageFns = { message.workspacePath = reader.string(); continue; } + case 8: { + if (tag !== 66) { + break; + } + + message.apiKeyKeychainName = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -12359,6 +12487,11 @@ export const ConfigureProviderRequest: MessageFns = { : isSet(object.workspace_path) ? globalThis.String(object.workspace_path) : undefined, + apiKeyKeychainName: isSet(object.apiKeyKeychainName) + ? globalThis.String(object.apiKeyKeychainName) + : isSet(object.api_key_keychain_name) + ? globalThis.String(object.api_key_keychain_name) + : undefined, }; }, @@ -12385,6 +12518,9 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { obj.workspacePath = message.workspacePath; } + if (message.apiKeyKeychainName !== undefined) { + obj.apiKeyKeychainName = message.apiKeyKeychainName; + } return obj; }, @@ -12400,6 +12536,7 @@ export const ConfigureProviderRequest: MessageFns = { message.baseUrl = object.baseUrl ?? undefined; message.target = object.target ?? undefined; message.workspacePath = object.workspacePath ?? undefined; + message.apiKeyKeychainName = object.apiKeyKeychainName ?? undefined; return message; }, }; diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py index be2efb7f..e556c26a 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xcb\x02\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_url\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"s\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_register\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x91\x02\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_path\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xcb\x02\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_url\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\xcf\x02\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\"\n\x15\x61pi_key_keychain_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x18\n\x16_api_key_keychain_name\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -57,20 +57,20 @@ _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_options = b'8\001' _globals['_MCPTRANSPORT_ENVENTRY']._loaded_options = None _globals['_MCPTRANSPORT_ENVENTRY']._serialized_options = b'8\001' - _globals['_ROLE']._serialized_start=18000 - _globals['_ROLE']._serialized_end=18095 - _globals['_CLIENTTYPE']._serialized_start=18098 - _globals['_CLIENTTYPE']._serialized_end=18253 - _globals['_REPLAYFORMAT']._serialized_start=18256 - _globals['_REPLAYFORMAT']._serialized_end=18386 - _globals['_MODELSOURCE']._serialized_start=18388 - _globals['_MODELSOURCE']._serialized_end=18484 - _globals['_PROVIDERTYPE']._serialized_start=18486 - _globals['_PROVIDERTYPE']._serialized_end=18603 - _globals['_LOGLEVEL']._serialized_start=18606 - _globals['_LOGLEVEL']._serialized_end=18746 - _globals['_SECRETSTORE']._serialized_start=18748 - _globals['_SECRETSTORE']._serialized_end=18865 + _globals['_ROLE']._serialized_start=18231 + _globals['_ROLE']._serialized_end=18326 + _globals['_CLIENTTYPE']._serialized_start=18329 + _globals['_CLIENTTYPE']._serialized_end=18484 + _globals['_REPLAYFORMAT']._serialized_start=18487 + _globals['_REPLAYFORMAT']._serialized_end=18617 + _globals['_MODELSOURCE']._serialized_start=18619 + _globals['_MODELSOURCE']._serialized_end=18715 + _globals['_PROVIDERTYPE']._serialized_start=18717 + _globals['_PROVIDERTYPE']._serialized_end=18834 + _globals['_LOGLEVEL']._serialized_start=18837 + _globals['_LOGLEVEL']._serialized_end=18977 + _globals['_SECRETSTORE']._serialized_start=18979 + _globals['_SECRETSTORE']._serialized_end=19096 _globals['_EMPTY']._serialized_start=40 _globals['_EMPTY']._serialized_end=47 _globals['_TIMESTAMP']._serialized_start=49 @@ -277,152 +277,152 @@ _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_end=10992 _globals['_CONSUMERCONFIGMSG']._serialized_start=11019 _globals['_CONSUMERCONFIGMSG']._serialized_end=11183 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11185 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11300 - _globals['_UPDATECONFIGREQUEST']._serialized_start=11302 - _globals['_UPDATECONFIGREQUEST']._serialized_end=11395 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11398 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=11671 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=11673 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=11717 - _globals['_REMOVEPROVIDERREQUEST']._serialized_start=11719 - _globals['_REMOVEPROVIDERREQUEST']._serialized_end=11843 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=11845 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=11874 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=11876 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=11955 - _globals['_PROVIDERTEMPLATE']._serialized_start=11958 - _globals['_PROVIDERTEMPLATE']._serialized_end=12090 - _globals['_GETKEYSTATUSREQUEST']._serialized_start=12092 - _globals['_GETKEYSTATUSREQUEST']._serialized_end=12143 - _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12145 - _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12183 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12185 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12214 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12216 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12301 - _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12304 - _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12440 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12442 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12488 - _globals['_CREATEPOLICYREQUEST']._serialized_start=12490 - _globals['_CREATEPOLICYREQUEST']._serialized_end=12567 - _globals['_DELETEPOLICYREQUEST']._serialized_start=12569 - _globals['_DELETEPOLICYREQUEST']._serialized_end=12604 - _globals['_GETSECRETREQUEST']._serialized_start=12606 - _globals['_GETSECRETREQUEST']._serialized_end=12637 - _globals['_GETSECRETRESPONSE']._serialized_start=12639 - _globals['_GETSECRETRESPONSE']._serialized_end=12673 - _globals['_SETSECRETREQUEST']._serialized_start=12675 - _globals['_SETSECRETREQUEST']._serialized_end=12761 - _globals['_DELETESECRETREQUEST']._serialized_start=12763 - _globals['_DELETESECRETREQUEST']._serialized_end=12797 - _globals['_LISTSECRETSREQUEST']._serialized_start=12799 - _globals['_LISTSECRETSREQUEST']._serialized_end=12819 - _globals['_LISTSECRETSRESPONSE']._serialized_start=12821 - _globals['_LISTSECRETSRESPONSE']._serialized_end=12883 - _globals['_SECRETINFO']._serialized_start=12885 - _globals['_SECRETINFO']._serialized_end=12969 - _globals['_REGISTERREQUEST']._serialized_start=12971 - _globals['_REGISTERREQUEST']._serialized_end=13097 - _globals['_REGISTERRESPONSE']._serialized_start=13099 - _globals['_REGISTERRESPONSE']._serialized_end=13163 - _globals['_UNREGISTERREQUEST']._serialized_start=13165 - _globals['_UNREGISTERREQUEST']._serialized_end=13203 - _globals['_GETSTATUSREQUEST']._serialized_start=13205 - _globals['_GETSTATUSREQUEST']._serialized_end=13223 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13225 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13256 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13258 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13310 - _globals['_DAEMONSTATUS']._serialized_start=13313 - _globals['_DAEMONSTATUS']._serialized_end=13517 - _globals['_CONNECTEDCLIENT']._serialized_start=13520 - _globals['_CONNECTEDCLIENT']._serialized_end=13690 - _globals['_SHUTDOWNREQUEST']._serialized_start=13692 - _globals['_SHUTDOWNREQUEST']._serialized_end=13754 - _globals['_HEALTHCHECKREQUEST']._serialized_start=13756 - _globals['_HEALTHCHECKREQUEST']._serialized_end=13776 - _globals['_HEALTHCHECKRESPONSE']._serialized_start=13778 - _globals['_HEALTHCHECKRESPONSE']._serialized_end=13833 - _globals['_STARTWEBSERVERREQUEST']._serialized_start=13835 - _globals['_STARTWEBSERVERREQUEST']._serialized_end=13872 - _globals['_STARTWEBSERVERRESPONSE']._serialized_start=13874 - _globals['_STARTWEBSERVERRESPONSE']._serialized_end=13967 - _globals['_STOPWEBSERVERREQUEST']._serialized_start=13969 - _globals['_STOPWEBSERVERREQUEST']._serialized_end=13991 - _globals['_VSCODEREQUEST']._serialized_start=13994 - _globals['_VSCODEREQUEST']._serialized_end=14391 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14393 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14436 - _globals['_VSCODERESPONSE']._serialized_start=14439 - _globals['_VSCODERESPONSE']._serialized_end=14885 - _globals['_GETWORKSPACEREQUEST']._serialized_start=14887 - _globals['_GETWORKSPACEREQUEST']._serialized_end=14908 - _globals['_GETWORKSPACERESPONSE']._serialized_start=14910 - _globals['_GETWORKSPACERESPONSE']._serialized_end=14983 - _globals['_VSCODEERROR']._serialized_start=14985 - _globals['_VSCODEERROR']._serialized_end=15029 - _globals['_INVOKETOOLREQUEST']._serialized_start=15031 - _globals['_INVOKETOOLREQUEST']._serialized_end=15093 - _globals['_INVOKETOOLRESPONSE']._serialized_start=15095 - _globals['_INVOKETOOLRESPONSE']._serialized_end=15154 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15156 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15180 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15182 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15250 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15252 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15322 - _globals['_VSCODETOOLINFO']._serialized_start=15324 - _globals['_VSCODETOOLINFO']._serialized_end=15411 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15413 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15484 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15486 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15553 - _globals['_VSCODEMODEL']._serialized_start=15555 - _globals['_VSCODEMODEL']._serialized_end=15652 - _globals['_SENDVSCODECHATREQUEST']._serialized_start=15655 - _globals['_SENDVSCODECHATREQUEST']._serialized_end=15817 - _globals['_SENDVSCODECHATRESPONSE']._serialized_start=15819 - _globals['_SENDVSCODECHATRESPONSE']._serialized_end=15888 - _globals['_VSCODECHATCHUNK']._serialized_start=15890 - _globals['_VSCODECHATCHUNK']._serialized_end=15981 - _globals['_VSCODETOOLCALL']._serialized_start=15983 - _globals['_VSCODETOOLCALL']._serialized_end=16054 - _globals['_LISTPOLICIESREQUEST']._serialized_start=16056 - _globals['_LISTPOLICIESREQUEST']._serialized_end=16077 - _globals['_LISTPOLICIESRESPONSE']._serialized_start=16079 - _globals['_LISTPOLICIESRESPONSE']._serialized_end=16143 - _globals['_POLICYINFO']._serialized_start=16145 - _globals['_POLICYINFO']._serialized_end=16230 - _globals['_POLICYCONFIG']._serialized_start=16233 - _globals['_POLICYCONFIG']._serialized_end=16555 - _globals['_POLICYSAMPLING']._serialized_start=16557 - _globals['_POLICYSAMPLING']._serialized_end=16675 - _globals['_POLICYOUTPUT']._serialized_start=16678 - _globals['_POLICYOUTPUT']._serialized_end=16946 - _globals['_POLICYCONTEXT']._serialized_start=16949 - _globals['_POLICYCONTEXT']._serialized_end=17078 - _globals['_POLICYTOOL']._serialized_start=17080 - _globals['_POLICYTOOL']._serialized_end=17188 - _globals['_POLICYRELIABILITY']._serialized_start=17190 - _globals['_POLICYRELIABILITY']._serialized_end=17305 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17308 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17513 - _globals['_MCPTRANSPORT']._serialized_start=17516 - _globals['_MCPTRANSPORT']._serialized_end=17814 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11186 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11469 + _globals['_UPDATECONFIGREQUEST']._serialized_start=11471 + _globals['_UPDATECONFIGREQUEST']._serialized_end=11564 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11567 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=11902 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=11904 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=11948 + _globals['_REMOVEPROVIDERREQUEST']._serialized_start=11950 + _globals['_REMOVEPROVIDERREQUEST']._serialized_end=12074 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=12076 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=12105 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=12107 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=12186 + _globals['_PROVIDERTEMPLATE']._serialized_start=12189 + _globals['_PROVIDERTEMPLATE']._serialized_end=12321 + _globals['_GETKEYSTATUSREQUEST']._serialized_start=12323 + _globals['_GETKEYSTATUSREQUEST']._serialized_end=12374 + _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12376 + _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12414 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12416 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12445 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12447 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12532 + _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12535 + _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12671 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12673 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12719 + _globals['_CREATEPOLICYREQUEST']._serialized_start=12721 + _globals['_CREATEPOLICYREQUEST']._serialized_end=12798 + _globals['_DELETEPOLICYREQUEST']._serialized_start=12800 + _globals['_DELETEPOLICYREQUEST']._serialized_end=12835 + _globals['_GETSECRETREQUEST']._serialized_start=12837 + _globals['_GETSECRETREQUEST']._serialized_end=12868 + _globals['_GETSECRETRESPONSE']._serialized_start=12870 + _globals['_GETSECRETRESPONSE']._serialized_end=12904 + _globals['_SETSECRETREQUEST']._serialized_start=12906 + _globals['_SETSECRETREQUEST']._serialized_end=12992 + _globals['_DELETESECRETREQUEST']._serialized_start=12994 + _globals['_DELETESECRETREQUEST']._serialized_end=13028 + _globals['_LISTSECRETSREQUEST']._serialized_start=13030 + _globals['_LISTSECRETSREQUEST']._serialized_end=13050 + _globals['_LISTSECRETSRESPONSE']._serialized_start=13052 + _globals['_LISTSECRETSRESPONSE']._serialized_end=13114 + _globals['_SECRETINFO']._serialized_start=13116 + _globals['_SECRETINFO']._serialized_end=13200 + _globals['_REGISTERREQUEST']._serialized_start=13202 + _globals['_REGISTERREQUEST']._serialized_end=13328 + _globals['_REGISTERRESPONSE']._serialized_start=13330 + _globals['_REGISTERRESPONSE']._serialized_end=13394 + _globals['_UNREGISTERREQUEST']._serialized_start=13396 + _globals['_UNREGISTERREQUEST']._serialized_end=13434 + _globals['_GETSTATUSREQUEST']._serialized_start=13436 + _globals['_GETSTATUSREQUEST']._serialized_end=13454 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13456 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13487 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13489 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13541 + _globals['_DAEMONSTATUS']._serialized_start=13544 + _globals['_DAEMONSTATUS']._serialized_end=13748 + _globals['_CONNECTEDCLIENT']._serialized_start=13751 + _globals['_CONNECTEDCLIENT']._serialized_end=13921 + _globals['_SHUTDOWNREQUEST']._serialized_start=13923 + _globals['_SHUTDOWNREQUEST']._serialized_end=13985 + _globals['_HEALTHCHECKREQUEST']._serialized_start=13987 + _globals['_HEALTHCHECKREQUEST']._serialized_end=14007 + _globals['_HEALTHCHECKRESPONSE']._serialized_start=14009 + _globals['_HEALTHCHECKRESPONSE']._serialized_end=14064 + _globals['_STARTWEBSERVERREQUEST']._serialized_start=14066 + _globals['_STARTWEBSERVERREQUEST']._serialized_end=14103 + _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14105 + _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14198 + _globals['_STOPWEBSERVERREQUEST']._serialized_start=14200 + _globals['_STOPWEBSERVERREQUEST']._serialized_end=14222 + _globals['_VSCODEREQUEST']._serialized_start=14225 + _globals['_VSCODEREQUEST']._serialized_end=14622 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14624 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14667 + _globals['_VSCODERESPONSE']._serialized_start=14670 + _globals['_VSCODERESPONSE']._serialized_end=15116 + _globals['_GETWORKSPACEREQUEST']._serialized_start=15118 + _globals['_GETWORKSPACEREQUEST']._serialized_end=15139 + _globals['_GETWORKSPACERESPONSE']._serialized_start=15141 + _globals['_GETWORKSPACERESPONSE']._serialized_end=15214 + _globals['_VSCODEERROR']._serialized_start=15216 + _globals['_VSCODEERROR']._serialized_end=15260 + _globals['_INVOKETOOLREQUEST']._serialized_start=15262 + _globals['_INVOKETOOLREQUEST']._serialized_end=15324 + _globals['_INVOKETOOLRESPONSE']._serialized_start=15326 + _globals['_INVOKETOOLRESPONSE']._serialized_end=15385 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15387 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15411 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15413 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15481 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15483 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15553 + _globals['_VSCODETOOLINFO']._serialized_start=15555 + _globals['_VSCODETOOLINFO']._serialized_end=15642 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15644 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15715 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15717 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15784 + _globals['_VSCODEMODEL']._serialized_start=15786 + _globals['_VSCODEMODEL']._serialized_end=15883 + _globals['_SENDVSCODECHATREQUEST']._serialized_start=15886 + _globals['_SENDVSCODECHATREQUEST']._serialized_end=16048 + _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16050 + _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16119 + _globals['_VSCODECHATCHUNK']._serialized_start=16121 + _globals['_VSCODECHATCHUNK']._serialized_end=16212 + _globals['_VSCODETOOLCALL']._serialized_start=16214 + _globals['_VSCODETOOLCALL']._serialized_end=16285 + _globals['_LISTPOLICIESREQUEST']._serialized_start=16287 + _globals['_LISTPOLICIESREQUEST']._serialized_end=16308 + _globals['_LISTPOLICIESRESPONSE']._serialized_start=16310 + _globals['_LISTPOLICIESRESPONSE']._serialized_end=16374 + _globals['_POLICYINFO']._serialized_start=16376 + _globals['_POLICYINFO']._serialized_end=16461 + _globals['_POLICYCONFIG']._serialized_start=16464 + _globals['_POLICYCONFIG']._serialized_end=16786 + _globals['_POLICYSAMPLING']._serialized_start=16788 + _globals['_POLICYSAMPLING']._serialized_end=16906 + _globals['_POLICYOUTPUT']._serialized_start=16909 + _globals['_POLICYOUTPUT']._serialized_end=17177 + _globals['_POLICYCONTEXT']._serialized_start=17180 + _globals['_POLICYCONTEXT']._serialized_end=17309 + _globals['_POLICYTOOL']._serialized_start=17311 + _globals['_POLICYTOOL']._serialized_end=17419 + _globals['_POLICYRELIABILITY']._serialized_start=17421 + _globals['_POLICYRELIABILITY']._serialized_end=17536 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17539 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17744 + _globals['_MCPTRANSPORT']._serialized_start=17747 + _globals['_MCPTRANSPORT']._serialized_end=18045 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10619 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10665 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10667 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10709 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=17816 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=17901 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=17903 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=17950 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=17952 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=17998 - _globals['_MCPBRIDGE']._serialized_start=18868 - _globals['_MCPBRIDGE']._serialized_end=19539 - _globals['_ABBENAY']._serialized_start=19542 - _globals['_ABBENAY']._serialized_end=23128 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18047 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18132 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18134 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18181 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18183 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18229 + _globals['_MCPBRIDGE']._serialized_start=19099 + _globals['_MCPBRIDGE']._serialized_end=19770 + _globals['_ABBENAY']._serialized_start=19773 + _globals['_ABBENAY']._serialized_end=23359 # @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi index 8fd72b3c..0823c63b 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi @@ -1098,12 +1098,22 @@ class ConsumerConfigMsg(_message.Message): def __init__(self, token_env: _Optional[str] = ..., token_keychain: _Optional[str] = ..., capabilities: _Optional[_Union[ConsumerCapabilitiesMsg, _Mapping]] = ...) -> None: ... class ConsumerCapabilitiesMsg(_message.Message): - __slots__ = ("inline_policy", "mcp_register") + __slots__ = ("inline_policy", "mcp_register", "secrets", "config", "providers", "shutdown", "chat") INLINE_POLICY_FIELD_NUMBER: _ClassVar[int] MCP_REGISTER_FIELD_NUMBER: _ClassVar[int] + SECRETS_FIELD_NUMBER: _ClassVar[int] + CONFIG_FIELD_NUMBER: _ClassVar[int] + PROVIDERS_FIELD_NUMBER: _ClassVar[int] + SHUTDOWN_FIELD_NUMBER: _ClassVar[int] + CHAT_FIELD_NUMBER: _ClassVar[int] inline_policy: bool mcp_register: bool - def __init__(self, inline_policy: bool = ..., mcp_register: bool = ...) -> None: ... + secrets: bool + config: bool + providers: bool + shutdown: bool + chat: bool + def __init__(self, inline_policy: bool = ..., mcp_register: bool = ..., secrets: bool = ..., config: bool = ..., providers: bool = ..., shutdown: bool = ..., chat: bool = ...) -> None: ... class UpdateConfigRequest(_message.Message): __slots__ = ("config", "location") @@ -1114,7 +1124,7 @@ class UpdateConfigRequest(_message.Message): def __init__(self, config: _Optional[_Union[Config, _Mapping]] = ..., location: _Optional[str] = ...) -> None: ... class ConfigureProviderRequest(_message.Message): - __slots__ = ("provider_id", "engine", "api_key", "env_var_name", "base_url", "target", "workspace_path") + __slots__ = ("provider_id", "engine", "api_key", "env_var_name", "base_url", "target", "workspace_path", "api_key_keychain_name") PROVIDER_ID_FIELD_NUMBER: _ClassVar[int] ENGINE_FIELD_NUMBER: _ClassVar[int] API_KEY_FIELD_NUMBER: _ClassVar[int] @@ -1122,6 +1132,7 @@ class ConfigureProviderRequest(_message.Message): BASE_URL_FIELD_NUMBER: _ClassVar[int] TARGET_FIELD_NUMBER: _ClassVar[int] WORKSPACE_PATH_FIELD_NUMBER: _ClassVar[int] + API_KEY_KEYCHAIN_NAME_FIELD_NUMBER: _ClassVar[int] provider_id: str engine: str api_key: str @@ -1129,7 +1140,8 @@ class ConfigureProviderRequest(_message.Message): base_url: str target: str workspace_path: str - def __init__(self, provider_id: _Optional[str] = ..., engine: _Optional[str] = ..., api_key: _Optional[str] = ..., env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., target: _Optional[str] = ..., workspace_path: _Optional[str] = ...) -> None: ... + api_key_keychain_name: str + def __init__(self, provider_id: _Optional[str] = ..., engine: _Optional[str] = ..., api_key: _Optional[str] = ..., env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., target: _Optional[str] = ..., workspace_path: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ...) -> None: ... class ConfigureProviderResponse(_message.Message): __slots__ = ("success",) diff --git a/packages/vscode/src/proto/abbenay/v1/service.ts b/packages/vscode/src/proto/abbenay/v1/service.ts index 44944e10..8f15baa8 100644 --- a/packages/vscode/src/proto/abbenay/v1/service.ts +++ b/packages/vscode/src/proto/abbenay/v1/service.ts @@ -1189,7 +1189,27 @@ export interface ConsumerCapabilitiesMsg { | boolean | undefined; /** Allow dynamic MCP server registration */ - mcpRegister?: boolean | undefined; + mcpRegister?: + | boolean + | undefined; + /** Allow secret read/write/list RPCs */ + secrets?: + | boolean + | undefined; + /** Allow GetConfig / UpdateConfig / policy / web control */ + config?: + | boolean + | undefined; + /** Allow ConfigureProvider / RemoveProvider / DiscoverModels */ + providers?: + | boolean + | undefined; + /** Allow Shutdown RPC */ + shutdown?: + | boolean + | undefined; + /** Allow Chat / SessionChat */ + chat?: boolean | undefined; } export interface UpdateConfigRequest { @@ -1207,7 +1227,7 @@ export interface ConfigureProviderRequest { engine?: | string | undefined; - /** Raw API key (daemon stores in keychain) */ + /** Raw API key value (optional with api_key_keychain_name) */ apiKey?: | string | undefined; @@ -1224,7 +1244,15 @@ export interface ConfigureProviderRequest { | string | undefined; /** Required if target is "workspace" */ - workspacePath?: string | undefined; + workspacePath?: + | string + | undefined; + /** + * Logical secret name (SetSecret key). Prefer this over inventing a name from + * provider_id. With api_key: store the value under this name. Without api_key: + * reference an existing secret (N providers may share one key). + */ + apiKeyKeychainName?: string | undefined; } export interface ConfigureProviderResponse { @@ -12059,7 +12087,15 @@ export const ConsumerConfigMsg: MessageFns = { }; function createBaseConsumerCapabilitiesMsg(): ConsumerCapabilitiesMsg { - return { inlinePolicy: undefined, mcpRegister: undefined }; + return { + inlinePolicy: undefined, + mcpRegister: undefined, + secrets: undefined, + config: undefined, + providers: undefined, + shutdown: undefined, + chat: undefined, + }; } export const ConsumerCapabilitiesMsg: MessageFns = { @@ -12070,6 +12106,21 @@ export const ConsumerCapabilitiesMsg: MessageFns = { if (message.mcpRegister !== undefined) { writer.uint32(16).bool(message.mcpRegister); } + if (message.secrets !== undefined) { + writer.uint32(24).bool(message.secrets); + } + if (message.config !== undefined) { + writer.uint32(32).bool(message.config); + } + if (message.providers !== undefined) { + writer.uint32(40).bool(message.providers); + } + if (message.shutdown !== undefined) { + writer.uint32(48).bool(message.shutdown); + } + if (message.chat !== undefined) { + writer.uint32(56).bool(message.chat); + } return writer; }, @@ -12096,6 +12147,46 @@ export const ConsumerCapabilitiesMsg: MessageFns = { message.mcpRegister = reader.bool(); continue; } + case 3: { + if (tag !== 24) { + break; + } + + message.secrets = reader.bool(); + continue; + } + case 4: { + if (tag !== 32) { + break; + } + + message.config = reader.bool(); + continue; + } + case 5: { + if (tag !== 40) { + break; + } + + message.providers = reader.bool(); + continue; + } + case 6: { + if (tag !== 48) { + break; + } + + message.shutdown = reader.bool(); + continue; + } + case 7: { + if (tag !== 56) { + break; + } + + message.chat = reader.bool(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -12117,6 +12208,11 @@ export const ConsumerCapabilitiesMsg: MessageFns = { : isSet(object.mcp_register) ? globalThis.Boolean(object.mcp_register) : undefined, + secrets: isSet(object.secrets) ? globalThis.Boolean(object.secrets) : undefined, + config: isSet(object.config) ? globalThis.Boolean(object.config) : undefined, + providers: isSet(object.providers) ? globalThis.Boolean(object.providers) : undefined, + shutdown: isSet(object.shutdown) ? globalThis.Boolean(object.shutdown) : undefined, + chat: isSet(object.chat) ? globalThis.Boolean(object.chat) : undefined, }; }, @@ -12128,6 +12224,21 @@ export const ConsumerCapabilitiesMsg: MessageFns = { if (message.mcpRegister !== undefined) { obj.mcpRegister = message.mcpRegister; } + if (message.secrets !== undefined) { + obj.secrets = message.secrets; + } + if (message.config !== undefined) { + obj.config = message.config; + } + if (message.providers !== undefined) { + obj.providers = message.providers; + } + if (message.shutdown !== undefined) { + obj.shutdown = message.shutdown; + } + if (message.chat !== undefined) { + obj.chat = message.chat; + } return obj; }, @@ -12138,6 +12249,11 @@ export const ConsumerCapabilitiesMsg: MessageFns = { const message = createBaseConsumerCapabilitiesMsg(); message.inlinePolicy = object.inlinePolicy ?? undefined; message.mcpRegister = object.mcpRegister ?? undefined; + message.secrets = object.secrets ?? undefined; + message.config = object.config ?? undefined; + message.providers = object.providers ?? undefined; + message.shutdown = object.shutdown ?? undefined; + message.chat = object.chat ?? undefined; return message; }, }; @@ -12229,6 +12345,7 @@ function createBaseConfigureProviderRequest(): ConfigureProviderRequest { baseUrl: undefined, target: undefined, workspacePath: undefined, + apiKeyKeychainName: undefined, }; } @@ -12255,6 +12372,9 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { writer.uint32(58).string(message.workspacePath); } + if (message.apiKeyKeychainName !== undefined) { + writer.uint32(66).string(message.apiKeyKeychainName); + } return writer; }, @@ -12321,6 +12441,14 @@ export const ConfigureProviderRequest: MessageFns = { message.workspacePath = reader.string(); continue; } + case 8: { + if (tag !== 66) { + break; + } + + message.apiKeyKeychainName = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -12359,6 +12487,11 @@ export const ConfigureProviderRequest: MessageFns = { : isSet(object.workspace_path) ? globalThis.String(object.workspace_path) : undefined, + apiKeyKeychainName: isSet(object.apiKeyKeychainName) + ? globalThis.String(object.apiKeyKeychainName) + : isSet(object.api_key_keychain_name) + ? globalThis.String(object.api_key_keychain_name) + : undefined, }; }, @@ -12385,6 +12518,9 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { obj.workspacePath = message.workspacePath; } + if (message.apiKeyKeychainName !== undefined) { + obj.apiKeyKeychainName = message.apiKeyKeychainName; + } return obj; }, @@ -12400,6 +12536,7 @@ export const ConfigureProviderRequest: MessageFns = { message.baseUrl = object.baseUrl ?? undefined; message.target = object.target ?? undefined; message.workspacePath = object.workspacePath ?? undefined; + message.apiKeyKeychainName = object.apiKeyKeychainName ?? undefined; return message; }, }; diff --git a/proto/abbenay/v1/service.proto b/proto/abbenay/v1/service.proto index c626df87..98a1458a 100644 --- a/proto/abbenay/v1/service.proto +++ b/proto/abbenay/v1/service.proto @@ -928,11 +928,15 @@ message UpdateConfigRequest { message ConfigureProviderRequest { string provider_id = 1; // Virtual provider name optional string engine = 2; // Engine type (e.g., "openai") - optional string api_key = 3; // Raw API key (daemon stores in keychain) + optional string api_key = 3; // Raw API key value (optional with api_key_keychain_name) optional string env_var_name = 4; // Alternative: use env var for API key optional string base_url = 5; // Custom API base URL optional string target = 6; // "user" (default) or "workspace" optional string workspace_path = 7; // Required if target is "workspace" + // Logical secret name (SetSecret key). Prefer this over inventing a name from + // provider_id. With api_key: store the value under this name. Without api_key: + // reference an existing secret (N providers may share one key). + optional string api_key_keychain_name = 8; } message ConfigureProviderResponse { From 6e9eac8eb93c7d2b079fed27df8d57b9e20e9c8b Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:06:06 -0700 Subject: [PATCH 03/18] refactor(daemon): prefer secret_name and secret_store vocabulary Rename the logical secret lookup to secret_name (YAML still accepts api_key_keychain_name). ConfigureProvider/HTTP use secret_name plus optional secret_store when writing a raw api_key. --- docs/ARCHITECTURE.md | 3 +- docs/CONFIGURATION.md | 38 +- docs/decisions.md | 12 +- packages/daemon/src/core/config-schema.ts | 3 + packages/daemon/src/core/config.ts | 21 +- packages/daemon/src/core/index.ts | 1 + packages/daemon/src/core/state.ts | 9 +- .../src/daemon/server/abbenay-service.ts | 68 +++- .../daemon/src/daemon/web/api-schemas.test.ts | 14 +- packages/daemon/src/daemon/web/api-schemas.ts | 15 +- packages/daemon/src/daemon/web/server.ts | 69 +++- .../tests/integration/consumer-auth.test.ts | 24 +- .../daemon/tests/integration/web-sse.test.ts | 10 +- packages/proto-ts/src/abbenay/v1/service.ts | 86 ++++- .../abbenay_grpc/abbenay/v1/service_pb2.py | 360 +++++++++--------- .../abbenay_grpc/abbenay/v1/service_pb2.pyi | 16 +- .../vscode/src/proto/abbenay/v1/service.ts | 86 ++++- proto/abbenay/v1/service.proto | 10 +- 18 files changed, 538 insertions(+), 307 deletions(-) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index b6740664..4d117cd1 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -185,7 +185,8 @@ Secrets are managed explicitly per-provider with two options: - macOS: Keychain - Linux: libsecret (GNOME Keyring / KDE Wallet) - Windows: Credential Vault -- Config references key by name: `api_key_keychain_name: "OPENAI_API_KEY"` +- Config references secret by name: `secret_name: "OPENAI_API_KEY"` + (legacy: `api_key_keychain_name`) ### Option 2: Environment Variable Reference - Config specifies env var name: `api_key_env_var_name: "OPENAI_API_KEY"` diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index d4b89f40..90a1b068 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -382,46 +382,44 @@ Legacy sessions without an `owner` field are treated as `local`. Each provider can specify exactly ONE of these (mutually exclusive): -### Option 1: Keychain Storage (`api_key_keychain_name`) +### Option 1: Secret store (`secret_name`) -- Key stored in system keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) -- Specify the key name used in keychain -- Set via web dashboard "API Key" toggle -- The name is a **logical lookup key** into the daemon secret store (keychain - or in-memory backend — see below) +- Value lives in the daemon secret store: **OS keychain** or **process-lifetime + memory** (see Option 1b) +- `secret_name` is the logical lookup key (preferred) +- Legacy alias: `api_key_keychain_name` (still accepted in YAML; mirrored on load) ```yaml providers: my-openai: engine: openai - api_key_keychain_name: "OPENAI_API_KEY" + secret_name: "OPENAI_API_KEY" ``` ### Option 1b: In-memory (process-lifetime) via secrets API -- Same logical key name as keychain (`api_key_keychain_name`) +- Same logical name as Option 1 (`secret_name`) - Client sets the value with gRPC `SetSecret` (`store=SECRET_STORE_MEMORY`) - or HTTP `POST /api/secrets` with `{ "store": "memory" }` + or HTTP `POST /api/secrets` with `{ "secret_store": "memory" }` - Lives only while the daemon process is running; cleared on restart or explicit delete/set by a consumer with the `secrets` capability - Mutually exclusive with keychain for the same key name (writing one backend removes the key from the other — DR-047) -- Default `store` (omitted / unspecified) remains **keychain** for backward - compatibility -- `SECRET_STORE_ENV` / `"store": "env"` is **not** writable via secrets APIs +- Default `secret_store` / `store` (omitted / unspecified) remains **keychain** +- `SECRET_STORE_ENV` / `"secret_store": "env"` is **not** writable via secrets APIs ### Recommended workflow (keys are N:1 with providers) Secrets and providers are separate. Many providers may share one named key. -1. **Add a secret by name** — `SetSecret` / `POST /api/secrets` (optionally - `store=memory`). -2. **Configure the provider** — `ConfigureProvider` / `POST /api/provider/:id/configure` - with `api_key_keychain_name` / `apiKeyKeychainName` pointing at that name - (no value). The secret must already exist. -3. Optionally pass raw `api_key` **with** `api_key_keychain_name` to store the - value under an explicit name in one step. Raw `api_key` alone still invents - `${PROVIDER_ID}_API_KEY` (legacy 1:1 shortcut). +1. **Add a secret by name** — `SetSecret` / `POST /api/secrets` with optional + `secret_store` (`memory` | `keychain`). +2. **Configure the provider** — `ConfigureProvider` / + `POST /api/provider/:id/configure` with `secret_name` / `secretName` + pointing at that name (no value). The secret must already exist. +3. Optionally pass raw `api_key` **with** `secret_name` (and optional + `secret_store`) to store the value under an explicit name in one step. + Raw `api_key` alone still invents `${PROVIDER_ID}_API_KEY` (legacy). ### Option 2: Environment Variable (`api_key_env_var_name`) diff --git a/docs/decisions.md b/docs/decisions.md index 1c70676e..88cf2ce4 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -845,12 +845,16 @@ disconnect. `SECRET_STORE_ENV` is rejected on write; env credentials remain read-only via provider `api_key_env_var_name`. Configure / `addProvider` continue to write keychain only. `api_key_keychain_name` remains a logical lookup name into the composite store (not “must be OS keychain”). -`ConfigureProvider` / HTTP configure accept `api_key_keychain_name` to -reference an existing named secret (N providers → 1 key). Raw `api_key` -alone remains a legacy shortcut that invents `${PROVIDER_ID}_API_KEY`. +Provider config prefers `secret_name` (legacy alias `api_key_keychain_name`). +`ConfigureProvider` / HTTP configure accept `secret_name` to reference an +existing named secret (N providers → 1 key), and `secret_store` when writing +a raw `api_key` (MEMORY or KEYCHAIN). Raw `api_key` alone remains a legacy +shortcut that invents `${PROVIDER_ID}_API_KEY`. Env credentials stay on +`api_key_env_var_name` (not the secret store). **Rationale:** Ephemeral keys for clients that must not persist credentials were already sketched (`MemorySecretStore`, proto `SECRET_STORE_MEMORY`) but unused by the daemon. Mutual exclusivity avoids overlay/sync/refresh bugs. Defaulting unspecified store to keychain preserves existing callers. Keys are not 1:1 with providers — configure should pick a secret by name after -`SetSecret`, not invent a private key name per provider. +`SetSecret`. `secret_name` / `secret_store` name the real abstraction; +`api_key_keychain_name` was a historical misnomer. diff --git a/packages/daemon/src/core/config-schema.ts b/packages/daemon/src/core/config-schema.ts index 598ab0d5..60fe478a 100644 --- a/packages/daemon/src/core/config-schema.ts +++ b/packages/daemon/src/core/config-schema.ts @@ -83,6 +83,9 @@ export const ModelConfigSchema = z export const ProviderConfigSchema = z .object({ engine: z.string().min(1), + /** Logical secret name (memory or OS keychain). Preferred. */ + secret_name: z.string().min(1).optional(), + /** @deprecated Use secret_name. */ api_key_keychain_name: z.string().min(1).optional(), api_key_env_var_name: z.string().min(1).optional(), base_url: ProviderBaseUrlSchema.optional(), diff --git a/packages/daemon/src/core/config.ts b/packages/daemon/src/core/config.ts index f6ede5fe..ee0c09e4 100644 --- a/packages/daemon/src/core/config.ts +++ b/packages/daemon/src/core/config.ts @@ -73,7 +73,14 @@ export interface ModelConfig { export interface ProviderConfig { /** Actual engine type: "openrouter", "openai", "anthropic", etc. */ engine: string; - /** Keychain key name for API key */ + /** + * Logical secret name in the daemon secret store (memory or OS keychain). + * Preferred over {@link api_key_keychain_name}. + */ + secret_name?: string; + /** + * @deprecated Use {@link secret_name}. Kept for existing YAML configs. + */ api_key_keychain_name?: string; /** Environment variable name for API key */ api_key_env_var_name?: string; @@ -83,6 +90,11 @@ export interface ProviderConfig { models?: Record; } +/** Resolve the secret-store lookup name (secret_name preferred). */ +export function providerSecretName(cfg: ProviderConfig): string | undefined { + return cfg.secret_name || cfg.api_key_keychain_name; +} + /** * MCP server connection configuration. * Defines an external MCP server the daemon can connect to for tool aggregation. @@ -291,6 +303,13 @@ export function loadConfigFromPath(configPath: string): ConfigFile | null { * (backward compat with the old 1:1 mapping). */ function migrateProviderConfig(provId: string, cfg: Record): void { + // Prefer secret_name; mirror legacy api_key_keychain_name either direction. + if (cfg.secret_name && !cfg.api_key_keychain_name) { + cfg.api_key_keychain_name = cfg.secret_name; + } else if (cfg.api_key_keychain_name && !cfg.secret_name) { + cfg.secret_name = cfg.api_key_keychain_name; + } + // If already new format (has engine field), just rename api_base → base_url if (cfg.engine) { if (cfg.api_base && !cfg.base_url) { diff --git a/packages/daemon/src/core/index.ts b/packages/daemon/src/core/index.ts index c1f14bac..6583ce21 100644 --- a/packages/daemon/src/core/index.ts +++ b/packages/daemon/src/core/index.ts @@ -79,6 +79,7 @@ export type { ConfigFile } from './config.js'; /** Per-provider configuration block */ export type { ProviderConfig } from './config.js'; +export { providerSecretName } from './config.js'; /** Per-model configuration block */ export type { ModelConfig } from './config.js'; diff --git a/packages/daemon/src/core/state.ts b/packages/daemon/src/core/state.ts index d5439275..929787cc 100644 --- a/packages/daemon/src/core/state.ts +++ b/packages/daemon/src/core/state.ts @@ -19,6 +19,7 @@ import { type ConfigFile, type ProviderConfig, type ModelConfig, + providerSecretName, } from './config.js'; import { resolvePolicy, flattenPolicy, type FlattenedPolicy, type PolicyConfig } from './policies.js'; import { @@ -238,6 +239,7 @@ export class CoreState { if (options.apiKey) { const keychainName = `abbenay.${providerId}`; await this.secretStore.set(keychainName, options.apiKey); + providerCfg.secret_name = keychainName; providerCfg.api_key_keychain_name = keychainName; auditSecretChange({ key: keychainName, op: 'set', source: 'core-add' }); } else if (options.apiKeyEnvVar) { @@ -358,9 +360,10 @@ export class CoreState { if (!providerCfg) return null; - // Check keychain - if (providerCfg.api_key_keychain_name) { - const value = await this.secretStore.get(providerCfg.api_key_keychain_name); + // Check secret store (memory or keychain) via logical name + const secretName = providerSecretName(providerCfg); + if (secretName) { + const value = await this.secretStore.get(secretName); if (value) return value; } diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index a847b156..ff888f18 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -22,6 +22,7 @@ import { maybeSummarize, generateSessionSummary } from '../../core/session-summa import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, isValidVirtualName, + providerSecretName, type ConfigFile, type ProviderConfig as DaemonProviderConfig, type McpServerConfig, } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; @@ -262,6 +263,7 @@ interface FullProviderConfigProto { api_key_env_var_name?: string; base_url?: string; models?: Record; + secret_name?: string; } interface ModelParamConfigProto { @@ -322,8 +324,13 @@ interface ConfigureProviderRequestProto { target?: string; workspace_path?: string; workspacePath?: string; + secret_name?: string; + secretName?: string; + /** @deprecated Alias for secret_name (PR transition). */ api_key_keychain_name?: string; apiKeyKeychainName?: string; + secret_store?: number | string; + secretStore?: number | string; } interface RemoveProviderRequestProto { @@ -1710,8 +1717,12 @@ export function createAbbenayService( const engine = call.request.engine; const apiKey = call.request.api_key || call.request.apiKey; const envVarName = call.request.env_var_name || call.request.envVarName; - const keychainNameRef = - call.request.api_key_keychain_name || call.request.apiKeyKeychainName; + const secretNameRef = + call.request.secret_name || + call.request.secretName || + call.request.api_key_keychain_name || + call.request.apiKeyKeychainName; + const secretStoreRaw = call.request.secret_store ?? call.request.secretStore; const baseUrl = call.request.base_url || call.request.baseUrl; const target = call.request.target || 'user'; const workspacePath = call.request.workspace_path || call.request.workspacePath; @@ -1769,36 +1780,54 @@ export function createAbbenayService( }); return; } - if (keychainNameRef && envVarName) { + if (secretNameRef && envVarName) { callback({ code: grpc.status.INVALID_ARGUMENT, - message: 'Provide only one of api_key_keychain_name or env_var_name', + message: 'Provide only one of secret_name or env_var_name', }); return; } if (apiKey) { + const storeChoice = parseSecretStoreChoice(secretStoreRaw); + if (!storeChoice.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: storeChoice.error, + }); + return; + } // Explicit name, or legacy invent from provider id (1:1 shortcut). - const keychainName = keychainNameRef || `${providerId.toUpperCase()}_API_KEY`; - await state.secretStore.set(keychainName, apiKey); - auditSecretChange({ key: keychainName, op: 'set', source: 'grpc-configure' }); - config.providers[providerId].api_key_keychain_name = keychainName; + const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + if (dual) { + await dual.setIn(storeChoice.backend, secretName, apiKey); + } else { + await state.secretStore.set(secretName, apiKey); + } + const auditSource = + storeChoice.backend === 'memory' ? 'grpc-configure-memory' : 'grpc-configure'; + auditSecretChange({ key: secretName, op: 'set', source: auditSource }); + config.providers[providerId].secret_name = secretName; + config.providers[providerId].api_key_keychain_name = secretName; delete config.providers[providerId].api_key_env_var_name; - } else if (keychainNameRef) { + } else if (secretNameRef) { // Reference an existing named secret (N:1 — many providers, one key). - const exists = await state.secretStore.has(keychainNameRef); + const exists = await state.secretStore.has(secretNameRef); if (!exists) { callback({ code: grpc.status.INVALID_ARGUMENT, message: - `Secret "${keychainNameRef}" not found; SetSecret first or pass api_key`, + `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, }); return; } - config.providers[providerId].api_key_keychain_name = keychainNameRef; + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].api_key_keychain_name = secretNameRef; delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { config.providers[providerId].api_key_env_var_name = envVarName; + delete config.providers[providerId].secret_name; delete config.providers[providerId].api_key_keychain_name; } @@ -1858,11 +1887,11 @@ export function createAbbenayService( : loadConfig()) || { providers: {} }; if (config.providers && config.providers[providerId]) { - const keychainName = config.providers[providerId].api_key_keychain_name; - if (keychainName) { + const secretName = providerSecretName(config.providers[providerId]); + if (secretName) { try { - await state.secretStore.delete(keychainName); - auditSecretChange({ key: keychainName, op: 'delete', source: 'grpc-configure' }); + await state.secretStore.delete(secretName); + auditSecretChange({ key: secretName, op: 'delete', source: 'grpc-configure' }); } catch { /* ignore */ } } delete config.providers[providerId]; @@ -2170,7 +2199,8 @@ export function configFileToProto(config: ConfigFile): ConfigProto { } providers[pid] = { engine: pcfg.engine || pid, - api_key_keychain_name: pcfg.api_key_keychain_name, + secret_name: providerSecretName(pcfg), + api_key_keychain_name: providerSecretName(pcfg), api_key_env_var_name: pcfg.api_key_env_var_name, base_url: pcfg.base_url, models, @@ -2247,9 +2277,11 @@ export function protoToConfigFile(proto: ConfigProto): ConfigFile { }; } } + const secretName = pcfg.secret_name || pcfg.api_key_keychain_name || undefined; config.providers[pid] = { engine: pcfg.engine || pid, - api_key_keychain_name: pcfg.api_key_keychain_name || undefined, + secret_name: secretName, + api_key_keychain_name: secretName, api_key_env_var_name: pcfg.api_key_env_var_name || undefined, base_url: pcfg.base_url || undefined, models: Object.keys(models).length > 0 ? models : undefined, diff --git a/packages/daemon/src/daemon/web/api-schemas.test.ts b/packages/daemon/src/daemon/web/api-schemas.test.ts index d028a221..415c2d30 100644 --- a/packages/daemon/src/daemon/web/api-schemas.test.ts +++ b/packages/daemon/src/daemon/web/api-schemas.test.ts @@ -65,20 +65,20 @@ describe('PostProviderConfigureBodySchema', () => { expect(result.success).toBe(true); }); - it('accepts apiKeyKeychainName to pick an existing secret', () => { + it('accepts secretName to pick an existing secret', () => { expect( PostProviderConfigureBodySchema.safeParse({ engine: 'openai', - apiKeyKeychainName: 'SHARED_OPENAI', + secretName: 'SHARED_OPENAI', }).success, ).toBe(true); }); - it('rejects apiKeyKeychainName together with envVarName', () => { + it('rejects secretName together with envVarName', () => { expect( PostProviderConfigureBodySchema.safeParse({ engine: 'openai', - apiKeyKeychainName: 'SHARED', + secretName: 'SHARED', envVarName: 'OPENAI_API_KEY', }).success, ).toBe(false); @@ -144,15 +144,15 @@ describe('secret body schemas', () => { expect(PostSecretByKeyBodySchema.safeParse({ value: '' }).success).toBe(false); }); - it('accepts optional store memory|keychain|env', () => { + it('accepts optional secret_store memory|keychain|env (and legacy store)', () => { expect( - PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'memory' }).success, + PostSecretBodySchema.safeParse({ key: 'K', value: 'v', secret_store: 'memory' }).success, ).toBe(true); expect( PostSecretByKeyBodySchema.safeParse({ value: 'v', store: 'keychain' }).success, ).toBe(true); expect( - PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'env' }).success, + PostSecretBodySchema.safeParse({ key: 'K', value: 'v', secret_store: 'env' }).success, ).toBe(true); expect( PostSecretBodySchema.safeParse({ key: 'K', value: 'v', store: 'vault' }).success, diff --git a/packages/daemon/src/daemon/web/api-schemas.ts b/packages/daemon/src/daemon/web/api-schemas.ts index 414158e0..4f073dc8 100644 --- a/packages/daemon/src/daemon/web/api-schemas.ts +++ b/packages/daemon/src/daemon/web/api-schemas.ts @@ -48,6 +48,8 @@ export const PostSecretByKeyBodySchema = z .object({ value: z.string().min(1), /** Default: keychain (persistent). memory = process-lifetime only. */ + secret_store: SecretStoreFieldSchema, + /** @deprecated Use secret_store. */ store: SecretStoreFieldSchema, }) .strict(); @@ -57,6 +59,8 @@ export const PostSecretBodySchema = z key: z.string().min(1), value: z.string().min(1), /** Default: keychain (persistent). memory = process-lifetime only. */ + secret_store: SecretStoreFieldSchema, + /** @deprecated Use secret_store. */ store: SecretStoreFieldSchema, }) .strict(); @@ -109,6 +113,10 @@ export const PostProviderConfigureBodySchema = z engine: z.string().min(1).optional(), apiKey: z.string().min(1).optional(), /** Logical secret name (SetSecret key). Prefer over inventing from provider id. */ + secretName: z.string().min(1).optional(), + /** Where to write apiKey: memory | keychain (default keychain). */ + secretStore: z.enum(['memory', 'keychain', 'env']).optional(), + /** @deprecated Use secretName. */ apiKeyKeychainName: z.string().min(1).optional(), envVarName: z.string().min(1).optional(), /** Format-checked here; host policy applied in the route with server config. */ @@ -132,11 +140,12 @@ export const PostProviderConfigureBodySchema = z path: ['apiKey'], }); } - if (data.apiKeyKeychainName && data.envVarName) { + const secretName = data.secretName || data.apiKeyKeychainName; + if (secretName && data.envVarName) { ctx.addIssue({ code: z.ZodIssueCode.custom, - message: 'Provide only one of apiKeyKeychainName or envVarName', - path: ['apiKeyKeychainName'], + message: 'Provide only one of secretName or envVarName', + path: ['secretName'], }); } }); diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 567d4ef6..8b04e194 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -16,7 +16,7 @@ import * as path from 'node:path'; import * as fs from 'node:fs'; import { fileURLToPath } from 'node:url'; import { getDefaultSocketPath } from '../transport.js'; -import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, type ConfigFile, type ProviderConfig } from '../../core/config.js'; +import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, providerSecretName, type ConfigFile, type ProviderConfig } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; import { isDualSecretStore, parseSecretStoreChoice } from '../secrets/dual.js'; import { @@ -1058,7 +1058,9 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - const storeChoice = parseSecretStoreChoice(parsed.data.store ?? 'keychain'); + const storeChoice = parseSecretStoreChoice( + parsed.data.secret_store ?? parsed.data.store ?? 'keychain', + ); if (!storeChoice.ok) { sendBadRequest(res, storeChoice.error); return; @@ -1072,7 +1074,7 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): const auditSource = storeChoice.backend === 'memory' ? 'http-secrets-memory' : 'http-secrets'; auditSecretChange({ key, op: 'set', source: auditSource }); - res.json({ success: true, store: storeChoice.backend }); + res.json({ success: true, secret_store: storeChoice.backend }); state.notifyModelsChanged('secret_updated'); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); @@ -1083,7 +1085,7 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): /** * POST /api/secrets - Set a secret (API key) — legacy route - * Body: { key: string, value: string, store?: "memory" | "keychain" } + * Body: { key: string, value: string, secret_store?: "memory" | "keychain" } */ app.post('/api/secrets', async (req, res) => { try { @@ -1092,7 +1094,9 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - const storeChoice = parseSecretStoreChoice(parsed.data.store ?? 'keychain'); + const storeChoice = parseSecretStoreChoice( + parsed.data.secret_store ?? parsed.data.store ?? 'keychain', + ); if (!storeChoice.ok) { sendBadRequest(res, storeChoice.error); return; @@ -1106,7 +1110,7 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): const auditSource = storeChoice.backend === 'memory' ? 'http-secrets-memory' : 'http-secrets'; auditSecretChange({ key: parsed.data.key, op: 'set', source: auditSource }); - res.json({ success: true, store: storeChoice.backend }); + res.json({ success: true, secret_store: storeChoice.backend }); state.notifyModelsChanged('secret_updated'); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); @@ -1360,8 +1364,18 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - const { engine, apiKey, apiKeyKeychainName, envVarName, baseUrl, target, workspacePath } = - parsed.data; + const { + engine, + apiKey, + secretName: secretNameBody, + secretStore: secretStoreBody, + apiKeyKeychainName, + envVarName, + baseUrl, + target, + workspacePath, + } = parsed.data; + const secretNameRef = secretNameBody || apiKeyKeychainName; let resolvedWorkspace: string | undefined; if (target === 'workspace' && workspacePath) { @@ -1412,25 +1426,40 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): config.providers[providerId] = existing as ProviderConfig; if (apiKey) { + const storeChoice = parseSecretStoreChoice(secretStoreBody ?? 'keychain'); + if (!storeChoice.ok) { + sendBadRequest(res, storeChoice.error); + return; + } // Explicit name, or legacy invent from provider id (1:1 shortcut). - const keychainName = apiKeyKeychainName || `${providerId.toUpperCase()}_API_KEY`; - await state.secretStore.set(keychainName, apiKey); - auditSecretChange({ key: keychainName, op: 'set', source: 'http-configure' }); - config.providers[providerId].api_key_keychain_name = keychainName; + const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; + const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + if (dual) { + await dual.setIn(storeChoice.backend, secretName, apiKey); + } else { + await state.secretStore.set(secretName, apiKey); + } + const auditSource = + storeChoice.backend === 'memory' ? 'http-configure-memory' : 'http-configure'; + auditSecretChange({ key: secretName, op: 'set', source: auditSource }); + config.providers[providerId].secret_name = secretName; + config.providers[providerId].api_key_keychain_name = secretName; delete config.providers[providerId].api_key_env_var_name; - } else if (apiKeyKeychainName) { + } else if (secretNameRef) { // Reference an existing named secret (N:1 — many providers, one key). - const exists = await state.secretStore.has(apiKeyKeychainName); + const exists = await state.secretStore.has(secretNameRef); if (!exists) { res.status(400).json({ - error: `Secret "${apiKeyKeychainName}" not found; POST /api/secrets first or pass apiKey`, + error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, }); return; } - config.providers[providerId].api_key_keychain_name = apiKeyKeychainName; + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].api_key_keychain_name = secretNameRef; delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { config.providers[providerId].api_key_env_var_name = envVarName; + delete config.providers[providerId].secret_name; delete config.providers[providerId].api_key_keychain_name; } @@ -1496,11 +1525,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): : loadConfig()) || { providers: {} }; if (config.providers && config.providers[providerId]) { - const keychainName = config.providers[providerId].api_key_keychain_name; - if (keychainName) { + const secretName = providerSecretName(config.providers[providerId]); + if (secretName) { try { - await state.secretStore.delete(keychainName); - auditSecretChange({ key: keychainName, op: 'delete', source: 'http-configure' }); + await state.secretStore.delete(secretName); + auditSecretChange({ key: secretName, op: 'delete', source: 'http-configure' }); } catch { /* ignore */ } } diff --git a/packages/daemon/tests/integration/consumer-auth.test.ts b/packages/daemon/tests/integration/consumer-auth.test.ts index 5394c36e..e2a542d9 100644 --- a/packages/daemon/tests/integration/consumer-auth.test.ts +++ b/packages/daemon/tests/integration/consumer-auth.test.ts @@ -43,6 +43,8 @@ vi.mock('../../src/core/config.js', () => ({ getUserConfigPath: () => '/tmp/abbenay-test-config.yaml', getWorkspaceConfigPath: () => '/tmp/abbenay-test-ws-config.yaml', isValidVirtualName: (n: string) => /^[a-z0-9][a-z0-9._-]*$/.test(n), + providerSecretName: (cfg: { secret_name?: string; api_key_keychain_name?: string }) => + cfg.secret_name || cfg.api_key_keychain_name, })); vi.mock('../../src/core/engines.js', () => ({ @@ -280,42 +282,48 @@ describe('Consumer auth RPC gating', () => { const res = await callUnary(client, 'ConfigureProvider', { provider_id: 'work-openai', engine: 'mock', - api_key_keychain_name: 'SHARED_OPENAI', + secret_name: 'SHARED_OPENAI', }, GOOD_TOKEN); expect(res.success).toBe(true); const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { - providers: { 'work-openai': { api_key_keychain_name?: string } }; + providers: { + 'work-openai': { secret_name?: string; api_key_keychain_name?: string }; + }; }; + expect(saved.providers['work-openai'].secret_name).toBe('SHARED_OPENAI'); expect(saved.providers['work-openai'].api_key_keychain_name).toBe('SHARED_OPENAI'); // Reference path must not invent a provider-scoped key name or rewrite the secret. expect(mockSecretStoreData.has('WORK-OPENAI_API_KEY')).toBe(false); }); - it('ConfigureProvider rejects missing api_key_keychain_name', async () => { + it('ConfigureProvider rejects missing secret_name', async () => { await expect( callUnary(client, 'ConfigureProvider', { provider_id: 'missing-key-provider', engine: 'mock', - api_key_keychain_name: 'DOES_NOT_EXIST', + secret_name: 'DOES_NOT_EXIST', }, GOOD_TOKEN), ).rejects.toMatchObject({ code: grpc.status.INVALID_ARGUMENT }); }); - it('ConfigureProvider stores api_key under an explicit keychain name', async () => { + it('ConfigureProvider stores api_key under an explicit secret_name', async () => { const res = await callUnary(client, 'ConfigureProvider', { provider_id: 'named-write', engine: 'mock', api_key: 'sk-explicit', - api_key_keychain_name: 'MY_EXPLICIT_KEY', + secret_name: 'MY_EXPLICIT_KEY', + secret_store: 'SECRET_STORE_KEYCHAIN', }, GOOD_TOKEN); expect(res.success).toBe(true); expect(mockSecretStoreData.get('MY_EXPLICIT_KEY')).toBe('sk-explicit'); const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { - providers: { 'named-write': { api_key_keychain_name?: string } }; + providers: { + 'named-write': { secret_name?: string; api_key_keychain_name?: string }; + }; }; - expect(saved.providers['named-write'].api_key_keychain_name).toBe('MY_EXPLICIT_KEY'); + expect(saved.providers['named-write'].secret_name).toBe('MY_EXPLICIT_KEY'); }); it('denies Shutdown without shutdown capability', async () => { diff --git a/packages/daemon/tests/integration/web-sse.test.ts b/packages/daemon/tests/integration/web-sse.test.ts index abde1a05..704ea9ed 100644 --- a/packages/daemon/tests/integration/web-sse.test.ts +++ b/packages/daemon/tests/integration/web-sse.test.ts @@ -476,21 +476,21 @@ describe('Web API - Secrets Endpoints', () => { expect(body.success).toBe(true); }); - it('POST /api/secrets/:key should accept store=memory', async () => { + it('POST /api/secrets/:key should accept secret_store=memory', async () => { const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets/MEM_KEY`, { value: 'ephemeral', - store: 'memory', + secret_store: 'memory', }); expect(statusCode).toBe(200); expect(body.success).toBe(true); - expect(body.store).toBe('memory'); + expect(body.secret_store).toBe('memory'); }); - it('POST /api/secrets should reject store=env', async () => { + it('POST /api/secrets should reject secret_store=env', async () => { const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets`, { key: 'ENV_KEY', value: 'nope', - store: 'env', + secret_store: 'env', }); expect(statusCode).toBe(400); expect(body.error).toMatch(/ENV/i); diff --git a/packages/proto-ts/src/abbenay/v1/service.ts b/packages/proto-ts/src/abbenay/v1/service.ts index 8f15baa8..b52a0dfd 100644 --- a/packages/proto-ts/src/abbenay/v1/service.ts +++ b/packages/proto-ts/src/abbenay/v1/service.ts @@ -1089,10 +1089,13 @@ export interface Config_ConsumersEntry { export interface FullProviderConfig { engine: string; + /** deprecated: use secret_name */ apiKeyKeychainName?: string | undefined; apiKeyEnvVarName?: string | undefined; baseUrl?: string | undefined; models: { [key: string]: ModelParamConfig }; + /** Logical secret store name (preferred) */ + secretName?: string | undefined; } export interface FullProviderConfig_ModelsEntry { @@ -1227,7 +1230,7 @@ export interface ConfigureProviderRequest { engine?: | string | undefined; - /** Raw API key value (optional with api_key_keychain_name) */ + /** Raw API key value (optional with secret_name) */ apiKey?: | string | undefined; @@ -1252,7 +1255,14 @@ export interface ConfigureProviderRequest { * provider_id. With api_key: store the value under this name. Without api_key: * reference an existing secret (N providers may share one key). */ - apiKeyKeychainName?: string | undefined; + secretName?: + | string + | undefined; + /** + * Where to write api_key when provided (MEMORY or KEYCHAIN). Default KEYCHAIN. + * Ignored when only referencing an existing secret_name. + */ + secretStore?: SecretStore | undefined; } export interface ConfigureProviderResponse { @@ -10896,7 +10906,14 @@ export const Config_ConsumersEntry: MessageFns = { }; function createBaseFullProviderConfig(): FullProviderConfig { - return { engine: "", apiKeyKeychainName: undefined, apiKeyEnvVarName: undefined, baseUrl: undefined, models: {} }; + return { + engine: "", + apiKeyKeychainName: undefined, + apiKeyEnvVarName: undefined, + baseUrl: undefined, + models: {}, + secretName: undefined, + }; } export const FullProviderConfig: MessageFns = { @@ -10916,6 +10933,9 @@ export const FullProviderConfig: MessageFns = { globalThis.Object.entries(message.models).forEach(([key, value]: [string, ModelParamConfig]) => { FullProviderConfig_ModelsEntry.encode({ key: key as any, value }, writer.uint32(42).fork()).join(); }); + if (message.secretName !== undefined) { + writer.uint32(50).string(message.secretName); + } return writer; }, @@ -10969,6 +10989,14 @@ export const FullProviderConfig: MessageFns = { } continue; } + case 6: { + if (tag !== 50) { + break; + } + + message.secretName = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -11005,6 +11033,11 @@ export const FullProviderConfig: MessageFns = { {}, ) : {}, + secretName: isSet(object.secretName) + ? globalThis.String(object.secretName) + : isSet(object.secret_name) + ? globalThis.String(object.secret_name) + : undefined, }; }, @@ -11031,6 +11064,9 @@ export const FullProviderConfig: MessageFns = { }); } } + if (message.secretName !== undefined) { + obj.secretName = message.secretName; + } return obj; }, @@ -11052,6 +11088,7 @@ export const FullProviderConfig: MessageFns = { }, {}, ); + message.secretName = object.secretName ?? undefined; return message; }, }; @@ -12345,7 +12382,8 @@ function createBaseConfigureProviderRequest(): ConfigureProviderRequest { baseUrl: undefined, target: undefined, workspacePath: undefined, - apiKeyKeychainName: undefined, + secretName: undefined, + secretStore: undefined, }; } @@ -12372,8 +12410,11 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { writer.uint32(58).string(message.workspacePath); } - if (message.apiKeyKeychainName !== undefined) { - writer.uint32(66).string(message.apiKeyKeychainName); + if (message.secretName !== undefined) { + writer.uint32(66).string(message.secretName); + } + if (message.secretStore !== undefined) { + writer.uint32(72).int32(message.secretStore); } return writer; }, @@ -12446,7 +12487,15 @@ export const ConfigureProviderRequest: MessageFns = { break; } - message.apiKeyKeychainName = reader.string(); + message.secretName = reader.string(); + continue; + } + case 9: { + if (tag !== 72) { + break; + } + + message.secretStore = reader.int32() as any; continue; } } @@ -12487,10 +12536,15 @@ export const ConfigureProviderRequest: MessageFns = { : isSet(object.workspace_path) ? globalThis.String(object.workspace_path) : undefined, - apiKeyKeychainName: isSet(object.apiKeyKeychainName) - ? globalThis.String(object.apiKeyKeychainName) - : isSet(object.api_key_keychain_name) - ? globalThis.String(object.api_key_keychain_name) + secretName: isSet(object.secretName) + ? globalThis.String(object.secretName) + : isSet(object.secret_name) + ? globalThis.String(object.secret_name) + : undefined, + secretStore: isSet(object.secretStore) + ? secretStoreFromJSON(object.secretStore) + : isSet(object.secret_store) + ? secretStoreFromJSON(object.secret_store) : undefined, }; }, @@ -12518,8 +12572,11 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { obj.workspacePath = message.workspacePath; } - if (message.apiKeyKeychainName !== undefined) { - obj.apiKeyKeychainName = message.apiKeyKeychainName; + if (message.secretName !== undefined) { + obj.secretName = message.secretName; + } + if (message.secretStore !== undefined) { + obj.secretStore = secretStoreToJSON(message.secretStore); } return obj; }, @@ -12536,7 +12593,8 @@ export const ConfigureProviderRequest: MessageFns = { message.baseUrl = object.baseUrl ?? undefined; message.target = object.target ?? undefined; message.workspacePath = object.workspacePath ?? undefined; - message.apiKeyKeychainName = object.apiKeyKeychainName ?? undefined; + message.secretName = object.secretName ?? undefined; + message.secretStore = object.secretStore ?? undefined; return message; }, }; diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py index e556c26a..4054c8b2 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xcb\x02\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_url\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\xcf\x02\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\"\n\x15\x61pi_key_keychain_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x18\n\x16_api_key_keychain_name\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xf5\x02\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_name\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -57,20 +57,20 @@ _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_options = b'8\001' _globals['_MCPTRANSPORT_ENVENTRY']._loaded_options = None _globals['_MCPTRANSPORT_ENVENTRY']._serialized_options = b'8\001' - _globals['_ROLE']._serialized_start=18231 - _globals['_ROLE']._serialized_end=18326 - _globals['_CLIENTTYPE']._serialized_start=18329 - _globals['_CLIENTTYPE']._serialized_end=18484 - _globals['_REPLAYFORMAT']._serialized_start=18487 - _globals['_REPLAYFORMAT']._serialized_end=18617 - _globals['_MODELSOURCE']._serialized_start=18619 - _globals['_MODELSOURCE']._serialized_end=18715 - _globals['_PROVIDERTYPE']._serialized_start=18717 - _globals['_PROVIDERTYPE']._serialized_end=18834 - _globals['_LOGLEVEL']._serialized_start=18837 - _globals['_LOGLEVEL']._serialized_end=18977 - _globals['_SECRETSTORE']._serialized_start=18979 - _globals['_SECRETSTORE']._serialized_end=19096 + _globals['_ROLE']._serialized_start=18322 + _globals['_ROLE']._serialized_end=18417 + _globals['_CLIENTTYPE']._serialized_start=18420 + _globals['_CLIENTTYPE']._serialized_end=18575 + _globals['_REPLAYFORMAT']._serialized_start=18578 + _globals['_REPLAYFORMAT']._serialized_end=18708 + _globals['_MODELSOURCE']._serialized_start=18710 + _globals['_MODELSOURCE']._serialized_end=18806 + _globals['_PROVIDERTYPE']._serialized_start=18808 + _globals['_PROVIDERTYPE']._serialized_end=18925 + _globals['_LOGLEVEL']._serialized_start=18928 + _globals['_LOGLEVEL']._serialized_end=19068 + _globals['_SECRETSTORE']._serialized_start=19070 + _globals['_SECRETSTORE']._serialized_end=19187 _globals['_EMPTY']._serialized_start=40 _globals['_EMPTY']._serialized_end=47 _globals['_TIMESTAMP']._serialized_start=49 @@ -260,169 +260,169 @@ _globals['_CONFIG_CONSUMERSENTRY']._serialized_start=9576 _globals['_CONFIG_CONSUMERSENTRY']._serialized_end=9655 _globals['_FULLPROVIDERCONFIG']._serialized_start=9658 - _globals['_FULLPROVIDERCONFIG']._serialized_end=9989 - _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_start=9850 - _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_end=9925 - _globals['_MODELPARAMCONFIG']._serialized_start=9992 - _globals['_MODELPARAMCONFIG']._serialized_end=10356 - _globals['_MCPSERVERCONFIGMSG']._serialized_start=10359 - _globals['_MCPSERVERCONFIGMSG']._serialized_end=10751 - _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_start=10619 - _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_end=10665 - _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_start=10667 - _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_end=10709 - _globals['_TOOLPOLICYCONFIGMSG']._serialized_start=10754 - _globals['_TOOLPOLICYCONFIGMSG']._serialized_end=11016 - _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_start=10946 - _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_end=10992 - _globals['_CONSUMERCONFIGMSG']._serialized_start=11019 - _globals['_CONSUMERCONFIGMSG']._serialized_end=11183 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11186 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11469 - _globals['_UPDATECONFIGREQUEST']._serialized_start=11471 - _globals['_UPDATECONFIGREQUEST']._serialized_end=11564 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11567 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=11902 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=11904 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=11948 - _globals['_REMOVEPROVIDERREQUEST']._serialized_start=11950 - _globals['_REMOVEPROVIDERREQUEST']._serialized_end=12074 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=12076 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=12105 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=12107 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=12186 - _globals['_PROVIDERTEMPLATE']._serialized_start=12189 - _globals['_PROVIDERTEMPLATE']._serialized_end=12321 - _globals['_GETKEYSTATUSREQUEST']._serialized_start=12323 - _globals['_GETKEYSTATUSREQUEST']._serialized_end=12374 - _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12376 - _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12414 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12416 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12445 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12447 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12532 - _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12535 - _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12671 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12673 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12719 - _globals['_CREATEPOLICYREQUEST']._serialized_start=12721 - _globals['_CREATEPOLICYREQUEST']._serialized_end=12798 - _globals['_DELETEPOLICYREQUEST']._serialized_start=12800 - _globals['_DELETEPOLICYREQUEST']._serialized_end=12835 - _globals['_GETSECRETREQUEST']._serialized_start=12837 - _globals['_GETSECRETREQUEST']._serialized_end=12868 - _globals['_GETSECRETRESPONSE']._serialized_start=12870 - _globals['_GETSECRETRESPONSE']._serialized_end=12904 - _globals['_SETSECRETREQUEST']._serialized_start=12906 - _globals['_SETSECRETREQUEST']._serialized_end=12992 - _globals['_DELETESECRETREQUEST']._serialized_start=12994 - _globals['_DELETESECRETREQUEST']._serialized_end=13028 - _globals['_LISTSECRETSREQUEST']._serialized_start=13030 - _globals['_LISTSECRETSREQUEST']._serialized_end=13050 - _globals['_LISTSECRETSRESPONSE']._serialized_start=13052 - _globals['_LISTSECRETSRESPONSE']._serialized_end=13114 - _globals['_SECRETINFO']._serialized_start=13116 - _globals['_SECRETINFO']._serialized_end=13200 - _globals['_REGISTERREQUEST']._serialized_start=13202 - _globals['_REGISTERREQUEST']._serialized_end=13328 - _globals['_REGISTERRESPONSE']._serialized_start=13330 - _globals['_REGISTERRESPONSE']._serialized_end=13394 - _globals['_UNREGISTERREQUEST']._serialized_start=13396 - _globals['_UNREGISTERREQUEST']._serialized_end=13434 - _globals['_GETSTATUSREQUEST']._serialized_start=13436 - _globals['_GETSTATUSREQUEST']._serialized_end=13454 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13456 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13487 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13489 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13541 - _globals['_DAEMONSTATUS']._serialized_start=13544 - _globals['_DAEMONSTATUS']._serialized_end=13748 - _globals['_CONNECTEDCLIENT']._serialized_start=13751 - _globals['_CONNECTEDCLIENT']._serialized_end=13921 - _globals['_SHUTDOWNREQUEST']._serialized_start=13923 - _globals['_SHUTDOWNREQUEST']._serialized_end=13985 - _globals['_HEALTHCHECKREQUEST']._serialized_start=13987 - _globals['_HEALTHCHECKREQUEST']._serialized_end=14007 - _globals['_HEALTHCHECKRESPONSE']._serialized_start=14009 - _globals['_HEALTHCHECKRESPONSE']._serialized_end=14064 - _globals['_STARTWEBSERVERREQUEST']._serialized_start=14066 - _globals['_STARTWEBSERVERREQUEST']._serialized_end=14103 - _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14105 - _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14198 - _globals['_STOPWEBSERVERREQUEST']._serialized_start=14200 - _globals['_STOPWEBSERVERREQUEST']._serialized_end=14222 - _globals['_VSCODEREQUEST']._serialized_start=14225 - _globals['_VSCODEREQUEST']._serialized_end=14622 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14624 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14667 - _globals['_VSCODERESPONSE']._serialized_start=14670 - _globals['_VSCODERESPONSE']._serialized_end=15116 - _globals['_GETWORKSPACEREQUEST']._serialized_start=15118 - _globals['_GETWORKSPACEREQUEST']._serialized_end=15139 - _globals['_GETWORKSPACERESPONSE']._serialized_start=15141 - _globals['_GETWORKSPACERESPONSE']._serialized_end=15214 - _globals['_VSCODEERROR']._serialized_start=15216 - _globals['_VSCODEERROR']._serialized_end=15260 - _globals['_INVOKETOOLREQUEST']._serialized_start=15262 - _globals['_INVOKETOOLREQUEST']._serialized_end=15324 - _globals['_INVOKETOOLRESPONSE']._serialized_start=15326 - _globals['_INVOKETOOLRESPONSE']._serialized_end=15385 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15387 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15411 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15413 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15481 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15483 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15553 - _globals['_VSCODETOOLINFO']._serialized_start=15555 - _globals['_VSCODETOOLINFO']._serialized_end=15642 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15644 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15715 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15717 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15784 - _globals['_VSCODEMODEL']._serialized_start=15786 - _globals['_VSCODEMODEL']._serialized_end=15883 - _globals['_SENDVSCODECHATREQUEST']._serialized_start=15886 - _globals['_SENDVSCODECHATREQUEST']._serialized_end=16048 - _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16050 - _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16119 - _globals['_VSCODECHATCHUNK']._serialized_start=16121 - _globals['_VSCODECHATCHUNK']._serialized_end=16212 - _globals['_VSCODETOOLCALL']._serialized_start=16214 - _globals['_VSCODETOOLCALL']._serialized_end=16285 - _globals['_LISTPOLICIESREQUEST']._serialized_start=16287 - _globals['_LISTPOLICIESREQUEST']._serialized_end=16308 - _globals['_LISTPOLICIESRESPONSE']._serialized_start=16310 - _globals['_LISTPOLICIESRESPONSE']._serialized_end=16374 - _globals['_POLICYINFO']._serialized_start=16376 - _globals['_POLICYINFO']._serialized_end=16461 - _globals['_POLICYCONFIG']._serialized_start=16464 - _globals['_POLICYCONFIG']._serialized_end=16786 - _globals['_POLICYSAMPLING']._serialized_start=16788 - _globals['_POLICYSAMPLING']._serialized_end=16906 - _globals['_POLICYOUTPUT']._serialized_start=16909 - _globals['_POLICYOUTPUT']._serialized_end=17177 - _globals['_POLICYCONTEXT']._serialized_start=17180 - _globals['_POLICYCONTEXT']._serialized_end=17309 - _globals['_POLICYTOOL']._serialized_start=17311 - _globals['_POLICYTOOL']._serialized_end=17419 - _globals['_POLICYRELIABILITY']._serialized_start=17421 - _globals['_POLICYRELIABILITY']._serialized_end=17536 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17539 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17744 - _globals['_MCPTRANSPORT']._serialized_start=17747 - _globals['_MCPTRANSPORT']._serialized_end=18045 - _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10619 - _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10665 - _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10667 - _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10709 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18047 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18132 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18134 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18181 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18183 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18229 - _globals['_MCPBRIDGE']._serialized_start=19099 - _globals['_MCPBRIDGE']._serialized_end=19770 - _globals['_ABBENAY']._serialized_start=19773 - _globals['_ABBENAY']._serialized_end=23359 + _globals['_FULLPROVIDERCONFIG']._serialized_end=10031 + _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_start=9876 + _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_end=9951 + _globals['_MODELPARAMCONFIG']._serialized_start=10034 + _globals['_MODELPARAMCONFIG']._serialized_end=10398 + _globals['_MCPSERVERCONFIGMSG']._serialized_start=10401 + _globals['_MCPSERVERCONFIGMSG']._serialized_end=10793 + _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_start=10661 + _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_end=10707 + _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_start=10709 + _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_end=10751 + _globals['_TOOLPOLICYCONFIGMSG']._serialized_start=10796 + _globals['_TOOLPOLICYCONFIGMSG']._serialized_end=11058 + _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_start=10988 + _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_end=11034 + _globals['_CONSUMERCONFIGMSG']._serialized_start=11061 + _globals['_CONSUMERCONFIGMSG']._serialized_end=11225 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11228 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11511 + _globals['_UPDATECONFIGREQUEST']._serialized_start=11513 + _globals['_UPDATECONFIGREQUEST']._serialized_end=11606 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11609 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=11993 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=11995 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=12039 + _globals['_REMOVEPROVIDERREQUEST']._serialized_start=12041 + _globals['_REMOVEPROVIDERREQUEST']._serialized_end=12165 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=12167 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=12196 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=12198 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=12277 + _globals['_PROVIDERTEMPLATE']._serialized_start=12280 + _globals['_PROVIDERTEMPLATE']._serialized_end=12412 + _globals['_GETKEYSTATUSREQUEST']._serialized_start=12414 + _globals['_GETKEYSTATUSREQUEST']._serialized_end=12465 + _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12467 + _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12505 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12507 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12536 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12538 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12623 + _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12626 + _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12762 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12764 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12810 + _globals['_CREATEPOLICYREQUEST']._serialized_start=12812 + _globals['_CREATEPOLICYREQUEST']._serialized_end=12889 + _globals['_DELETEPOLICYREQUEST']._serialized_start=12891 + _globals['_DELETEPOLICYREQUEST']._serialized_end=12926 + _globals['_GETSECRETREQUEST']._serialized_start=12928 + _globals['_GETSECRETREQUEST']._serialized_end=12959 + _globals['_GETSECRETRESPONSE']._serialized_start=12961 + _globals['_GETSECRETRESPONSE']._serialized_end=12995 + _globals['_SETSECRETREQUEST']._serialized_start=12997 + _globals['_SETSECRETREQUEST']._serialized_end=13083 + _globals['_DELETESECRETREQUEST']._serialized_start=13085 + _globals['_DELETESECRETREQUEST']._serialized_end=13119 + _globals['_LISTSECRETSREQUEST']._serialized_start=13121 + _globals['_LISTSECRETSREQUEST']._serialized_end=13141 + _globals['_LISTSECRETSRESPONSE']._serialized_start=13143 + _globals['_LISTSECRETSRESPONSE']._serialized_end=13205 + _globals['_SECRETINFO']._serialized_start=13207 + _globals['_SECRETINFO']._serialized_end=13291 + _globals['_REGISTERREQUEST']._serialized_start=13293 + _globals['_REGISTERREQUEST']._serialized_end=13419 + _globals['_REGISTERRESPONSE']._serialized_start=13421 + _globals['_REGISTERRESPONSE']._serialized_end=13485 + _globals['_UNREGISTERREQUEST']._serialized_start=13487 + _globals['_UNREGISTERREQUEST']._serialized_end=13525 + _globals['_GETSTATUSREQUEST']._serialized_start=13527 + _globals['_GETSTATUSREQUEST']._serialized_end=13545 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13547 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13578 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13580 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13632 + _globals['_DAEMONSTATUS']._serialized_start=13635 + _globals['_DAEMONSTATUS']._serialized_end=13839 + _globals['_CONNECTEDCLIENT']._serialized_start=13842 + _globals['_CONNECTEDCLIENT']._serialized_end=14012 + _globals['_SHUTDOWNREQUEST']._serialized_start=14014 + _globals['_SHUTDOWNREQUEST']._serialized_end=14076 + _globals['_HEALTHCHECKREQUEST']._serialized_start=14078 + _globals['_HEALTHCHECKREQUEST']._serialized_end=14098 + _globals['_HEALTHCHECKRESPONSE']._serialized_start=14100 + _globals['_HEALTHCHECKRESPONSE']._serialized_end=14155 + _globals['_STARTWEBSERVERREQUEST']._serialized_start=14157 + _globals['_STARTWEBSERVERREQUEST']._serialized_end=14194 + _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14196 + _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14289 + _globals['_STOPWEBSERVERREQUEST']._serialized_start=14291 + _globals['_STOPWEBSERVERREQUEST']._serialized_end=14313 + _globals['_VSCODEREQUEST']._serialized_start=14316 + _globals['_VSCODEREQUEST']._serialized_end=14713 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14715 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14758 + _globals['_VSCODERESPONSE']._serialized_start=14761 + _globals['_VSCODERESPONSE']._serialized_end=15207 + _globals['_GETWORKSPACEREQUEST']._serialized_start=15209 + _globals['_GETWORKSPACEREQUEST']._serialized_end=15230 + _globals['_GETWORKSPACERESPONSE']._serialized_start=15232 + _globals['_GETWORKSPACERESPONSE']._serialized_end=15305 + _globals['_VSCODEERROR']._serialized_start=15307 + _globals['_VSCODEERROR']._serialized_end=15351 + _globals['_INVOKETOOLREQUEST']._serialized_start=15353 + _globals['_INVOKETOOLREQUEST']._serialized_end=15415 + _globals['_INVOKETOOLRESPONSE']._serialized_start=15417 + _globals['_INVOKETOOLRESPONSE']._serialized_end=15476 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15478 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15502 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15504 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15572 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15574 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15644 + _globals['_VSCODETOOLINFO']._serialized_start=15646 + _globals['_VSCODETOOLINFO']._serialized_end=15733 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15735 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15806 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15808 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15875 + _globals['_VSCODEMODEL']._serialized_start=15877 + _globals['_VSCODEMODEL']._serialized_end=15974 + _globals['_SENDVSCODECHATREQUEST']._serialized_start=15977 + _globals['_SENDVSCODECHATREQUEST']._serialized_end=16139 + _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16141 + _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16210 + _globals['_VSCODECHATCHUNK']._serialized_start=16212 + _globals['_VSCODECHATCHUNK']._serialized_end=16303 + _globals['_VSCODETOOLCALL']._serialized_start=16305 + _globals['_VSCODETOOLCALL']._serialized_end=16376 + _globals['_LISTPOLICIESREQUEST']._serialized_start=16378 + _globals['_LISTPOLICIESREQUEST']._serialized_end=16399 + _globals['_LISTPOLICIESRESPONSE']._serialized_start=16401 + _globals['_LISTPOLICIESRESPONSE']._serialized_end=16465 + _globals['_POLICYINFO']._serialized_start=16467 + _globals['_POLICYINFO']._serialized_end=16552 + _globals['_POLICYCONFIG']._serialized_start=16555 + _globals['_POLICYCONFIG']._serialized_end=16877 + _globals['_POLICYSAMPLING']._serialized_start=16879 + _globals['_POLICYSAMPLING']._serialized_end=16997 + _globals['_POLICYOUTPUT']._serialized_start=17000 + _globals['_POLICYOUTPUT']._serialized_end=17268 + _globals['_POLICYCONTEXT']._serialized_start=17271 + _globals['_POLICYCONTEXT']._serialized_end=17400 + _globals['_POLICYTOOL']._serialized_start=17402 + _globals['_POLICYTOOL']._serialized_end=17510 + _globals['_POLICYRELIABILITY']._serialized_start=17512 + _globals['_POLICYRELIABILITY']._serialized_end=17627 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17630 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17835 + _globals['_MCPTRANSPORT']._serialized_start=17838 + _globals['_MCPTRANSPORT']._serialized_end=18136 + _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10661 + _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10707 + _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10709 + _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10751 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18138 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18223 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18225 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18272 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18274 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18320 + _globals['_MCPBRIDGE']._serialized_start=19190 + _globals['_MCPBRIDGE']._serialized_end=19861 + _globals['_ABBENAY']._serialized_start=19864 + _globals['_ABBENAY']._serialized_end=23450 # @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi index 0823c63b..56bd7cad 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi @@ -990,7 +990,7 @@ class Config(_message.Message): def __init__(self, providers: _Optional[_Mapping[str, FullProviderConfig]] = ..., mcp_servers: _Optional[_Mapping[str, McpServerConfigMsg]] = ..., tool_policy: _Optional[_Union[ToolPolicyConfigMsg, _Mapping]] = ..., consumers: _Optional[_Mapping[str, ConsumerConfigMsg]] = ...) -> None: ... class FullProviderConfig(_message.Message): - __slots__ = ("engine", "api_key_keychain_name", "api_key_env_var_name", "base_url", "models") + __slots__ = ("engine", "api_key_keychain_name", "api_key_env_var_name", "base_url", "models", "secret_name") class ModelsEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] @@ -1003,12 +1003,14 @@ class FullProviderConfig(_message.Message): API_KEY_ENV_VAR_NAME_FIELD_NUMBER: _ClassVar[int] BASE_URL_FIELD_NUMBER: _ClassVar[int] MODELS_FIELD_NUMBER: _ClassVar[int] + SECRET_NAME_FIELD_NUMBER: _ClassVar[int] engine: str api_key_keychain_name: str api_key_env_var_name: str base_url: str models: _containers.MessageMap[str, ModelParamConfig] - def __init__(self, engine: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ..., api_key_env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., models: _Optional[_Mapping[str, ModelParamConfig]] = ...) -> None: ... + secret_name: str + def __init__(self, engine: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ..., api_key_env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., models: _Optional[_Mapping[str, ModelParamConfig]] = ..., secret_name: _Optional[str] = ...) -> None: ... class ModelParamConfig(_message.Message): __slots__ = ("model_id", "policy", "system_prompt", "system_prompt_mode", "temperature", "top_p", "top_k", "max_tokens", "timeout") @@ -1124,7 +1126,7 @@ class UpdateConfigRequest(_message.Message): def __init__(self, config: _Optional[_Union[Config, _Mapping]] = ..., location: _Optional[str] = ...) -> None: ... class ConfigureProviderRequest(_message.Message): - __slots__ = ("provider_id", "engine", "api_key", "env_var_name", "base_url", "target", "workspace_path", "api_key_keychain_name") + __slots__ = ("provider_id", "engine", "api_key", "env_var_name", "base_url", "target", "workspace_path", "secret_name", "secret_store") PROVIDER_ID_FIELD_NUMBER: _ClassVar[int] ENGINE_FIELD_NUMBER: _ClassVar[int] API_KEY_FIELD_NUMBER: _ClassVar[int] @@ -1132,7 +1134,8 @@ class ConfigureProviderRequest(_message.Message): BASE_URL_FIELD_NUMBER: _ClassVar[int] TARGET_FIELD_NUMBER: _ClassVar[int] WORKSPACE_PATH_FIELD_NUMBER: _ClassVar[int] - API_KEY_KEYCHAIN_NAME_FIELD_NUMBER: _ClassVar[int] + SECRET_NAME_FIELD_NUMBER: _ClassVar[int] + SECRET_STORE_FIELD_NUMBER: _ClassVar[int] provider_id: str engine: str api_key: str @@ -1140,8 +1143,9 @@ class ConfigureProviderRequest(_message.Message): base_url: str target: str workspace_path: str - api_key_keychain_name: str - def __init__(self, provider_id: _Optional[str] = ..., engine: _Optional[str] = ..., api_key: _Optional[str] = ..., env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., target: _Optional[str] = ..., workspace_path: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ...) -> None: ... + secret_name: str + secret_store: SecretStore + def __init__(self, provider_id: _Optional[str] = ..., engine: _Optional[str] = ..., api_key: _Optional[str] = ..., env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., target: _Optional[str] = ..., workspace_path: _Optional[str] = ..., secret_name: _Optional[str] = ..., secret_store: _Optional[_Union[SecretStore, str]] = ...) -> None: ... class ConfigureProviderResponse(_message.Message): __slots__ = ("success",) diff --git a/packages/vscode/src/proto/abbenay/v1/service.ts b/packages/vscode/src/proto/abbenay/v1/service.ts index 8f15baa8..b52a0dfd 100644 --- a/packages/vscode/src/proto/abbenay/v1/service.ts +++ b/packages/vscode/src/proto/abbenay/v1/service.ts @@ -1089,10 +1089,13 @@ export interface Config_ConsumersEntry { export interface FullProviderConfig { engine: string; + /** deprecated: use secret_name */ apiKeyKeychainName?: string | undefined; apiKeyEnvVarName?: string | undefined; baseUrl?: string | undefined; models: { [key: string]: ModelParamConfig }; + /** Logical secret store name (preferred) */ + secretName?: string | undefined; } export interface FullProviderConfig_ModelsEntry { @@ -1227,7 +1230,7 @@ export interface ConfigureProviderRequest { engine?: | string | undefined; - /** Raw API key value (optional with api_key_keychain_name) */ + /** Raw API key value (optional with secret_name) */ apiKey?: | string | undefined; @@ -1252,7 +1255,14 @@ export interface ConfigureProviderRequest { * provider_id. With api_key: store the value under this name. Without api_key: * reference an existing secret (N providers may share one key). */ - apiKeyKeychainName?: string | undefined; + secretName?: + | string + | undefined; + /** + * Where to write api_key when provided (MEMORY or KEYCHAIN). Default KEYCHAIN. + * Ignored when only referencing an existing secret_name. + */ + secretStore?: SecretStore | undefined; } export interface ConfigureProviderResponse { @@ -10896,7 +10906,14 @@ export const Config_ConsumersEntry: MessageFns = { }; function createBaseFullProviderConfig(): FullProviderConfig { - return { engine: "", apiKeyKeychainName: undefined, apiKeyEnvVarName: undefined, baseUrl: undefined, models: {} }; + return { + engine: "", + apiKeyKeychainName: undefined, + apiKeyEnvVarName: undefined, + baseUrl: undefined, + models: {}, + secretName: undefined, + }; } export const FullProviderConfig: MessageFns = { @@ -10916,6 +10933,9 @@ export const FullProviderConfig: MessageFns = { globalThis.Object.entries(message.models).forEach(([key, value]: [string, ModelParamConfig]) => { FullProviderConfig_ModelsEntry.encode({ key: key as any, value }, writer.uint32(42).fork()).join(); }); + if (message.secretName !== undefined) { + writer.uint32(50).string(message.secretName); + } return writer; }, @@ -10969,6 +10989,14 @@ export const FullProviderConfig: MessageFns = { } continue; } + case 6: { + if (tag !== 50) { + break; + } + + message.secretName = reader.string(); + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -11005,6 +11033,11 @@ export const FullProviderConfig: MessageFns = { {}, ) : {}, + secretName: isSet(object.secretName) + ? globalThis.String(object.secretName) + : isSet(object.secret_name) + ? globalThis.String(object.secret_name) + : undefined, }; }, @@ -11031,6 +11064,9 @@ export const FullProviderConfig: MessageFns = { }); } } + if (message.secretName !== undefined) { + obj.secretName = message.secretName; + } return obj; }, @@ -11052,6 +11088,7 @@ export const FullProviderConfig: MessageFns = { }, {}, ); + message.secretName = object.secretName ?? undefined; return message; }, }; @@ -12345,7 +12382,8 @@ function createBaseConfigureProviderRequest(): ConfigureProviderRequest { baseUrl: undefined, target: undefined, workspacePath: undefined, - apiKeyKeychainName: undefined, + secretName: undefined, + secretStore: undefined, }; } @@ -12372,8 +12410,11 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { writer.uint32(58).string(message.workspacePath); } - if (message.apiKeyKeychainName !== undefined) { - writer.uint32(66).string(message.apiKeyKeychainName); + if (message.secretName !== undefined) { + writer.uint32(66).string(message.secretName); + } + if (message.secretStore !== undefined) { + writer.uint32(72).int32(message.secretStore); } return writer; }, @@ -12446,7 +12487,15 @@ export const ConfigureProviderRequest: MessageFns = { break; } - message.apiKeyKeychainName = reader.string(); + message.secretName = reader.string(); + continue; + } + case 9: { + if (tag !== 72) { + break; + } + + message.secretStore = reader.int32() as any; continue; } } @@ -12487,10 +12536,15 @@ export const ConfigureProviderRequest: MessageFns = { : isSet(object.workspace_path) ? globalThis.String(object.workspace_path) : undefined, - apiKeyKeychainName: isSet(object.apiKeyKeychainName) - ? globalThis.String(object.apiKeyKeychainName) - : isSet(object.api_key_keychain_name) - ? globalThis.String(object.api_key_keychain_name) + secretName: isSet(object.secretName) + ? globalThis.String(object.secretName) + : isSet(object.secret_name) + ? globalThis.String(object.secret_name) + : undefined, + secretStore: isSet(object.secretStore) + ? secretStoreFromJSON(object.secretStore) + : isSet(object.secret_store) + ? secretStoreFromJSON(object.secret_store) : undefined, }; }, @@ -12518,8 +12572,11 @@ export const ConfigureProviderRequest: MessageFns = { if (message.workspacePath !== undefined) { obj.workspacePath = message.workspacePath; } - if (message.apiKeyKeychainName !== undefined) { - obj.apiKeyKeychainName = message.apiKeyKeychainName; + if (message.secretName !== undefined) { + obj.secretName = message.secretName; + } + if (message.secretStore !== undefined) { + obj.secretStore = secretStoreToJSON(message.secretStore); } return obj; }, @@ -12536,7 +12593,8 @@ export const ConfigureProviderRequest: MessageFns = { message.baseUrl = object.baseUrl ?? undefined; message.target = object.target ?? undefined; message.workspacePath = object.workspacePath ?? undefined; - message.apiKeyKeychainName = object.apiKeyKeychainName ?? undefined; + message.secretName = object.secretName ?? undefined; + message.secretStore = object.secretStore ?? undefined; return message; }, }; diff --git a/proto/abbenay/v1/service.proto b/proto/abbenay/v1/service.proto index 98a1458a..6fa94771 100644 --- a/proto/abbenay/v1/service.proto +++ b/proto/abbenay/v1/service.proto @@ -854,10 +854,11 @@ message Config { message FullProviderConfig { string engine = 1; - optional string api_key_keychain_name = 2; + optional string api_key_keychain_name = 2; // deprecated: use secret_name optional string api_key_env_var_name = 3; optional string base_url = 4; map models = 5; + optional string secret_name = 6; // Logical secret store name (preferred) } message ModelParamConfig { @@ -928,7 +929,7 @@ message UpdateConfigRequest { message ConfigureProviderRequest { string provider_id = 1; // Virtual provider name optional string engine = 2; // Engine type (e.g., "openai") - optional string api_key = 3; // Raw API key value (optional with api_key_keychain_name) + optional string api_key = 3; // Raw API key value (optional with secret_name) optional string env_var_name = 4; // Alternative: use env var for API key optional string base_url = 5; // Custom API base URL optional string target = 6; // "user" (default) or "workspace" @@ -936,7 +937,10 @@ message ConfigureProviderRequest { // Logical secret name (SetSecret key). Prefer this over inventing a name from // provider_id. With api_key: store the value under this name. Without api_key: // reference an existing secret (N providers may share one key). - optional string api_key_keychain_name = 8; + optional string secret_name = 8; + // Where to write api_key when provided (MEMORY or KEYCHAIN). Default KEYCHAIN. + // Ignored when only referencing an existing secret_name. + optional SecretStore secret_store = 9; } message ConfigureProviderResponse { From 111c3abaafe2cb61c913e4c79e510d923eba28df Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:14:02 -0700 Subject: [PATCH 04/18] feat(daemon): allow secret_store=env for provider references secret_name + secret_store=env points at a process env var (resolved at request time). SetSecret still rejects ENV writes; legacy env_var_name maps to the same shape. --- docs/CONFIGURATION.md | 66 ++-- docs/decisions.md | 12 +- packages/daemon/src/core/config-schema.ts | 5 +- packages/daemon/src/core/config.ts | 49 ++- packages/daemon/src/core/index.ts | 2 +- packages/daemon/src/core/state.ts | 20 +- .../daemon/src/daemon/secrets/dual.test.ts | 7 + packages/daemon/src/daemon/secrets/dual.ts | 20 +- .../src/daemon/server/abbenay-service.ts | 120 +++++- packages/daemon/src/daemon/web/server.ts | 48 ++- .../tests/integration/consumer-auth.test.ts | 43 +++ packages/proto-ts/src/abbenay/v1/service.ts | 34 +- .../abbenay_grpc/abbenay/v1/service_pb2.py | 360 +++++++++--------- .../abbenay_grpc/abbenay/v1/service_pb2.pyi | 6 +- .../vscode/src/proto/abbenay/v1/service.ts | 34 +- proto/abbenay/v1/service.proto | 5 +- 16 files changed, 543 insertions(+), 288 deletions(-) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 90a1b068..b62de82c 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -382,61 +382,55 @@ Legacy sessions without an `owner` field are treated as `local`. Each provider can specify exactly ONE of these (mutually exclusive): -### Option 1: Secret store (`secret_name`) +### Option 1: Secret store (`secret_name` + optional `secret_store`) -- Value lives in the daemon secret store: **OS keychain** or **process-lifetime - memory** (see Option 1b) -- `secret_name` is the logical lookup key (preferred) -- Legacy alias: `api_key_keychain_name` (still accepted in YAML; mirrored on load) +- `secret_name` is the logical name +- `secret_store` is where it lives: + - omitted / `keychain` / `memory` → daemon secret store (OS keychain or process memory) + - `env` → process environment variable named `secret_name` +- Legacy aliases: `api_key_keychain_name`, `api_key_env_var_name` ```yaml providers: my-openai: engine: openai secret_name: "OPENAI_API_KEY" + # secret_store: keychain # optional; memory|keychain use the secret store +``` + +```yaml +providers: + ci-openai: + engine: openai + secret_name: "OPENAI_API_KEY" + secret_store: env # already exported in the process environment ``` ### Option 1b: In-memory (process-lifetime) via secrets API -- Same logical name as Option 1 (`secret_name`) -- Client sets the value with gRPC `SetSecret` (`store=SECRET_STORE_MEMORY`) - or HTTP `POST /api/secrets` with `{ "secret_store": "memory" }` -- Lives only while the daemon process is running; cleared on restart or - explicit delete/set by a consumer with the `secrets` capability -- Mutually exclusive with keychain for the same key name (writing one backend - removes the key from the other — DR-047) -- Default `secret_store` / `store` (omitted / unspecified) remains **keychain** -- `SECRET_STORE_ENV` / `"secret_store": "env"` is **not** writable via secrets APIs +- Same `secret_name`; set value with `SetSecret` / `POST /api/secrets` and + `secret_store: memory` (SetSecret still cannot write `env`) +- Lives only while the daemon process is running +- Mutually exclusive with keychain for the same key name (DR-047) ### Recommended workflow (keys are N:1 with providers) -Secrets and providers are separate. Many providers may share one named key. - -1. **Add a secret by name** — `SetSecret` / `POST /api/secrets` with optional - `secret_store` (`memory` | `keychain`). -2. **Configure the provider** — `ConfigureProvider` / - `POST /api/provider/:id/configure` with `secret_name` / `secretName` - pointing at that name (no value). The secret must already exist. -3. Optionally pass raw `api_key` **with** `secret_name` (and optional - `secret_store`) to store the value under an explicit name in one step. - Raw `api_key` alone still invents `${PROVIDER_ID}_API_KEY` (legacy). +1. **Add a secret** (store) — `SetSecret` with `secret_store=memory|keychain`, **or** + export an env var yourself. +2. **Configure the provider** — `secret_name=NAME` and optional + `secret_store=memory|keychain|env`. For `env`, the variable is resolved at + request time (it need not exist at configure time). +3. Many providers may share one `secret_name`. -### Option 2: Environment Variable (`api_key_env_var_name`) +### Option 2: Environment Variable (legacy `api_key_env_var_name`) -- Key read from environment variable at runtime -- Specify the env var name to check -- Set via web dashboard "Env" toggle - -```yaml -providers: - anthropic-work: - engine: anthropic - api_key_env_var_name: "ANTHROPIC_API_KEY" -``` +Prefer `secret_name` + `secret_store: env`. The legacy field still works and is +mirrored on load. ### Fallback -If neither option is set, the engine's default environment variable is checked (e.g., `OPENAI_API_KEY` for the `openai` engine). +If neither option is set, the engine's default environment variable is checked +(e.g., `OPENAI_API_KEY` for the `openai` engine). ## Supported Engines diff --git a/docs/decisions.md b/docs/decisions.md index 88cf2ce4..ac98e842 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -846,11 +846,13 @@ read-only via provider `api_key_env_var_name`. Configure / `addProvider` continue to write keychain only. `api_key_keychain_name` remains a logical lookup name into the composite store (not “must be OS keychain”). Provider config prefers `secret_name` (legacy alias `api_key_keychain_name`). -`ConfigureProvider` / HTTP configure accept `secret_name` to reference an -existing named secret (N providers → 1 key), and `secret_store` when writing -a raw `api_key` (MEMORY or KEYCHAIN). Raw `api_key` alone remains a legacy -shortcut that invents `${PROVIDER_ID}_API_KEY`. Env credentials stay on -`api_key_env_var_name` (not the secret store). +`secret_store` is `memory` | `keychain` | `env`: env means resolve +`secret_name` from `process.env` (configure/reference only — SetSecret still +rejects ENV writes). `ConfigureProvider` accepts `secret_name` + optional +`secret_store` to reference an existing secret or env var (N providers → 1 +key). Raw `api_key` alone remains a legacy shortcut that invents +`${PROVIDER_ID}_API_KEY`. Legacy `api_key_env_var_name` maps to +`secret_name` + `secret_store: env` on load. **Rationale:** Ephemeral keys for clients that must not persist credentials were already sketched (`MemorySecretStore`, proto `SECRET_STORE_MEMORY`) but unused by the daemon. Mutual exclusivity avoids overlay/sync/refresh bugs. diff --git a/packages/daemon/src/core/config-schema.ts b/packages/daemon/src/core/config-schema.ts index 60fe478a..aee7a5f3 100644 --- a/packages/daemon/src/core/config-schema.ts +++ b/packages/daemon/src/core/config-schema.ts @@ -83,10 +83,13 @@ export const ModelConfigSchema = z export const ProviderConfigSchema = z .object({ engine: z.string().min(1), - /** Logical secret name (memory or OS keychain). Preferred. */ + /** Logical secret name (store key or env var). Preferred. */ secret_name: z.string().min(1).optional(), + /** memory | keychain | env — where secret_name is resolved. */ + secret_store: z.enum(['memory', 'keychain', 'env']).optional(), /** @deprecated Use secret_name. */ api_key_keychain_name: z.string().min(1).optional(), + /** @deprecated Use secret_name + secret_store: env. */ api_key_env_var_name: z.string().min(1).optional(), base_url: ProviderBaseUrlSchema.optional(), models: z.record(z.string(), ModelConfigSchema).optional(), diff --git a/packages/daemon/src/core/config.ts b/packages/daemon/src/core/config.ts index ee0c09e4..86a484a6 100644 --- a/packages/daemon/src/core/config.ts +++ b/packages/daemon/src/core/config.ts @@ -74,15 +74,23 @@ export interface ProviderConfig { /** Actual engine type: "openrouter", "openai", "anthropic", etc. */ engine: string; /** - * Logical secret name in the daemon secret store (memory or OS keychain). - * Preferred over {@link api_key_keychain_name}. + * Logical secret name: secret-store key or env var name. + * Preferred over {@link api_key_keychain_name} / {@link api_key_env_var_name}. */ secret_name?: string; + /** + * Where {@link secret_name} is resolved from. + * - `memory` / `keychain` / omitted (with a store name): daemon secret store + * - `env`: process environment variable + */ + secret_store?: 'memory' | 'keychain' | 'env'; /** * @deprecated Use {@link secret_name}. Kept for existing YAML configs. */ api_key_keychain_name?: string; - /** Environment variable name for API key */ + /** + * @deprecated Use {@link secret_name} + `secret_store: env`. + */ api_key_env_var_name?: string; /** Custom API base URL (falls back to engine default) */ base_url?: string; @@ -90,9 +98,30 @@ export interface ProviderConfig { models?: Record; } -/** Resolve the secret-store lookup name (secret_name preferred). */ +/** Resolve the logical secret / env var name (secret_name preferred). */ export function providerSecretName(cfg: ProviderConfig): string | undefined { - return cfg.secret_name || cfg.api_key_keychain_name; + return cfg.secret_name || cfg.api_key_keychain_name || undefined; +} + +/** + * How to resolve credentials for a provider. + * `store` → DualSecretStore (memory/keychain); `env` → process.env. + */ +export function providerCredentialSource( + cfg: ProviderConfig, +): { kind: 'store' | 'env'; name: string } | null { + if (cfg.secret_store === 'env') { + const name = cfg.secret_name || cfg.api_key_env_var_name; + return name ? { kind: 'env', name } : null; + } + const storeName = providerSecretName(cfg); + if (storeName) { + return { kind: 'store', name: storeName }; + } + if (cfg.api_key_env_var_name) { + return { kind: 'env', name: cfg.api_key_env_var_name }; + } + return null; } /** @@ -304,12 +333,20 @@ export function loadConfigFromPath(configPath: string): ConfigFile | null { */ function migrateProviderConfig(provId: string, cfg: Record): void { // Prefer secret_name; mirror legacy api_key_keychain_name either direction. - if (cfg.secret_name && !cfg.api_key_keychain_name) { + if (cfg.secret_name && !cfg.api_key_keychain_name && cfg.secret_store !== 'env') { cfg.api_key_keychain_name = cfg.secret_name; } else if (cfg.api_key_keychain_name && !cfg.secret_name) { cfg.secret_name = cfg.api_key_keychain_name; } + // Legacy env-only config → secret_name + secret_store: env + if (cfg.api_key_env_var_name && !cfg.secret_name && !cfg.api_key_keychain_name) { + cfg.secret_name = cfg.api_key_env_var_name; + if (!cfg.secret_store) cfg.secret_store = 'env'; + } else if (cfg.secret_store === 'env' && cfg.secret_name && !cfg.api_key_env_var_name) { + cfg.api_key_env_var_name = cfg.secret_name; + } + // If already new format (has engine field), just rename api_base → base_url if (cfg.engine) { if (cfg.api_base && !cfg.base_url) { diff --git a/packages/daemon/src/core/index.ts b/packages/daemon/src/core/index.ts index 6583ce21..0b8002f8 100644 --- a/packages/daemon/src/core/index.ts +++ b/packages/daemon/src/core/index.ts @@ -79,7 +79,7 @@ export type { ConfigFile } from './config.js'; /** Per-provider configuration block */ export type { ProviderConfig } from './config.js'; -export { providerSecretName } from './config.js'; +export { providerSecretName, providerCredentialSource } from './config.js'; /** Per-model configuration block */ export type { ModelConfig } from './config.js'; diff --git a/packages/daemon/src/core/state.ts b/packages/daemon/src/core/state.ts index 929787cc..347d1a2f 100644 --- a/packages/daemon/src/core/state.ts +++ b/packages/daemon/src/core/state.ts @@ -19,7 +19,7 @@ import { type ConfigFile, type ProviderConfig, type ModelConfig, - providerSecretName, + providerCredentialSource, } from './config.js'; import { resolvePolicy, flattenPolicy, type FlattenedPolicy, type PolicyConfig } from './policies.js'; import { @@ -349,7 +349,7 @@ export class CoreState { } /** - * Resolve the API key for a virtual provider from config (keychain or env var). + * Resolve the API key for a virtual provider from secret store or env var. * Falls back to the engine's default env var if no explicit config. */ async resolveApiKey(providerId: string, providerCfg?: ProviderConfig): Promise { @@ -360,17 +360,13 @@ export class CoreState { if (!providerCfg) return null; - // Check secret store (memory or keychain) via logical name - const secretName = providerSecretName(providerCfg); - if (secretName) { - const value = await this.secretStore.get(secretName); - if (value) return value; - } - - // Check env var from config - if (providerCfg.api_key_env_var_name) { - const value = process.env[providerCfg.api_key_env_var_name]; + const source = providerCredentialSource(providerCfg); + if (source?.kind === 'env') { + const value = process.env[source.name]; if (value && value.length > 0) return value; + } else if (source?.kind === 'store') { + const value = await this.secretStore.get(source.name); + if (value) return value; } // Fall back to engine's default env var diff --git a/packages/daemon/src/daemon/secrets/dual.test.ts b/packages/daemon/src/daemon/secrets/dual.test.ts index b714522b..0e1c98ef 100644 --- a/packages/daemon/src/daemon/secrets/dual.test.ts +++ b/packages/daemon/src/daemon/secrets/dual.test.ts @@ -118,6 +118,13 @@ describe('parseSecretStoreChoice', () => { } }); + it('allows ENV when allowEnv is set (configure/reference)', () => { + expect(parseSecretStoreChoice('env', { allowEnv: true })).toEqual({ + ok: true, + backend: 'env', + }); + }); + it('rejects unknown stores', () => { const result = parseSecretStoreChoice('vault'); expect(result.ok).toBe(false); diff --git a/packages/daemon/src/daemon/secrets/dual.ts b/packages/daemon/src/daemon/secrets/dual.ts index 2b787bec..a6369d9b 100644 --- a/packages/daemon/src/daemon/secrets/dual.ts +++ b/packages/daemon/src/daemon/secrets/dual.ts @@ -7,9 +7,12 @@ import type { SecretStore } from '../../core/secrets.js'; -/** Writable secret backends (ENV is not a write target). */ +/** Writable DualSecretStore backends. */ export type SecretBackend = 'memory' | 'keychain'; +/** Full secret_store vocabulary including env references. */ +export type SecretStoreKind = SecretBackend | 'env'; + /** * Composite store used by the daemon. * @@ -111,13 +114,14 @@ export function isDualSecretStore(store: SecretStore): store is DualSecretStore } /** - * Parse SetSecret / HTTP `store` field. - * Unspecified / omitted / keychain → keychain (default). - * ENV is rejected (env refs stay config-only). + * Parse SetSecret / ConfigureProvider `store` / `secret_store` field. + * Unspecified / omitted / keychain → keychain (default for writes). + * ENV rejected for writes unless `allowEnv` (configure/reference only). */ export function parseSecretStoreChoice( store: unknown, -): { ok: true; backend: SecretBackend } | { ok: false; error: string } { + opts?: { allowEnv?: boolean }, +): { ok: true; backend: SecretStoreKind } | { ok: false; error: string } { if ( store === undefined || store === null || @@ -136,10 +140,14 @@ export function parseSecretStoreChoice( return { ok: true, backend: 'memory' }; } if (store === 'env' || store === 'SECRET_STORE_ENV' || store === 2 || store === '2') { + if (opts?.allowEnv) { + return { ok: true, backend: 'env' }; + } return { ok: false, error: - 'SECRET_STORE_ENV is not writable via SetSecret; use api_key_env_var_name in provider config', + 'SECRET_STORE_ENV is not writable via SetSecret; configure the provider with ' + + 'secret_name + secret_store=env (or api_key_env_var_name)', }; } return { ok: false, error: `Unsupported secret store: ${String(store)}` }; diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index ff888f18..dece2f56 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -264,6 +264,7 @@ interface FullProviderConfigProto { base_url?: string; models?: Record; secret_name?: string; + secret_store?: number | string; } interface ModelParamConfigProto { @@ -1797,11 +1798,18 @@ export function createAbbenayService( }); return; } + if (storeChoice.backend === 'env') { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: 'Cannot write api_key into env; use secret_store=memory|keychain', + }); + return; + } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; if (dual) { - await dual.setIn(storeChoice.backend, secretName, apiKey); + await dual.setIn(storeChoice.backend as 'memory' | 'keychain', secretName, apiKey); } else { await state.secretStore.set(secretName, apiKey); } @@ -1809,25 +1817,70 @@ export function createAbbenayService( storeChoice.backend === 'memory' ? 'grpc-configure-memory' : 'grpc-configure'; auditSecretChange({ key: secretName, op: 'set', source: auditSource }); config.providers[providerId].secret_name = secretName; + config.providers[providerId].secret_store = storeChoice.backend; config.providers[providerId].api_key_keychain_name = secretName; delete config.providers[providerId].api_key_env_var_name; } else if (secretNameRef) { - // Reference an existing named secret (N:1 — many providers, one key). - const exists = await state.secretStore.has(secretNameRef); - if (!exists) { - callback({ - code: grpc.status.INVALID_ARGUMENT, - message: - `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, - }); - return; + const storeRaw = secretStoreRaw; + const wantsEnv = + storeRaw === 'env' || + storeRaw === 'SECRET_STORE_ENV' || + storeRaw === 2 || + storeRaw === '2'; + + if ( + wantsEnv || + (storeRaw !== undefined && storeRaw !== null && storeRaw !== '') + ) { + const storeChoice = parseSecretStoreChoice(storeRaw, { allowEnv: true }); + if (!storeChoice.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: storeChoice.error, + }); + return; + } + if (storeChoice.backend === 'env') { + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].secret_store = 'env'; + config.providers[providerId].api_key_env_var_name = secretNameRef; + delete config.providers[providerId].api_key_keychain_name; + } else { + const exists = await state.secretStore.has(secretNameRef); + if (!exists) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: + `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, + }); + return; + } + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].secret_store = storeChoice.backend; + config.providers[providerId].api_key_keychain_name = secretNameRef; + delete config.providers[providerId].api_key_env_var_name; + } + } else { + // No secret_store: reference daemon secret store (memory or keychain). + const exists = await state.secretStore.has(secretNameRef); + if (!exists) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: + `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, + }); + return; + } + config.providers[providerId].secret_name = secretNameRef; + delete config.providers[providerId].secret_store; + config.providers[providerId].api_key_keychain_name = secretNameRef; + delete config.providers[providerId].api_key_env_var_name; } - config.providers[providerId].secret_name = secretNameRef; - config.providers[providerId].api_key_keychain_name = secretNameRef; - delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { + // Legacy shortcut → secret_name + secret_store=env (var need not exist yet). + config.providers[providerId].secret_name = envVarName; + config.providers[providerId].secret_store = 'env'; config.providers[providerId].api_key_env_var_name = envVarName; - delete config.providers[providerId].secret_name; delete config.providers[providerId].api_key_keychain_name; } @@ -2197,11 +2250,23 @@ export function configFileToProto(config: ConfigFile): ConfigProto { }; } } + const secretName = providerSecretName(pcfg); providers[pid] = { engine: pcfg.engine || pid, - secret_name: providerSecretName(pcfg), - api_key_keychain_name: providerSecretName(pcfg), - api_key_env_var_name: pcfg.api_key_env_var_name, + secret_name: secretName, + secret_store: + pcfg.secret_store === 'env' + ? 2 + : pcfg.secret_store === 'memory' + ? 3 + : secretName + ? 1 + : 0, + api_key_keychain_name: pcfg.secret_store === 'env' ? undefined : secretName, + api_key_env_var_name: + pcfg.secret_store === 'env' + ? secretName || pcfg.api_key_env_var_name + : pcfg.api_key_env_var_name, base_url: pcfg.base_url, models, }; @@ -2278,11 +2343,26 @@ export function protoToConfigFile(proto: ConfigProto): ConfigFile { } } const secretName = pcfg.secret_name || pcfg.api_key_keychain_name || undefined; + let secretStore: 'memory' | 'keychain' | 'env' | undefined; + if (pcfg.secret_store === 2 || pcfg.secret_store === 'SECRET_STORE_ENV' || pcfg.secret_store === 'env') { + secretStore = 'env'; + } else if (pcfg.secret_store === 3 || pcfg.secret_store === 'SECRET_STORE_MEMORY' || pcfg.secret_store === 'memory') { + secretStore = 'memory'; + } else if (pcfg.secret_store === 1 || pcfg.secret_store === 'SECRET_STORE_KEYCHAIN' || pcfg.secret_store === 'keychain') { + secretStore = 'keychain'; + } else if (pcfg.api_key_env_var_name && !secretName) { + secretStore = 'env'; + } + const envName = + secretStore === 'env' + ? (secretName || pcfg.api_key_env_var_name || undefined) + : (pcfg.api_key_env_var_name || undefined); config.providers[pid] = { engine: pcfg.engine || pid, - secret_name: secretName, - api_key_keychain_name: secretName, - api_key_env_var_name: pcfg.api_key_env_var_name || undefined, + secret_name: secretStore === 'env' ? envName : secretName, + secret_store: secretStore, + api_key_keychain_name: secretStore === 'env' ? undefined : secretName, + api_key_env_var_name: envName, base_url: pcfg.base_url || undefined, models: Object.keys(models).length > 0 ? models : undefined, }; diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 8b04e194..fe959bc9 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -1431,6 +1431,10 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, storeChoice.error); return; } + if (storeChoice.backend === 'env') { + sendBadRequest(res, 'Cannot write apiKey into env; use secretStore=memory|keychain'); + return; + } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; @@ -1443,23 +1447,45 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): storeChoice.backend === 'memory' ? 'http-configure-memory' : 'http-configure'; auditSecretChange({ key: secretName, op: 'set', source: auditSource }); config.providers[providerId].secret_name = secretName; + config.providers[providerId].secret_store = storeChoice.backend; config.providers[providerId].api_key_keychain_name = secretName; delete config.providers[providerId].api_key_env_var_name; } else if (secretNameRef) { - // Reference an existing named secret (N:1 — many providers, one key). - const exists = await state.secretStore.has(secretNameRef); - if (!exists) { - res.status(400).json({ - error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, - }); - return; + const storeRaw = secretStoreBody; + if (storeRaw === 'env') { + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].secret_store = 'env'; + config.providers[providerId].api_key_env_var_name = secretNameRef; + delete config.providers[providerId].api_key_keychain_name; + } else if (storeRaw === 'memory' || storeRaw === 'keychain') { + const exists = await state.secretStore.has(secretNameRef); + if (!exists) { + res.status(400).json({ + error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, + }); + return; + } + config.providers[providerId].secret_name = secretNameRef; + config.providers[providerId].secret_store = storeRaw; + config.providers[providerId].api_key_keychain_name = secretNameRef; + delete config.providers[providerId].api_key_env_var_name; + } else { + const exists = await state.secretStore.has(secretNameRef); + if (!exists) { + res.status(400).json({ + error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, + }); + return; + } + config.providers[providerId].secret_name = secretNameRef; + delete config.providers[providerId].secret_store; + config.providers[providerId].api_key_keychain_name = secretNameRef; + delete config.providers[providerId].api_key_env_var_name; } - config.providers[providerId].secret_name = secretNameRef; - config.providers[providerId].api_key_keychain_name = secretNameRef; - delete config.providers[providerId].api_key_env_var_name; } else if (envVarName) { + config.providers[providerId].secret_name = envVarName; + config.providers[providerId].secret_store = 'env'; config.providers[providerId].api_key_env_var_name = envVarName; - delete config.providers[providerId].secret_name; delete config.providers[providerId].api_key_keychain_name; } diff --git a/packages/daemon/tests/integration/consumer-auth.test.ts b/packages/daemon/tests/integration/consumer-auth.test.ts index e2a542d9..af964a01 100644 --- a/packages/daemon/tests/integration/consumer-auth.test.ts +++ b/packages/daemon/tests/integration/consumer-auth.test.ts @@ -307,6 +307,49 @@ describe('Consumer auth RPC gating', () => { ).rejects.toMatchObject({ code: grpc.status.INVALID_ARGUMENT }); }); + it('ConfigureProvider references env via secret_store=env', async () => { + process.env.ABBENAY_TEST_PROVIDER_ENV = 'sk-from-env'; + try { + const res = await callUnary(client, 'ConfigureProvider', { + provider_id: 'env-openai', + engine: 'mock', + secret_name: 'ABBENAY_TEST_PROVIDER_ENV', + secret_store: 'SECRET_STORE_ENV', + }, GOOD_TOKEN); + expect(res.success).toBe(true); + + const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { + providers: { + 'env-openai': { + secret_name?: string; + secret_store?: string; + api_key_env_var_name?: string; + }; + }; + }; + expect(saved.providers['env-openai'].secret_name).toBe('ABBENAY_TEST_PROVIDER_ENV'); + expect(saved.providers['env-openai'].secret_store).toBe('env'); + expect(saved.providers['env-openai'].api_key_env_var_name).toBe('ABBENAY_TEST_PROVIDER_ENV'); + } finally { + delete process.env.ABBENAY_TEST_PROVIDER_ENV; + } + }); + + it('ConfigureProvider rejects secret_store=env is not required when unset', async () => { + delete process.env.ABBENAY_TEST_PROVIDER_ENV_MISSING; + const res = await callUnary(client, 'ConfigureProvider', { + provider_id: 'env-missing', + engine: 'mock', + secret_name: 'ABBENAY_TEST_PROVIDER_ENV_MISSING', + secret_store: 'SECRET_STORE_ENV', + }, GOOD_TOKEN); + expect(res.success).toBe(true); + const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { + providers: { 'env-missing': { secret_store?: string } }; + }; + expect(saved.providers['env-missing'].secret_store).toBe('env'); + }); + it('ConfigureProvider stores api_key under an explicit secret_name', async () => { const res = await callUnary(client, 'ConfigureProvider', { provider_id: 'named-write', diff --git a/packages/proto-ts/src/abbenay/v1/service.ts b/packages/proto-ts/src/abbenay/v1/service.ts index b52a0dfd..04ba55eb 100644 --- a/packages/proto-ts/src/abbenay/v1/service.ts +++ b/packages/proto-ts/src/abbenay/v1/service.ts @@ -1090,12 +1090,19 @@ export interface Config_ConsumersEntry { export interface FullProviderConfig { engine: string; /** deprecated: use secret_name */ - apiKeyKeychainName?: string | undefined; + apiKeyKeychainName?: + | string + | undefined; + /** deprecated: use secret_name + secret_store=env */ apiKeyEnvVarName?: string | undefined; baseUrl?: string | undefined; models: { [key: string]: ModelParamConfig }; - /** Logical secret store name (preferred) */ - secretName?: string | undefined; + /** Logical name (store key or env var) */ + secretName?: + | string + | undefined; + /** MEMORY | KEYCHAIN | ENV */ + secretStore?: SecretStore | undefined; } export interface FullProviderConfig_ModelsEntry { @@ -10913,6 +10920,7 @@ function createBaseFullProviderConfig(): FullProviderConfig { baseUrl: undefined, models: {}, secretName: undefined, + secretStore: undefined, }; } @@ -10936,6 +10944,9 @@ export const FullProviderConfig: MessageFns = { if (message.secretName !== undefined) { writer.uint32(50).string(message.secretName); } + if (message.secretStore !== undefined) { + writer.uint32(56).int32(message.secretStore); + } return writer; }, @@ -10997,6 +11008,14 @@ export const FullProviderConfig: MessageFns = { message.secretName = reader.string(); continue; } + case 7: { + if (tag !== 56) { + break; + } + + message.secretStore = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -11038,6 +11057,11 @@ export const FullProviderConfig: MessageFns = { : isSet(object.secret_name) ? globalThis.String(object.secret_name) : undefined, + secretStore: isSet(object.secretStore) + ? secretStoreFromJSON(object.secretStore) + : isSet(object.secret_store) + ? secretStoreFromJSON(object.secret_store) + : undefined, }; }, @@ -11067,6 +11091,9 @@ export const FullProviderConfig: MessageFns = { if (message.secretName !== undefined) { obj.secretName = message.secretName; } + if (message.secretStore !== undefined) { + obj.secretStore = secretStoreToJSON(message.secretStore); + } return obj; }, @@ -11089,6 +11116,7 @@ export const FullProviderConfig: MessageFns = { {}, ); message.secretName = object.secretName ?? undefined; + message.secretStore = object.secretStore ?? undefined; return message; }, }; diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py index 4054c8b2..763c4195 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xf5\x02\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_name\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xba\x03\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x32\n\x0csecret_store\x18\x07 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x04\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -57,20 +57,20 @@ _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_options = b'8\001' _globals['_MCPTRANSPORT_ENVENTRY']._loaded_options = None _globals['_MCPTRANSPORT_ENVENTRY']._serialized_options = b'8\001' - _globals['_ROLE']._serialized_start=18322 - _globals['_ROLE']._serialized_end=18417 - _globals['_CLIENTTYPE']._serialized_start=18420 - _globals['_CLIENTTYPE']._serialized_end=18575 - _globals['_REPLAYFORMAT']._serialized_start=18578 - _globals['_REPLAYFORMAT']._serialized_end=18708 - _globals['_MODELSOURCE']._serialized_start=18710 - _globals['_MODELSOURCE']._serialized_end=18806 - _globals['_PROVIDERTYPE']._serialized_start=18808 - _globals['_PROVIDERTYPE']._serialized_end=18925 - _globals['_LOGLEVEL']._serialized_start=18928 - _globals['_LOGLEVEL']._serialized_end=19068 - _globals['_SECRETSTORE']._serialized_start=19070 - _globals['_SECRETSTORE']._serialized_end=19187 + _globals['_ROLE']._serialized_start=18391 + _globals['_ROLE']._serialized_end=18486 + _globals['_CLIENTTYPE']._serialized_start=18489 + _globals['_CLIENTTYPE']._serialized_end=18644 + _globals['_REPLAYFORMAT']._serialized_start=18647 + _globals['_REPLAYFORMAT']._serialized_end=18777 + _globals['_MODELSOURCE']._serialized_start=18779 + _globals['_MODELSOURCE']._serialized_end=18875 + _globals['_PROVIDERTYPE']._serialized_start=18877 + _globals['_PROVIDERTYPE']._serialized_end=18994 + _globals['_LOGLEVEL']._serialized_start=18997 + _globals['_LOGLEVEL']._serialized_end=19137 + _globals['_SECRETSTORE']._serialized_start=19139 + _globals['_SECRETSTORE']._serialized_end=19256 _globals['_EMPTY']._serialized_start=40 _globals['_EMPTY']._serialized_end=47 _globals['_TIMESTAMP']._serialized_start=49 @@ -260,169 +260,169 @@ _globals['_CONFIG_CONSUMERSENTRY']._serialized_start=9576 _globals['_CONFIG_CONSUMERSENTRY']._serialized_end=9655 _globals['_FULLPROVIDERCONFIG']._serialized_start=9658 - _globals['_FULLPROVIDERCONFIG']._serialized_end=10031 - _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_start=9876 - _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_end=9951 - _globals['_MODELPARAMCONFIG']._serialized_start=10034 - _globals['_MODELPARAMCONFIG']._serialized_end=10398 - _globals['_MCPSERVERCONFIGMSG']._serialized_start=10401 - _globals['_MCPSERVERCONFIGMSG']._serialized_end=10793 - _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_start=10661 - _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_end=10707 - _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_start=10709 - _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_end=10751 - _globals['_TOOLPOLICYCONFIGMSG']._serialized_start=10796 - _globals['_TOOLPOLICYCONFIGMSG']._serialized_end=11058 - _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_start=10988 - _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_end=11034 - _globals['_CONSUMERCONFIGMSG']._serialized_start=11061 - _globals['_CONSUMERCONFIGMSG']._serialized_end=11225 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11228 - _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11511 - _globals['_UPDATECONFIGREQUEST']._serialized_start=11513 - _globals['_UPDATECONFIGREQUEST']._serialized_end=11606 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11609 - _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=11993 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=11995 - _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=12039 - _globals['_REMOVEPROVIDERREQUEST']._serialized_start=12041 - _globals['_REMOVEPROVIDERREQUEST']._serialized_end=12165 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=12167 - _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=12196 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=12198 - _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=12277 - _globals['_PROVIDERTEMPLATE']._serialized_start=12280 - _globals['_PROVIDERTEMPLATE']._serialized_end=12412 - _globals['_GETKEYSTATUSREQUEST']._serialized_start=12414 - _globals['_GETKEYSTATUSREQUEST']._serialized_end=12465 - _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12467 - _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12505 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12507 - _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12536 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12538 - _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12623 - _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12626 - _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12762 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12764 - _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12810 - _globals['_CREATEPOLICYREQUEST']._serialized_start=12812 - _globals['_CREATEPOLICYREQUEST']._serialized_end=12889 - _globals['_DELETEPOLICYREQUEST']._serialized_start=12891 - _globals['_DELETEPOLICYREQUEST']._serialized_end=12926 - _globals['_GETSECRETREQUEST']._serialized_start=12928 - _globals['_GETSECRETREQUEST']._serialized_end=12959 - _globals['_GETSECRETRESPONSE']._serialized_start=12961 - _globals['_GETSECRETRESPONSE']._serialized_end=12995 - _globals['_SETSECRETREQUEST']._serialized_start=12997 - _globals['_SETSECRETREQUEST']._serialized_end=13083 - _globals['_DELETESECRETREQUEST']._serialized_start=13085 - _globals['_DELETESECRETREQUEST']._serialized_end=13119 - _globals['_LISTSECRETSREQUEST']._serialized_start=13121 - _globals['_LISTSECRETSREQUEST']._serialized_end=13141 - _globals['_LISTSECRETSRESPONSE']._serialized_start=13143 - _globals['_LISTSECRETSRESPONSE']._serialized_end=13205 - _globals['_SECRETINFO']._serialized_start=13207 - _globals['_SECRETINFO']._serialized_end=13291 - _globals['_REGISTERREQUEST']._serialized_start=13293 - _globals['_REGISTERREQUEST']._serialized_end=13419 - _globals['_REGISTERRESPONSE']._serialized_start=13421 - _globals['_REGISTERRESPONSE']._serialized_end=13485 - _globals['_UNREGISTERREQUEST']._serialized_start=13487 - _globals['_UNREGISTERREQUEST']._serialized_end=13525 - _globals['_GETSTATUSREQUEST']._serialized_start=13527 - _globals['_GETSTATUSREQUEST']._serialized_end=13545 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13547 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13578 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13580 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13632 - _globals['_DAEMONSTATUS']._serialized_start=13635 - _globals['_DAEMONSTATUS']._serialized_end=13839 - _globals['_CONNECTEDCLIENT']._serialized_start=13842 - _globals['_CONNECTEDCLIENT']._serialized_end=14012 - _globals['_SHUTDOWNREQUEST']._serialized_start=14014 - _globals['_SHUTDOWNREQUEST']._serialized_end=14076 - _globals['_HEALTHCHECKREQUEST']._serialized_start=14078 - _globals['_HEALTHCHECKREQUEST']._serialized_end=14098 - _globals['_HEALTHCHECKRESPONSE']._serialized_start=14100 - _globals['_HEALTHCHECKRESPONSE']._serialized_end=14155 - _globals['_STARTWEBSERVERREQUEST']._serialized_start=14157 - _globals['_STARTWEBSERVERREQUEST']._serialized_end=14194 - _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14196 - _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14289 - _globals['_STOPWEBSERVERREQUEST']._serialized_start=14291 - _globals['_STOPWEBSERVERREQUEST']._serialized_end=14313 - _globals['_VSCODEREQUEST']._serialized_start=14316 - _globals['_VSCODEREQUEST']._serialized_end=14713 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14715 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14758 - _globals['_VSCODERESPONSE']._serialized_start=14761 - _globals['_VSCODERESPONSE']._serialized_end=15207 - _globals['_GETWORKSPACEREQUEST']._serialized_start=15209 - _globals['_GETWORKSPACEREQUEST']._serialized_end=15230 - _globals['_GETWORKSPACERESPONSE']._serialized_start=15232 - _globals['_GETWORKSPACERESPONSE']._serialized_end=15305 - _globals['_VSCODEERROR']._serialized_start=15307 - _globals['_VSCODEERROR']._serialized_end=15351 - _globals['_INVOKETOOLREQUEST']._serialized_start=15353 - _globals['_INVOKETOOLREQUEST']._serialized_end=15415 - _globals['_INVOKETOOLRESPONSE']._serialized_start=15417 - _globals['_INVOKETOOLRESPONSE']._serialized_end=15476 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15478 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15502 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15504 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15572 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15574 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15644 - _globals['_VSCODETOOLINFO']._serialized_start=15646 - _globals['_VSCODETOOLINFO']._serialized_end=15733 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15735 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15806 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15808 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15875 - _globals['_VSCODEMODEL']._serialized_start=15877 - _globals['_VSCODEMODEL']._serialized_end=15974 - _globals['_SENDVSCODECHATREQUEST']._serialized_start=15977 - _globals['_SENDVSCODECHATREQUEST']._serialized_end=16139 - _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16141 - _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16210 - _globals['_VSCODECHATCHUNK']._serialized_start=16212 - _globals['_VSCODECHATCHUNK']._serialized_end=16303 - _globals['_VSCODETOOLCALL']._serialized_start=16305 - _globals['_VSCODETOOLCALL']._serialized_end=16376 - _globals['_LISTPOLICIESREQUEST']._serialized_start=16378 - _globals['_LISTPOLICIESREQUEST']._serialized_end=16399 - _globals['_LISTPOLICIESRESPONSE']._serialized_start=16401 - _globals['_LISTPOLICIESRESPONSE']._serialized_end=16465 - _globals['_POLICYINFO']._serialized_start=16467 - _globals['_POLICYINFO']._serialized_end=16552 - _globals['_POLICYCONFIG']._serialized_start=16555 - _globals['_POLICYCONFIG']._serialized_end=16877 - _globals['_POLICYSAMPLING']._serialized_start=16879 - _globals['_POLICYSAMPLING']._serialized_end=16997 - _globals['_POLICYOUTPUT']._serialized_start=17000 - _globals['_POLICYOUTPUT']._serialized_end=17268 - _globals['_POLICYCONTEXT']._serialized_start=17271 - _globals['_POLICYCONTEXT']._serialized_end=17400 - _globals['_POLICYTOOL']._serialized_start=17402 - _globals['_POLICYTOOL']._serialized_end=17510 - _globals['_POLICYRELIABILITY']._serialized_start=17512 - _globals['_POLICYRELIABILITY']._serialized_end=17627 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17630 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17835 - _globals['_MCPTRANSPORT']._serialized_start=17838 - _globals['_MCPTRANSPORT']._serialized_end=18136 - _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10661 - _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10707 - _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10709 - _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10751 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18138 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18223 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18225 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18272 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18274 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18320 - _globals['_MCPBRIDGE']._serialized_start=19190 - _globals['_MCPBRIDGE']._serialized_end=19861 - _globals['_ABBENAY']._serialized_start=19864 - _globals['_ABBENAY']._serialized_end=23450 + _globals['_FULLPROVIDERCONFIG']._serialized_end=10100 + _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_start=9928 + _globals['_FULLPROVIDERCONFIG_MODELSENTRY']._serialized_end=10003 + _globals['_MODELPARAMCONFIG']._serialized_start=10103 + _globals['_MODELPARAMCONFIG']._serialized_end=10467 + _globals['_MCPSERVERCONFIGMSG']._serialized_start=10470 + _globals['_MCPSERVERCONFIGMSG']._serialized_end=10862 + _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_start=10730 + _globals['_MCPSERVERCONFIGMSG_HEADERSENTRY']._serialized_end=10776 + _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_start=10778 + _globals['_MCPSERVERCONFIGMSG_ENVENTRY']._serialized_end=10820 + _globals['_TOOLPOLICYCONFIGMSG']._serialized_start=10865 + _globals['_TOOLPOLICYCONFIGMSG']._serialized_end=11127 + _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_start=11057 + _globals['_TOOLPOLICYCONFIGMSG_ALIASESENTRY']._serialized_end=11103 + _globals['_CONSUMERCONFIGMSG']._serialized_start=11130 + _globals['_CONSUMERCONFIGMSG']._serialized_end=11294 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_start=11297 + _globals['_CONSUMERCAPABILITIESMSG']._serialized_end=11580 + _globals['_UPDATECONFIGREQUEST']._serialized_start=11582 + _globals['_UPDATECONFIGREQUEST']._serialized_end=11675 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_start=11678 + _globals['_CONFIGUREPROVIDERREQUEST']._serialized_end=12062 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_start=12064 + _globals['_CONFIGUREPROVIDERRESPONSE']._serialized_end=12108 + _globals['_REMOVEPROVIDERREQUEST']._serialized_start=12110 + _globals['_REMOVEPROVIDERREQUEST']._serialized_end=12234 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_start=12236 + _globals['_GETPROVIDERTEMPLATESREQUEST']._serialized_end=12265 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_start=12267 + _globals['_GETPROVIDERTEMPLATESRESPONSE']._serialized_end=12346 + _globals['_PROVIDERTEMPLATE']._serialized_start=12349 + _globals['_PROVIDERTEMPLATE']._serialized_end=12481 + _globals['_GETKEYSTATUSREQUEST']._serialized_start=12483 + _globals['_GETKEYSTATUSREQUEST']._serialized_end=12534 + _globals['_GETKEYSTATUSRESPONSE']._serialized_start=12536 + _globals['_GETKEYSTATUSRESPONSE']._serialized_end=12574 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_start=12576 + _globals['_LISTMCPSERVERCONFIGSREQUEST']._serialized_end=12605 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_start=12607 + _globals['_LISTMCPSERVERCONFIGSRESPONSE']._serialized_end=12692 + _globals['_MCPSERVERSTATUSENTRY']._serialized_start=12695 + _globals['_MCPSERVERSTATUSENTRY']._serialized_end=12831 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_start=12833 + _globals['_RECONNECTMCPSERVERREQUEST']._serialized_end=12879 + _globals['_CREATEPOLICYREQUEST']._serialized_start=12881 + _globals['_CREATEPOLICYREQUEST']._serialized_end=12958 + _globals['_DELETEPOLICYREQUEST']._serialized_start=12960 + _globals['_DELETEPOLICYREQUEST']._serialized_end=12995 + _globals['_GETSECRETREQUEST']._serialized_start=12997 + _globals['_GETSECRETREQUEST']._serialized_end=13028 + _globals['_GETSECRETRESPONSE']._serialized_start=13030 + _globals['_GETSECRETRESPONSE']._serialized_end=13064 + _globals['_SETSECRETREQUEST']._serialized_start=13066 + _globals['_SETSECRETREQUEST']._serialized_end=13152 + _globals['_DELETESECRETREQUEST']._serialized_start=13154 + _globals['_DELETESECRETREQUEST']._serialized_end=13188 + _globals['_LISTSECRETSREQUEST']._serialized_start=13190 + _globals['_LISTSECRETSREQUEST']._serialized_end=13210 + _globals['_LISTSECRETSRESPONSE']._serialized_start=13212 + _globals['_LISTSECRETSRESPONSE']._serialized_end=13274 + _globals['_SECRETINFO']._serialized_start=13276 + _globals['_SECRETINFO']._serialized_end=13360 + _globals['_REGISTERREQUEST']._serialized_start=13362 + _globals['_REGISTERREQUEST']._serialized_end=13488 + _globals['_REGISTERRESPONSE']._serialized_start=13490 + _globals['_REGISTERRESPONSE']._serialized_end=13554 + _globals['_UNREGISTERREQUEST']._serialized_start=13556 + _globals['_UNREGISTERREQUEST']._serialized_end=13594 + _globals['_GETSTATUSREQUEST']._serialized_start=13596 + _globals['_GETSTATUSREQUEST']._serialized_end=13614 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13616 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13647 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13649 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13701 + _globals['_DAEMONSTATUS']._serialized_start=13704 + _globals['_DAEMONSTATUS']._serialized_end=13908 + _globals['_CONNECTEDCLIENT']._serialized_start=13911 + _globals['_CONNECTEDCLIENT']._serialized_end=14081 + _globals['_SHUTDOWNREQUEST']._serialized_start=14083 + _globals['_SHUTDOWNREQUEST']._serialized_end=14145 + _globals['_HEALTHCHECKREQUEST']._serialized_start=14147 + _globals['_HEALTHCHECKREQUEST']._serialized_end=14167 + _globals['_HEALTHCHECKRESPONSE']._serialized_start=14169 + _globals['_HEALTHCHECKRESPONSE']._serialized_end=14224 + _globals['_STARTWEBSERVERREQUEST']._serialized_start=14226 + _globals['_STARTWEBSERVERREQUEST']._serialized_end=14263 + _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14265 + _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14358 + _globals['_STOPWEBSERVERREQUEST']._serialized_start=14360 + _globals['_STOPWEBSERVERREQUEST']._serialized_end=14382 + _globals['_VSCODEREQUEST']._serialized_start=14385 + _globals['_VSCODEREQUEST']._serialized_end=14782 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14784 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14827 + _globals['_VSCODERESPONSE']._serialized_start=14830 + _globals['_VSCODERESPONSE']._serialized_end=15276 + _globals['_GETWORKSPACEREQUEST']._serialized_start=15278 + _globals['_GETWORKSPACEREQUEST']._serialized_end=15299 + _globals['_GETWORKSPACERESPONSE']._serialized_start=15301 + _globals['_GETWORKSPACERESPONSE']._serialized_end=15374 + _globals['_VSCODEERROR']._serialized_start=15376 + _globals['_VSCODEERROR']._serialized_end=15420 + _globals['_INVOKETOOLREQUEST']._serialized_start=15422 + _globals['_INVOKETOOLREQUEST']._serialized_end=15484 + _globals['_INVOKETOOLRESPONSE']._serialized_start=15486 + _globals['_INVOKETOOLRESPONSE']._serialized_end=15545 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15547 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15571 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15573 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15641 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15643 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15713 + _globals['_VSCODETOOLINFO']._serialized_start=15715 + _globals['_VSCODETOOLINFO']._serialized_end=15802 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15804 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15875 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15877 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15944 + _globals['_VSCODEMODEL']._serialized_start=15946 + _globals['_VSCODEMODEL']._serialized_end=16043 + _globals['_SENDVSCODECHATREQUEST']._serialized_start=16046 + _globals['_SENDVSCODECHATREQUEST']._serialized_end=16208 + _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16210 + _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16279 + _globals['_VSCODECHATCHUNK']._serialized_start=16281 + _globals['_VSCODECHATCHUNK']._serialized_end=16372 + _globals['_VSCODETOOLCALL']._serialized_start=16374 + _globals['_VSCODETOOLCALL']._serialized_end=16445 + _globals['_LISTPOLICIESREQUEST']._serialized_start=16447 + _globals['_LISTPOLICIESREQUEST']._serialized_end=16468 + _globals['_LISTPOLICIESRESPONSE']._serialized_start=16470 + _globals['_LISTPOLICIESRESPONSE']._serialized_end=16534 + _globals['_POLICYINFO']._serialized_start=16536 + _globals['_POLICYINFO']._serialized_end=16621 + _globals['_POLICYCONFIG']._serialized_start=16624 + _globals['_POLICYCONFIG']._serialized_end=16946 + _globals['_POLICYSAMPLING']._serialized_start=16948 + _globals['_POLICYSAMPLING']._serialized_end=17066 + _globals['_POLICYOUTPUT']._serialized_start=17069 + _globals['_POLICYOUTPUT']._serialized_end=17337 + _globals['_POLICYCONTEXT']._serialized_start=17340 + _globals['_POLICYCONTEXT']._serialized_end=17469 + _globals['_POLICYTOOL']._serialized_start=17471 + _globals['_POLICYTOOL']._serialized_end=17579 + _globals['_POLICYRELIABILITY']._serialized_start=17581 + _globals['_POLICYRELIABILITY']._serialized_end=17696 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17699 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17904 + _globals['_MCPTRANSPORT']._serialized_start=17907 + _globals['_MCPTRANSPORT']._serialized_end=18205 + _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10730 + _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10776 + _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10778 + _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10820 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18207 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18292 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18294 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18341 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18343 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18389 + _globals['_MCPBRIDGE']._serialized_start=19259 + _globals['_MCPBRIDGE']._serialized_end=19930 + _globals['_ABBENAY']._serialized_start=19933 + _globals['_ABBENAY']._serialized_end=23519 # @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi index 56bd7cad..762fd3c1 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi @@ -990,7 +990,7 @@ class Config(_message.Message): def __init__(self, providers: _Optional[_Mapping[str, FullProviderConfig]] = ..., mcp_servers: _Optional[_Mapping[str, McpServerConfigMsg]] = ..., tool_policy: _Optional[_Union[ToolPolicyConfigMsg, _Mapping]] = ..., consumers: _Optional[_Mapping[str, ConsumerConfigMsg]] = ...) -> None: ... class FullProviderConfig(_message.Message): - __slots__ = ("engine", "api_key_keychain_name", "api_key_env_var_name", "base_url", "models", "secret_name") + __slots__ = ("engine", "api_key_keychain_name", "api_key_env_var_name", "base_url", "models", "secret_name", "secret_store") class ModelsEntry(_message.Message): __slots__ = ("key", "value") KEY_FIELD_NUMBER: _ClassVar[int] @@ -1004,13 +1004,15 @@ class FullProviderConfig(_message.Message): BASE_URL_FIELD_NUMBER: _ClassVar[int] MODELS_FIELD_NUMBER: _ClassVar[int] SECRET_NAME_FIELD_NUMBER: _ClassVar[int] + SECRET_STORE_FIELD_NUMBER: _ClassVar[int] engine: str api_key_keychain_name: str api_key_env_var_name: str base_url: str models: _containers.MessageMap[str, ModelParamConfig] secret_name: str - def __init__(self, engine: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ..., api_key_env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., models: _Optional[_Mapping[str, ModelParamConfig]] = ..., secret_name: _Optional[str] = ...) -> None: ... + secret_store: SecretStore + def __init__(self, engine: _Optional[str] = ..., api_key_keychain_name: _Optional[str] = ..., api_key_env_var_name: _Optional[str] = ..., base_url: _Optional[str] = ..., models: _Optional[_Mapping[str, ModelParamConfig]] = ..., secret_name: _Optional[str] = ..., secret_store: _Optional[_Union[SecretStore, str]] = ...) -> None: ... class ModelParamConfig(_message.Message): __slots__ = ("model_id", "policy", "system_prompt", "system_prompt_mode", "temperature", "top_p", "top_k", "max_tokens", "timeout") diff --git a/packages/vscode/src/proto/abbenay/v1/service.ts b/packages/vscode/src/proto/abbenay/v1/service.ts index b52a0dfd..04ba55eb 100644 --- a/packages/vscode/src/proto/abbenay/v1/service.ts +++ b/packages/vscode/src/proto/abbenay/v1/service.ts @@ -1090,12 +1090,19 @@ export interface Config_ConsumersEntry { export interface FullProviderConfig { engine: string; /** deprecated: use secret_name */ - apiKeyKeychainName?: string | undefined; + apiKeyKeychainName?: + | string + | undefined; + /** deprecated: use secret_name + secret_store=env */ apiKeyEnvVarName?: string | undefined; baseUrl?: string | undefined; models: { [key: string]: ModelParamConfig }; - /** Logical secret store name (preferred) */ - secretName?: string | undefined; + /** Logical name (store key or env var) */ + secretName?: + | string + | undefined; + /** MEMORY | KEYCHAIN | ENV */ + secretStore?: SecretStore | undefined; } export interface FullProviderConfig_ModelsEntry { @@ -10913,6 +10920,7 @@ function createBaseFullProviderConfig(): FullProviderConfig { baseUrl: undefined, models: {}, secretName: undefined, + secretStore: undefined, }; } @@ -10936,6 +10944,9 @@ export const FullProviderConfig: MessageFns = { if (message.secretName !== undefined) { writer.uint32(50).string(message.secretName); } + if (message.secretStore !== undefined) { + writer.uint32(56).int32(message.secretStore); + } return writer; }, @@ -10997,6 +11008,14 @@ export const FullProviderConfig: MessageFns = { message.secretName = reader.string(); continue; } + case 7: { + if (tag !== 56) { + break; + } + + message.secretStore = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -11038,6 +11057,11 @@ export const FullProviderConfig: MessageFns = { : isSet(object.secret_name) ? globalThis.String(object.secret_name) : undefined, + secretStore: isSet(object.secretStore) + ? secretStoreFromJSON(object.secretStore) + : isSet(object.secret_store) + ? secretStoreFromJSON(object.secret_store) + : undefined, }; }, @@ -11067,6 +11091,9 @@ export const FullProviderConfig: MessageFns = { if (message.secretName !== undefined) { obj.secretName = message.secretName; } + if (message.secretStore !== undefined) { + obj.secretStore = secretStoreToJSON(message.secretStore); + } return obj; }, @@ -11089,6 +11116,7 @@ export const FullProviderConfig: MessageFns = { {}, ); message.secretName = object.secretName ?? undefined; + message.secretStore = object.secretStore ?? undefined; return message; }, }; diff --git a/proto/abbenay/v1/service.proto b/proto/abbenay/v1/service.proto index 6fa94771..b4e68ba7 100644 --- a/proto/abbenay/v1/service.proto +++ b/proto/abbenay/v1/service.proto @@ -855,10 +855,11 @@ message Config { message FullProviderConfig { string engine = 1; optional string api_key_keychain_name = 2; // deprecated: use secret_name - optional string api_key_env_var_name = 3; + optional string api_key_env_var_name = 3; // deprecated: use secret_name + secret_store=env optional string base_url = 4; map models = 5; - optional string secret_name = 6; // Logical secret store name (preferred) + optional string secret_name = 6; // Logical name (store key or env var) + optional SecretStore secret_store = 7; // MEMORY | KEYCHAIN | ENV } message ModelParamConfig { From 03bd64fc48537b917e5e85734076b3f8abbd4632 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:20:28 -0700 Subject: [PATCH 05/18] fix(daemon): narrow secret_store writes to memory|keychain for tsc parseSecretStoreChoice overloads so SetSecret/configure writes type as SecretBackend; env remains configure/reference-only and CI builds again. --- packages/daemon/src/daemon/secrets/dual.ts | 8 ++++++++ packages/daemon/src/daemon/server/abbenay-service.ts | 9 +-------- packages/daemon/src/daemon/web/server.ts | 4 ---- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/daemon/src/daemon/secrets/dual.ts b/packages/daemon/src/daemon/secrets/dual.ts index a6369d9b..cf221519 100644 --- a/packages/daemon/src/daemon/secrets/dual.ts +++ b/packages/daemon/src/daemon/secrets/dual.ts @@ -118,6 +118,14 @@ export function isDualSecretStore(store: SecretStore): store is DualSecretStore * Unspecified / omitted / keychain → keychain (default for writes). * ENV rejected for writes unless `allowEnv` (configure/reference only). */ +export function parseSecretStoreChoice( + store: unknown, + opts: { allowEnv: true }, +): { ok: true; backend: SecretStoreKind } | { ok: false; error: string }; +export function parseSecretStoreChoice( + store: unknown, + opts?: { allowEnv?: false | undefined }, +): { ok: true; backend: SecretBackend } | { ok: false; error: string }; export function parseSecretStoreChoice( store: unknown, opts?: { allowEnv?: boolean }, diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index dece2f56..b687db96 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -1798,18 +1798,11 @@ export function createAbbenayService( }); return; } - if (storeChoice.backend === 'env') { - callback({ - code: grpc.status.INVALID_ARGUMENT, - message: 'Cannot write api_key into env; use secret_store=memory|keychain', - }); - return; - } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; if (dual) { - await dual.setIn(storeChoice.backend as 'memory' | 'keychain', secretName, apiKey); + await dual.setIn(storeChoice.backend, secretName, apiKey); } else { await state.secretStore.set(secretName, apiKey); } diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index fe959bc9..01f4cc8e 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -1431,10 +1431,6 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, storeChoice.error); return; } - if (storeChoice.backend === 'env') { - sendBadRequest(res, 'Cannot write apiKey into env; use secretStore=memory|keychain'); - return; - } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; From 3d060c4b6e2ae0abff7d787b29b52ce8505e9300 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:37:26 -0700 Subject: [PATCH 06/18] refactor(daemon): namespace secrets by (store, name) via SecretStoreRegistry Drop move-on-write DualSecretStore so memory and keychain stay discrete; providers resolve only their configured backend, positioning N pluggable stores. --- docs/ARCHITECTURE.md | 12 +- docs/CONFIGURATION.md | 24 +- docs/SECURITY.md | 7 +- docs/decisions.md | 47 ++-- packages/daemon/src/core/config.ts | 16 +- packages/daemon/src/core/index.ts | 4 +- packages/daemon/src/core/secrets.ts | 26 +- packages/daemon/src/core/state.ts | 6 +- .../daemon/src/daemon/secrets/dual.test.ts | 140 ---------- packages/daemon/src/daemon/secrets/dual.ts | 169 ------------ .../src/daemon/secrets/registry.test.ts | 129 +++++++++ .../daemon/src/daemon/secrets/registry.ts | 171 ++++++++++++ .../src/daemon/server/abbenay-service.ts | 111 ++++++-- packages/daemon/src/daemon/state.ts | 4 +- packages/daemon/src/daemon/web/server.ts | 101 ++++--- .../integration/grpc-real-service.test.ts | 32 ++- packages/proto-ts/src/abbenay/v1/service.ts | 50 +++- .../abbenay_grpc/abbenay/v1/service_pb2.py | 252 +++++++++--------- .../abbenay_grpc/abbenay/v1/service_pb2.pyi | 12 +- .../vscode/src/proto/abbenay/v1/service.ts | 50 +++- proto/abbenay/v1/service.proto | 4 +- 21 files changed, 801 insertions(+), 566 deletions(-) delete mode 100644 packages/daemon/src/daemon/secrets/dual.test.ts delete mode 100644 packages/daemon/src/daemon/secrets/dual.ts create mode 100644 packages/daemon/src/daemon/secrets/registry.test.ts create mode 100644 packages/daemon/src/daemon/secrets/registry.ts diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4d117cd1..a7896ddc 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -32,7 +32,7 @@ Abbenay is a unified AI daemon and library written in TypeScript/Node.js that pr │ │ │ ┌─ daemon layer ────────────────────────────────────────────────────┐ │ │ │ DaemonState gRPC Server VS Code Backchannel │ │ -│ │ CLI (Commander) Web Dashboard (Express) DualSecretStore │ │ +│ │ CLI (Commander) Web Dashboard (Express) SecretStoreRegistry │ │ │ └───────────────────────────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────┬──────────────────────────────┘ @@ -87,8 +87,8 @@ Full application layer. Extends core with transport, UI, and CLI. | `daemon/web/server.ts` | Express web server + REST API | | `daemon/web/openai-compat.ts` | OpenAI-compatible `/v1/*` routes (models, chat completions) | | `daemon/web/grpc-web-control.ts` | gRPC client for web server control | +| `daemon/secrets/registry.ts` | `SecretStoreRegistry` (memory + keychain namespaces) | | `daemon/secrets/keychain.ts` | `KeychainSecretStore` (keytar native addon) | -| `daemon/secrets/dual.ts` | `DualSecretStore` (memory + keychain, move-on-write) | ## Components @@ -206,9 +206,11 @@ interface SecretStore { ``` `CoreState` accepts any `SecretStore` via constructor injection. `DaemonState` -uses `DualSecretStore` (process-lifetime `MemorySecretStore` + keytar-backed -`KeychainSecretStore`) by default. Tests and library consumers can use -`MemorySecretStore` alone. +uses `SecretStoreRegistry` (discrete process-lifetime `MemorySecretStore` + +keytar-backed `KeychainSecretStore` namespaces; resolve via +`(secret_store, secret_name)`) by default. Tests and library consumers can +use `MemorySecretStore` alone. `NamespacedSecretStore` extends the interface +for multi-backend `getFrom` / `setIn` / … ## Configuration diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index b62de82c..951b6df6 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -382,12 +382,15 @@ Legacy sessions without an `owner` field are treated as `local`. Each provider can specify exactly ONE of these (mutually exclusive): -### Option 1: Secret store (`secret_name` + optional `secret_store`) +### Option 1: Secret store (`secret_name` + `secret_store`) -- `secret_name` is the logical name -- `secret_store` is where it lives: - - omitted / `keychain` / `memory` → daemon secret store (OS keychain or process memory) +- `secret_name` is the logical name within a backend +- `secret_store` selects the namespace: + - `keychain` (default when omitted) → OS keychain + - `memory` → process-lifetime daemon memory - `env` → process environment variable named `secret_name` +- The same `secret_name` may exist in more than one store; resolve uses only + the provider's `secret_store` (no overlay) - Legacy aliases: `api_key_keychain_name`, `api_key_env_var_name` ```yaml @@ -395,7 +398,7 @@ providers: my-openai: engine: openai secret_name: "OPENAI_API_KEY" - # secret_store: keychain # optional; memory|keychain use the secret store + secret_store: keychain # optional; defaults to keychain ``` ```yaml @@ -408,19 +411,20 @@ providers: ### Option 1b: In-memory (process-lifetime) via secrets API -- Same `secret_name`; set value with `SetSecret` / `POST /api/secrets` and - `secret_store: memory` (SetSecret still cannot write `env`) +- Same `secret_name` in the `memory` namespace; set value with `SetSecret` / + `POST /api/secrets` and `secret_store: memory` (SetSecret still cannot + write `env`) - Lives only while the daemon process is running -- Mutually exclusive with keychain for the same key name (DR-047) +- Independent from keychain — overlapping names are allowed (DR-047) ### Recommended workflow (keys are N:1 with providers) 1. **Add a secret** (store) — `SetSecret` with `secret_store=memory|keychain`, **or** export an env var yourself. -2. **Configure the provider** — `secret_name=NAME` and optional +2. **Configure the provider** — `secret_name=NAME` and `secret_store=memory|keychain|env`. For `env`, the variable is resolved at request time (it need not exist at configure time). -3. Many providers may share one `secret_name`. +3. Many providers may share one `(secret_store, secret_name)` pair. ### Option 2: Environment Variable (legacy `api_key_env_var_name`) diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 59706d51..6ef59b08 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -65,9 +65,10 @@ defaults (or stronger) in place. - `--host 0.0.0.0`, `ABBENAY_HTTP_AUTH=0`, and `--insecure` deliberately weaken posture. - Cloud providers still receive prompts if you configure them. - HTTP on loopback remains plaintext; use a TLS-terminating proxy when exposing beyond the machine. -- In-memory secrets (DR-047) are not written to disk or the OS keychain, but - they remain readable by any authenticated client with the `secrets` - capability for the life of the daemon process. Restart clears them; treat +- In-memory secrets (DR-047) live in a discrete `memory` namespace (not written + to disk or the OS keychain). Providers must set `secret_store: memory` to + resolve them. Authenticated clients with the `secrets` capability can still + read them for the life of the daemon process. Restart clears them; treat RAM and process dumps accordingly. --- diff --git a/docs/decisions.md b/docs/decisions.md index ac98e842..36f1bd6b 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -834,29 +834,30 @@ Numbered DR-046 because main already shipped VS Code webview UX as DR-045. ## DR-047: Process-lifetime in-memory secret store **Date:** 2026-08-12 -**Decision:** The daemon secret store is a dual backend (`DualSecretStore`): -OS keychain (persistent) and process-lifetime memory. Clients select the -backend via gRPC `SetSecretRequest.store` (`SECRET_STORE_MEMORY` / -`SECRET_STORE_KEYCHAIN`) or HTTP `store: "memory" | "keychain"` (default -keychain). The same key name lives in exactly one backend: writing to one -deletes that key from the other (move-on-write). Memory secrets survive -until consumer delete/set or daemon restart — no TTL and no clear-on- -disconnect. `SECRET_STORE_ENV` is rejected on write; env credentials remain -read-only via provider `api_key_env_var_name`. Configure / `addProvider` -continue to write keychain only. `api_key_keychain_name` remains a logical -lookup name into the composite store (not “must be OS keychain”). -Provider config prefers `secret_name` (legacy alias `api_key_keychain_name`). -`secret_store` is `memory` | `keychain` | `env`: env means resolve -`secret_name` from `process.env` (configure/reference only — SetSecret still -rejects ENV writes). `ConfigureProvider` accepts `secret_name` + optional -`secret_store` to reference an existing secret or env var (N providers → 1 -key). Raw `api_key` alone remains a legacy shortcut that invents -`${PROVIDER_ID}_API_KEY`. Legacy `api_key_env_var_name` maps to -`secret_name` + `secret_store: env` on load. +**Decision:** The daemon exposes discrete secret backends via +`SecretStoreRegistry` (OS keychain + process-lifetime memory today). Values are +addressed by `(secret_store, secret_name)` — the same name may exist in more +than one backend. Clients select the backend on write via gRPC +`SetSecretRequest.store` (`SECRET_STORE_MEMORY` / `SECRET_STORE_KEYCHAIN`) or +HTTP `secret_store: "memory" | "keychain"` (default keychain). Get/Delete +take the same store field (default keychain). Provider config records both +`secret_name` and `secret_store`; resolve reads only that backend (no +cross-store overlay). Memory secrets survive until consumer delete/set or +daemon restart — no TTL and no clear-on-disconnect. `SECRET_STORE_ENV` is +rejected on write; env credentials are configure/reference only +(`secret_store: env` → `process.env[secret_name]`). `ConfigureProvider` +accepts `secret_name` + optional `secret_store` to reference an existing +secret (N providers → 1 key). Raw `api_key` alone remains a legacy shortcut +that invents `${PROVIDER_ID}_API_KEY`. Legacy `api_key_env_var_name` maps to +`secret_name` + `secret_store: env` on load; omitted store for store-backed +secrets defaults to `keychain`. `SecretStoreRegistry` + `NamespacedSecretStore` +(`getFrom` / `setIn` / …) is the extension surface for additional backends later. **Rationale:** Ephemeral keys for clients that must not persist credentials were already sketched (`MemorySecretStore`, proto `SECRET_STORE_MEMORY`) but -unused by the daemon. Mutual exclusivity avoids overlay/sync/refresh bugs. -Defaulting unspecified store to keychain preserves existing callers. Keys are -not 1:1 with providers — configure should pick a secret by name after -`SetSecret`. `secret_name` / `secret_store` name the real abstraction; +unused by the daemon. Discrete namespaces (not move-on-write exclusivity) +match provider config, which already carries `secret_store`, and position +the daemon for N pluggable backends without renaming. Defaulting unspecified +store to keychain preserves existing callers. Keys are not 1:1 with +providers — configure should pick a secret by name after `SetSecret`. +`secret_name` / `secret_store` name the real abstraction; `api_key_keychain_name` was a historical misnomer. diff --git a/packages/daemon/src/core/config.ts b/packages/daemon/src/core/config.ts index 86a484a6..fdf299c9 100644 --- a/packages/daemon/src/core/config.ts +++ b/packages/daemon/src/core/config.ts @@ -105,18 +105,23 @@ export function providerSecretName(cfg: ProviderConfig): string | undefined { /** * How to resolve credentials for a provider. - * `store` → DualSecretStore (memory/keychain); `env` → process.env. + * `store` → named backend (memory|keychain) via (secret_store, secret_name); + * `env` → process.env[secret_name]. Omitted secret_store defaults to keychain. */ export function providerCredentialSource( cfg: ProviderConfig, -): { kind: 'store' | 'env'; name: string } | null { +): + | { kind: 'store'; name: string; backend: 'memory' | 'keychain' } + | { kind: 'env'; name: string } + | null { if (cfg.secret_store === 'env') { const name = cfg.secret_name || cfg.api_key_env_var_name; return name ? { kind: 'env', name } : null; } const storeName = providerSecretName(cfg); if (storeName) { - return { kind: 'store', name: storeName }; + const backend = cfg.secret_store === 'memory' ? 'memory' : 'keychain'; + return { kind: 'store', name: storeName, backend }; } if (cfg.api_key_env_var_name) { return { kind: 'env', name: cfg.api_key_env_var_name }; @@ -347,6 +352,11 @@ function migrateProviderConfig(provId: string, cfg: Record): vo cfg.api_key_env_var_name = cfg.secret_name; } + // Store-backed secrets default to the keychain namespace when store is omitted. + if (cfg.secret_name && !cfg.secret_store) { + cfg.secret_store = 'keychain'; + } + // If already new format (has engine field), just rename api_base → base_url if (cfg.engine) { if (cfg.api_base && !cfg.base_url) { diff --git a/packages/daemon/src/core/index.ts b/packages/daemon/src/core/index.ts index 0b8002f8..372353ee 100644 --- a/packages/daemon/src/core/index.ts +++ b/packages/daemon/src/core/index.ts @@ -29,8 +29,8 @@ export { CoreState } from './state.js'; export type { CoreStateOptions, AddProviderOptions } from './state.js'; /** Secret store — inject your own or use the built-in MemorySecretStore */ -export { MemorySecretStore, auditSecretChange } from './secrets.js'; -export type { SecretStore, SecretAuditEvent } from './secrets.js'; +export { MemorySecretStore, auditSecretChange, isNamespacedSecretStore } from './secrets.js'; +export type { SecretStore, NamespacedSecretStore, SecretAuditEvent } from './secrets.js'; // ─── Types: Providers & Models ────────────────────────────────────────── diff --git a/packages/daemon/src/core/secrets.ts b/packages/daemon/src/core/secrets.ts index a91e6b19..f962a49f 100644 --- a/packages/daemon/src/core/secrets.ts +++ b/packages/daemon/src/core/secrets.ts @@ -2,7 +2,7 @@ * Secret store interface and in-memory implementation. * * Core consumers inject their own SecretStore implementation. - * The daemon uses DualSecretStore (MemorySecretStore + KeychainSecretStore); + * The daemon uses SecretStoreRegistry (MemorySecretStore + KeychainSecretStore); * tests/library use MemorySecretStore. * * Credential aggregation (finding A1): one daemon may hold many provider keys. @@ -28,6 +28,30 @@ export interface SecretStore { has(key: string): Promise; } +/** + * Multi-backend secret store: values are addressed by (backend, key). + * Built-ins today are `memory` | `keychain`; custom ids come later. + * {@link SecretStore} methods map to the implementation's default backend. + */ +export interface NamespacedSecretStore extends SecretStore { + getFrom(backend: string, key: string): Promise; + setIn(backend: string, key: string, value: string): Promise; + deleteFrom(backend: string, key: string): Promise; + hasIn(backend: string, key: string): Promise; +} + +export function isNamespacedSecretStore( + store: SecretStore, +): store is NamespacedSecretStore { + const candidate = store as NamespacedSecretStore; + return ( + typeof candidate.getFrom === 'function' && + typeof candidate.setIn === 'function' && + typeof candidate.deleteFrom === 'function' && + typeof candidate.hasIn === 'function' + ); +} + export interface SecretAuditEvent { /** Secret key name only — never the value */ key: string; diff --git a/packages/daemon/src/core/state.ts b/packages/daemon/src/core/state.ts index 347d1a2f..3c6198ae 100644 --- a/packages/daemon/src/core/state.ts +++ b/packages/daemon/src/core/state.ts @@ -8,7 +8,7 @@ * (agent devs, web devs, custom apps). */ -import type { SecretStore } from './secrets.js'; +import { isNamespacedSecretStore, type SecretStore } from './secrets.js'; import { debug } from './debug.js'; import { loadConfig, @@ -365,7 +365,9 @@ export class CoreState { const value = process.env[source.name]; if (value && value.length > 0) return value; } else if (source?.kind === 'store') { - const value = await this.secretStore.get(source.name); + const value = isNamespacedSecretStore(this.secretStore) + ? await this.secretStore.getFrom(source.backend, source.name) + : await this.secretStore.get(source.name); if (value) return value; } diff --git a/packages/daemon/src/daemon/secrets/dual.test.ts b/packages/daemon/src/daemon/secrets/dual.test.ts deleted file mode 100644 index 0e1c98ef..00000000 --- a/packages/daemon/src/daemon/secrets/dual.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Unit tests for DualSecretStore (memory + keychain, move-on-write). - */ - -import { describe, it, expect } from 'vitest'; -import { MemorySecretStore, type SecretStore } from '../../core/secrets.js'; -import { - DualSecretStore, - parseSecretStoreChoice, - secretBackendToProto, -} from './dual.js'; - -function createDual() { - const memory = new MemorySecretStore(); - const keychain = new MemorySecretStore(); // stand-in for keychain in unit tests - const dual = new DualSecretStore(memory, keychain); - return { dual, memory, keychain }; -} - -describe('DualSecretStore', () => { - it('set defaults to keychain and clears memory for the same key', async () => { - const { dual, memory, keychain } = createDual(); - await memory.set('K', 'from-memory'); - await dual.set('K', 'from-keychain'); - - expect(await dual.get('K')).toBe('from-keychain'); - expect(await keychain.has('K')).toBe(true); - expect(await memory.has('K')).toBe(false); - expect(await dual.locate('K')).toBe('keychain'); - }); - - it('setIn memory moves the key out of keychain', async () => { - const { dual, memory, keychain } = createDual(); - await dual.setIn('keychain', 'K', 'persistent'); - await dual.setIn('memory', 'K', 'ephemeral'); - - expect(await dual.get('K')).toBe('ephemeral'); - expect(await memory.get('K')).toBe('ephemeral'); - expect(await keychain.has('K')).toBe(false); - expect(await dual.locate('K')).toBe('memory'); - }); - - it('get prefers memory when both somehow hold a value', async () => { - const { dual, memory, keychain } = createDual(); - // Bypass setIn to simulate inconsistent state - await memory.set('K', 'mem'); - await keychain.set('K', 'kc'); - expect(await dual.get('K')).toBe('mem'); - }); - - it('delete clears both backends', async () => { - const { dual, memory, keychain } = createDual(); - await memory.set('A', '1'); - await keychain.set('B', '2'); - expect(await dual.delete('A')).toBe(true); - expect(await dual.delete('B')).toBe(true); - expect(await dual.delete('missing')).toBe(false); - expect(await memory.has('A')).toBe(false); - expect(await keychain.has('B')).toBe(false); - }); - - it('has and locate reflect the active backend', async () => { - const { dual } = createDual(); - expect(await dual.has('K')).toBe(false); - expect(await dual.locate('K')).toBeNull(); - - await dual.setIn('memory', 'K', 'v'); - expect(await dual.has('K')).toBe(true); - expect(await dual.locate('K')).toBe('memory'); - - await dual.setIn('keychain', 'K', 'v2'); - expect(await dual.locate('K')).toBe('keychain'); - }); - - it('fails closed when the other backend still has the key after delete', async () => { - const sticky = new Map([['K', 'old-persistent']]); - const memory = new MemorySecretStore(); - const stickyKeychain: SecretStore = { - async get(key) { - return sticky.get(key) ?? null; - }, - async set(key, value) { - sticky.set(key, value); - }, - async delete() { - return false; // soft-fail like KeychainSecretStore on error - }, - async has(key) { - return sticky.has(key); - }, - }; - const dual = new DualSecretStore(memory, stickyKeychain); - - await expect(dual.setIn('memory', 'K', 'ephemeral')).rejects.toThrow(/Failed to clear/); - expect(await memory.has('K')).toBe(false); - expect(await stickyKeychain.has('K')).toBe(true); - }); -}); - -describe('parseSecretStoreChoice', () => { - it('defaults unspecified / keychain to keychain', () => { - for (const store of [undefined, null, '', 0, 'SECRET_STORE_UNSPECIFIED', 'keychain', 1]) { - expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'keychain' }); - } - }); - - it('accepts memory', () => { - for (const store of ['memory', 'SECRET_STORE_MEMORY', 3]) { - expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'memory' }); - } - }); - - it('rejects ENV writes', () => { - const result = parseSecretStoreChoice('SECRET_STORE_ENV'); - expect(result.ok).toBe(false); - if (!result.ok) { - expect(result.error).toMatch(/ENV/i); - } - }); - - it('allows ENV when allowEnv is set (configure/reference)', () => { - expect(parseSecretStoreChoice('env', { allowEnv: true })).toEqual({ - ok: true, - backend: 'env', - }); - }); - - it('rejects unknown stores', () => { - const result = parseSecretStoreChoice('vault'); - expect(result.ok).toBe(false); - }); -}); - -describe('secretBackendToProto', () => { - it('maps backends to proto enum numbers', () => { - expect(secretBackendToProto('keychain')).toBe(1); - expect(secretBackendToProto('memory')).toBe(3); - expect(secretBackendToProto(null)).toBe(0); - }); -}); diff --git a/packages/daemon/src/daemon/secrets/dual.ts b/packages/daemon/src/daemon/secrets/dual.ts deleted file mode 100644 index cf221519..00000000 --- a/packages/daemon/src/daemon/secrets/dual.ts +++ /dev/null @@ -1,169 +0,0 @@ -/** - * Dual secret store: process-lifetime memory + OS keychain backends. - * - * Same key name lives in exactly one backend (move-on-write). Default - * {@link SecretStore.set} targets keychain for backward compatibility. - */ - -import type { SecretStore } from '../../core/secrets.js'; - -/** Writable DualSecretStore backends. */ -export type SecretBackend = 'memory' | 'keychain'; - -/** Full secret_store vocabulary including env references. */ -export type SecretStoreKind = SecretBackend | 'env'; - -/** - * Composite store used by the daemon. - * - * - `set` → keychain (existing configure / addProvider callers) - * - `setIn('memory' | 'keychain', …)` → write target + delete from the other - * - `get` / `has` → memory first, then keychain (at most one hit) - * - `delete` → both backends - * - `locate` → which backend holds the key (for List / SecretInfo) - */ -export class DualSecretStore implements SecretStore { - constructor( - private readonly memory: SecretStore, - private readonly keychain: SecretStore, - ) {} - - /** Expose backends for tests that assert exclusivity. */ - get memoryStore(): SecretStore { - return this.memory; - } - - get keychainStore(): SecretStore { - return this.keychain; - } - - async get(key: string): Promise { - const fromMemory = await this.memory.get(key); - if (fromMemory !== null) return fromMemory; - return this.keychain.get(key); - } - - /** Default write path: keychain (persistent). */ - async set(key: string, value: string): Promise { - await this.setIn('keychain', key, value); - } - - /** - * Write to one backend and remove the same key from the other - * (mutual exclusivity — no overlay / sync). - * - * Fails closed if the other backend still holds the key after delete - * (e.g. keychain soft-fail), so callers cannot believe a memory write - * is ephemeral while an OS keychain residue remains. - */ - async setIn(backend: SecretBackend, key: string, value: string): Promise { - const primary = backend === 'memory' ? this.memory : this.keychain; - const other = backend === 'memory' ? this.keychain : this.memory; - const otherName = backend === 'memory' ? 'keychain' : 'memory'; - - await primary.set(key, value); - - try { - await other.delete(key); - } catch (error: unknown) { - // Roll back primary so we do not leave a dual-resident key. - try { - await primary.delete(key); - } catch { - /* ignore rollback errors */ - } - const msg = error instanceof Error ? error.message : String(error); - throw new Error( - `Failed to clear secret '${key}' from ${otherName} after write to ${backend}: ${msg}`, - ); - } - - if (await other.has(key)) { - try { - await primary.delete(key); - } catch { - /* ignore rollback errors */ - } - throw new Error( - `Failed to clear secret '${key}' from ${otherName} after write to ${backend}`, - ); - } - } - - async delete(key: string): Promise { - const fromMemory = await this.memory.delete(key); - const fromKeychain = await this.keychain.delete(key); - return fromMemory || fromKeychain; - } - - async has(key: string): Promise { - if (await this.memory.has(key)) return true; - return this.keychain.has(key); - } - - /** Which backend currently holds the key, if any. */ - async locate(key: string): Promise { - if (await this.memory.has(key)) return 'memory'; - if (await this.keychain.has(key)) return 'keychain'; - return null; - } -} - -export function isDualSecretStore(store: SecretStore): store is DualSecretStore { - return store instanceof DualSecretStore; -} - -/** - * Parse SetSecret / ConfigureProvider `store` / `secret_store` field. - * Unspecified / omitted / keychain → keychain (default for writes). - * ENV rejected for writes unless `allowEnv` (configure/reference only). - */ -export function parseSecretStoreChoice( - store: unknown, - opts: { allowEnv: true }, -): { ok: true; backend: SecretStoreKind } | { ok: false; error: string }; -export function parseSecretStoreChoice( - store: unknown, - opts?: { allowEnv?: false | undefined }, -): { ok: true; backend: SecretBackend } | { ok: false; error: string }; -export function parseSecretStoreChoice( - store: unknown, - opts?: { allowEnv?: boolean }, -): { ok: true; backend: SecretStoreKind } | { ok: false; error: string } { - if ( - store === undefined || - store === null || - store === '' || - store === 0 || - store === '0' || - store === 'SECRET_STORE_UNSPECIFIED' || - store === 'keychain' || - store === 'SECRET_STORE_KEYCHAIN' || - store === 1 || - store === '1' - ) { - return { ok: true, backend: 'keychain' }; - } - if (store === 'memory' || store === 'SECRET_STORE_MEMORY' || store === 3 || store === '3') { - return { ok: true, backend: 'memory' }; - } - if (store === 'env' || store === 'SECRET_STORE_ENV' || store === 2 || store === '2') { - if (opts?.allowEnv) { - return { ok: true, backend: 'env' }; - } - return { - ok: false, - error: - 'SECRET_STORE_ENV is not writable via SetSecret; configure the provider with ' + - 'secret_name + secret_store=env (or api_key_env_var_name)', - }; - } - return { ok: false, error: `Unsupported secret store: ${String(store)}` }; -} - -/** Proto SecretStore enum numeric values for ListSecrets / SecretInfo. */ -export function secretBackendToProto(backend: SecretBackend | null): number { - if (backend === 'memory') return 3; // SECRET_STORE_MEMORY - if (backend === 'keychain') return 1; // SECRET_STORE_KEYCHAIN - return 0; // SECRET_STORE_UNSPECIFIED -} diff --git a/packages/daemon/src/daemon/secrets/registry.test.ts b/packages/daemon/src/daemon/secrets/registry.test.ts new file mode 100644 index 00000000..a9caed58 --- /dev/null +++ b/packages/daemon/src/daemon/secrets/registry.test.ts @@ -0,0 +1,129 @@ +/** + * Unit tests for SecretStoreRegistry (discrete namespaced backends). + */ + +import { describe, it, expect } from 'vitest'; +import { MemorySecretStore } from '../../core/secrets.js'; +import { + SecretStoreRegistry, + parseSecretStoreChoice, + secretBackendToProto, +} from './registry.js'; + +function createRegistry() { + const memory = new MemorySecretStore(); + const keychain = new MemorySecretStore(); // stand-in for keychain in unit tests + const registry = new SecretStoreRegistry(memory, keychain); + return { registry, memory, keychain }; +} + +describe('SecretStoreRegistry', () => { + it('set defaults to keychain and leaves memory untouched', async () => { + const { registry, memory, keychain } = createRegistry(); + await memory.set('K', 'from-memory'); + await registry.set('K', 'from-keychain'); + + expect(await registry.get('K')).toBe('from-keychain'); + expect(await registry.getFrom('keychain', 'K')).toBe('from-keychain'); + expect(await registry.getFrom('memory', 'K')).toBe('from-memory'); + expect(await keychain.has('K')).toBe(true); + expect(await memory.has('K')).toBe(true); + expect(await registry.locateAll('K')).toEqual(['memory', 'keychain']); + }); + + it('setIn memory does not clear keychain (discrete namespaces)', async () => { + const { registry, memory, keychain } = createRegistry(); + await registry.setIn('keychain', 'K', 'persistent'); + await registry.setIn('memory', 'K', 'ephemeral'); + + expect(await memory.get('K')).toBe('ephemeral'); + expect(await keychain.get('K')).toBe('persistent'); + expect(await registry.getFrom('memory', 'K')).toBe('ephemeral'); + expect(await registry.getFrom('keychain', 'K')).toBe('persistent'); + }); + + it('SecretStore.get/has/delete map to keychain only', async () => { + const { registry, memory } = createRegistry(); + await registry.setIn('memory', 'K', 'mem'); + expect(await registry.get('K')).toBeNull(); + expect(await registry.has('K')).toBe(false); + + await registry.set('K', 'kc'); + expect(await registry.get('K')).toBe('kc'); + expect(await memory.get('K')).toBe('mem'); + + expect(await registry.delete('K')).toBe(true); + expect(await registry.has('K')).toBe(false); + expect(await memory.has('K')).toBe(true); + }); + + it('deleteFrom clears only the named backend', async () => { + const { registry, memory, keychain } = createRegistry(); + await registry.setIn('memory', 'K', '1'); + await registry.setIn('keychain', 'K', '2'); + expect(await registry.deleteFrom('memory', 'K')).toBe(true); + expect(await memory.has('K')).toBe(false); + expect(await keychain.has('K')).toBe(true); + }); + + it('hasIn and locateAll reflect each backend independently', async () => { + const { registry } = createRegistry(); + expect(await registry.locateAll('K')).toEqual([]); + expect(await registry.locate('K')).toBeNull(); + + await registry.setIn('memory', 'K', 'v'); + expect(await registry.hasIn('memory', 'K')).toBe(true); + expect(await registry.hasIn('keychain', 'K')).toBe(false); + expect(await registry.locateAll('K')).toEqual(['memory']); + + await registry.setIn('keychain', 'K', 'v2'); + expect(await registry.locateAll('K')).toEqual(['memory', 'keychain']); + }); + + it('rejects unknown backend ids', async () => { + const { registry } = createRegistry(); + await expect(registry.getFrom('vault', 'K')).rejects.toThrow(/Unknown secret store/); + }); +}); + +describe('parseSecretStoreChoice', () => { + it('defaults unspecified / keychain to keychain', () => { + for (const store of [undefined, null, '', 0, 'SECRET_STORE_UNSPECIFIED', 'keychain', 1]) { + expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'keychain' }); + } + }); + + it('accepts memory', () => { + for (const store of ['memory', 'SECRET_STORE_MEMORY', 3]) { + expect(parseSecretStoreChoice(store)).toEqual({ ok: true, backend: 'memory' }); + } + }); + + it('rejects ENV writes', () => { + const result = parseSecretStoreChoice('SECRET_STORE_ENV'); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toMatch(/ENV/i); + } + }); + + it('allows ENV when allowEnv is set (configure/reference)', () => { + expect(parseSecretStoreChoice('env', { allowEnv: true })).toEqual({ + ok: true, + backend: 'env', + }); + }); + + it('rejects unknown stores', () => { + const result = parseSecretStoreChoice('vault'); + expect(result.ok).toBe(false); + }); +}); + +describe('secretBackendToProto', () => { + it('maps backends to proto enum numbers', () => { + expect(secretBackendToProto('keychain')).toBe(1); + expect(secretBackendToProto('memory')).toBe(3); + expect(secretBackendToProto(null)).toBe(0); + }); +}); diff --git a/packages/daemon/src/daemon/secrets/registry.ts b/packages/daemon/src/daemon/secrets/registry.ts new file mode 100644 index 00000000..b9795457 --- /dev/null +++ b/packages/daemon/src/daemon/secrets/registry.ts @@ -0,0 +1,171 @@ +/** + * Registry of discrete secret backends (memory + keychain today). + * + * Each backend is independent — the same key name may exist in more than one. + * Resolution is always (secret_store, secret_name). The {@link SecretStore} + * interface methods map to the default backend (keychain) for backward + * compatibility; prefer {@link SecretStoreRegistry.getFrom} / {@link setIn} / + * {@link deleteFrom} / {@link hasIn} for explicit store selection. + * + * `env` is not registered here — it is a configure/resolve credential source + * (`process.env`), not a daemon-owned writable store. + */ + +import type { SecretStore } from '../../core/secrets.js'; + +/** Built-in writable registry backends. */ +export type SecretBackend = 'memory' | 'keychain'; + +/** Full secret_store vocabulary including env references. */ +export type SecretStoreKind = SecretBackend | 'env'; + +/** Default writable backend when store is omitted (backward compatible). */ +export const DEFAULT_SECRET_BACKEND: SecretBackend = 'keychain'; + +/** + * Maps store id → {@link SecretStore} implementation. + * + * - `set` / `get` / `has` / `delete` → {@link DEFAULT_SECRET_BACKEND} (keychain) + * - `setIn` / `getFrom` / `hasIn` / `deleteFrom` → explicit backend + * - `locateAll` → every backend that currently holds a key + */ +export class SecretStoreRegistry implements SecretStore { + constructor( + private readonly memory: SecretStore, + private readonly keychain: SecretStore, + ) {} + + /** Expose backends for tests and future registry iteration. */ + get memoryStore(): SecretStore { + return this.memory; + } + + get keychainStore(): SecretStore { + return this.keychain; + } + + /** Built-in writable backends (order stable for ListSecrets). */ + backends(): readonly SecretBackend[] { + return ['memory', 'keychain'] as const; + } + + private storeFor(backend: SecretBackend): SecretStore { + return backend === 'memory' ? this.memory : this.keychain; + } + + private requireBackend(backend: string): SecretBackend { + if (backend === 'memory' || backend === 'keychain') return backend; + throw new Error(`Unknown secret store: ${backend}`); + } + + /** SecretStore interface → default keychain namespace. */ + async get(key: string): Promise { + return this.getFrom(DEFAULT_SECRET_BACKEND, key); + } + + async set(key: string, value: string): Promise { + await this.setIn(DEFAULT_SECRET_BACKEND, key, value); + } + + async delete(key: string): Promise { + return this.deleteFrom(DEFAULT_SECRET_BACKEND, key); + } + + async has(key: string): Promise { + return this.hasIn(DEFAULT_SECRET_BACKEND, key); + } + + async getFrom(backend: string, key: string): Promise { + return this.storeFor(this.requireBackend(backend)).get(key); + } + + /** Write to one backend only — does not clear other namespaces. */ + async setIn(backend: string, key: string, value: string): Promise { + await this.storeFor(this.requireBackend(backend)).set(key, value); + } + + async deleteFrom(backend: string, key: string): Promise { + return this.storeFor(this.requireBackend(backend)).delete(key); + } + + async hasIn(backend: string, key: string): Promise { + return this.storeFor(this.requireBackend(backend)).has(key); + } + + /** Backends that currently hold `key` (may be empty, one, or many). */ + async locateAll(key: string): Promise { + const found: SecretBackend[] = []; + for (const backend of this.backends()) { + if (await this.hasIn(backend, key)) found.push(backend); + } + return found; + } + + /** + * @deprecated Prefer {@link locateAll}. Returns the first backend that holds + * the key (memory before keychain), or null. + */ + async locate(key: string): Promise { + const all = await this.locateAll(key); + return all[0] ?? null; + } +} + +export function isSecretStoreRegistry(store: SecretStore): store is SecretStoreRegistry { + return store instanceof SecretStoreRegistry; +} + +/** + * Parse SetSecret / ConfigureProvider `store` / `secret_store` field. + * Unspecified / omitted / keychain → keychain (default for writes). + * ENV rejected for writes unless `allowEnv` (configure/reference only). + */ +export function parseSecretStoreChoice( + store: unknown, + opts: { allowEnv: true }, +): { ok: true; backend: SecretStoreKind } | { ok: false; error: string }; +export function parseSecretStoreChoice( + store: unknown, + opts?: { allowEnv?: false | undefined }, +): { ok: true; backend: SecretBackend } | { ok: false; error: string }; +export function parseSecretStoreChoice( + store: unknown, + opts?: { allowEnv?: boolean }, +): { ok: true; backend: SecretStoreKind } | { ok: false; error: string } { + if ( + store === undefined || + store === null || + store === '' || + store === 0 || + store === '0' || + store === 'SECRET_STORE_UNSPECIFIED' || + store === 'keychain' || + store === 'SECRET_STORE_KEYCHAIN' || + store === 1 || + store === '1' + ) { + return { ok: true, backend: 'keychain' }; + } + if (store === 'memory' || store === 'SECRET_STORE_MEMORY' || store === 3 || store === '3') { + return { ok: true, backend: 'memory' }; + } + if (store === 'env' || store === 'SECRET_STORE_ENV' || store === 2 || store === '2') { + if (opts?.allowEnv) { + return { ok: true, backend: 'env' }; + } + return { + ok: false, + error: + 'SECRET_STORE_ENV is not writable via SetSecret; configure the provider with ' + + 'secret_name + secret_store=env (or api_key_env_var_name)', + }; + } + return { ok: false, error: `Unsupported secret store: ${String(store)}` }; +} + +/** Proto SecretStore enum numeric values for ListSecrets / SecretInfo. */ +export function secretBackendToProto(backend: SecretBackend | null): number { + if (backend === 'memory') return 3; // SECRET_STORE_MEMORY + if (backend === 'keychain') return 1; // SECRET_STORE_KEYCHAIN + return 0; // SECRET_STORE_UNSPECIFIED +} diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index b687db96..4397fbf1 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -27,10 +27,10 @@ import { } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; import { - isDualSecretStore, + isSecretStoreRegistry, parseSecretStoreChoice, secretBackendToProto, -} from '../secrets/dual.js'; +} from '../secrets/registry.js'; import { auditProviderEndpointChange, auditProviderEndpointConfigDiff, @@ -155,6 +155,7 @@ interface ChatRequestProto { interface GetSecretRequestProto { key: string; + store?: number | string; } interface SetSecretRequestProto { @@ -166,6 +167,7 @@ interface SetSecretRequestProto { interface DeleteSecretRequestProto { key: string; + store?: number | string; } interface GetProviderStatusRequestProto { @@ -802,8 +804,21 @@ export function createAbbenayService( ): void { if (!requireCapability(call, 'secrets', authContext, callback)) return; const key = call.request.key; - - state.secretStore.get(key).then((value) => { + const parsed = parseSecretStoreChoice(call.request.store); + if (!parsed.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: parsed.error, + }); + return; + } + + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const read = registry + ? registry.getFrom(parsed.backend, key) + : state.secretStore.get(key); + + read.then((value) => { callback(null, { value: value || '', found: value !== null, @@ -835,9 +850,9 @@ export function createAbbenayService( return; } - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - const write = dual - ? dual.setIn(parsed.backend, key, value) + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const write = registry + ? registry.setIn(parsed.backend, key, value) : state.secretStore.set(key, value); const auditSource = parsed.backend === 'memory' ? 'grpc-secrets-memory' : 'grpc-secrets'; @@ -863,8 +878,28 @@ export function createAbbenayService( callback: grpc.sendUnaryData ): void { if (!requireCapability(call, 'secrets', authContext, callback)) return; - state.secretStore.delete(call.request.key).then(() => { - auditSecretChange({ key: call.request.key, op: 'delete', source: 'grpc-secrets' }); + const key = call.request.key; + const parsed = parseSecretStoreChoice(call.request.store); + if (!parsed.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: parsed.error, + }); + return; + } + + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const remove = registry + ? registry.deleteFrom(parsed.backend, key) + : state.secretStore.delete(key); + + remove.then(() => { + auditSecretChange({ + key, + op: 'delete', + source: + parsed.backend === 'memory' ? 'grpc-secrets-memory' : 'grpc-secrets', + }); callback(null, {}); }).catch((error: unknown) => { callback({ @@ -882,23 +917,39 @@ export function createAbbenayService( callback: grpc.sendUnaryData ): void { if (!requireCapability(call, 'secrets', authContext, callback)) return; - // Return known key names with availability status + // Return known key names with availability status (one row per backend hit). const engines = getEngines(); - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; const checks = engines.filter(e => e.requiresKey).map(async (e) => { const key = e.defaultEnvVar || `${e.id.toUpperCase()}_API_KEY`; + if (registry) { + const backends = await registry.locateAll(key); + if (backends.length === 0) { + return [{ + key, + engine: e.id, + has_value: false, + store: secretBackendToProto(null), + }]; + } + return backends.map((backend) => ({ + key, + engine: e.id, + has_value: true, + store: secretBackendToProto(backend), + })); + } const hasValue = await state.secretStore.has(key); - const backend = dual && hasValue ? await dual.locate(key) : null; - return { + return [{ key, engine: e.id, has_value: hasValue, - store: secretBackendToProto(backend), - }; + store: secretBackendToProto(null), + }]; }); - Promise.all(checks).then((secrets) => { - callback(null, { secrets }); + Promise.all(checks).then((groups) => { + callback(null, { secrets: groups.flat() }); }).catch((error: unknown) => { callback({ code: grpc.status.INTERNAL, @@ -1800,9 +1851,9 @@ export function createAbbenayService( } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - if (dual) { - await dual.setIn(storeChoice.backend, secretName, apiKey); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + if (registry) { + await registry.setIn(storeChoice.backend, secretName, apiKey); } else { await state.secretStore.set(secretName, apiKey); } @@ -1839,12 +1890,16 @@ export function createAbbenayService( config.providers[providerId].api_key_env_var_name = secretNameRef; delete config.providers[providerId].api_key_keychain_name; } else { - const exists = await state.secretStore.has(secretNameRef); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const exists = registry + ? await registry.hasIn(storeChoice.backend, secretNameRef) + : await state.secretStore.has(secretNameRef); if (!exists) { callback({ code: grpc.status.INVALID_ARGUMENT, message: - `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, + `Secret "${secretNameRef}" not found in ${storeChoice.backend}; ` + + `SetSecret first or pass api_key`, }); return; } @@ -1854,18 +1909,22 @@ export function createAbbenayService( delete config.providers[providerId].api_key_env_var_name; } } else { - // No secret_store: reference daemon secret store (memory or keychain). - const exists = await state.secretStore.has(secretNameRef); + // No secret_store: default namespace is keychain. + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const exists = registry + ? await registry.hasIn('keychain', secretNameRef) + : await state.secretStore.has(secretNameRef); if (!exists) { callback({ code: grpc.status.INVALID_ARGUMENT, message: - `Secret "${secretNameRef}" not found; SetSecret first or pass api_key`, + `Secret "${secretNameRef}" not found in keychain; ` + + `SetSecret first, pass api_key, or set secret_store`, }); return; } config.providers[providerId].secret_name = secretNameRef; - delete config.providers[providerId].secret_store; + config.providers[providerId].secret_store = 'keychain'; config.providers[providerId].api_key_keychain_name = secretNameRef; delete config.providers[providerId].api_key_env_var_name; } diff --git a/packages/daemon/src/daemon/state.ts b/packages/daemon/src/daemon/state.ts index a48ca009..10ff623a 100644 --- a/packages/daemon/src/daemon/state.ts +++ b/packages/daemon/src/daemon/state.ts @@ -10,7 +10,7 @@ import { CoreState, type ChatToolOptions } from '../core/state.js'; import type { ChatChunk, ChatParams, ToolExecutor } from '../core/engines.js'; import type { PolicyConfig } from '../core/policies.js'; import { MemorySecretStore } from '../core/secrets.js'; -import { DualSecretStore } from './secrets/dual.js'; +import { SecretStoreRegistry } from './secrets/registry.js'; import { KeychainSecretStore } from './secrets/keychain.js'; import { ToolRegistry } from '../core/tool-registry.js'; import { ToolRouter } from './tool-router.js'; @@ -85,7 +85,7 @@ export class DaemonState extends CoreState { constructor() { super({ - secretStore: new DualSecretStore(new MemorySecretStore(), new KeychainSecretStore()), + secretStore: new SecretStoreRegistry(new MemorySecretStore(), new KeychainSecretStore()), }); // Initialize tool registry, router, MCP client pool, and MCP server diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 01f4cc8e..580dbd00 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -18,7 +18,7 @@ import { fileURLToPath } from 'node:url'; import { getDefaultSocketPath } from '../transport.js'; import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, providerSecretName, type ConfigFile, type ProviderConfig } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; -import { isDualSecretStore, parseSecretStoreChoice } from '../secrets/dual.js'; +import { isSecretStoreRegistry, parseSecretStoreChoice } from '../secrets/registry.js'; import { auditProviderEndpointChange, auditProviderEndpointConfigDiff, @@ -1024,21 +1024,27 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): app.get('/api/secrets', async (req, res) => { try { const engines = getEngines(); - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - const secrets = await Promise.all( + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const groups = await Promise.all( engines.filter(e => e.requiresKey).map(async (e) => { const key = e.defaultEnvVar || `${e.id.toUpperCase()}_API_KEY`; + if (registry) { + const backends = await registry.locateAll(key); + if (backends.length === 0) { + return [{ key, engine: e.id, hasValue: false }]; + } + return backends.map((store) => ({ + key, + engine: e.id, + hasValue: true, + store, + })); + } const hasValue = await state.secretStore.has(key); - const store = dual && hasValue ? await dual.locate(key) : null; - return { - key, - engine: e.id, - hasValue, - ...(store ? { store } : {}), - }; + return [{ key, engine: e.id, hasValue }]; }) ); - res.json({ secrets }); + res.json({ secrets: groups.flat() }); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); console.error('[Web] /api/secrets error:', msg); @@ -1065,9 +1071,9 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, storeChoice.error); return; } - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - if (dual) { - await dual.setIn(storeChoice.backend, key, parsed.data.value); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + if (registry) { + await registry.setIn(storeChoice.backend, key, parsed.data.value); } else { await state.secretStore.set(key, parsed.data.value); } @@ -1101,9 +1107,9 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, storeChoice.error); return; } - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - if (dual) { - await dual.setIn(storeChoice.backend, parsed.data.key, parsed.data.value); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + if (registry) { + await registry.setIn(storeChoice.backend, parsed.data.key, parsed.data.value); } else { await state.secretStore.set(parsed.data.key, parsed.data.value); } @@ -1121,6 +1127,7 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): /** * DELETE /api/secrets/:key - Delete a secret + * Query: secret_store=memory|keychain (default keychain) */ app.delete('/api/secrets/:key', async (req, res) => { try { @@ -1129,9 +1136,28 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): sendBadRequest(res, parsed.error); return; } - await state.secretStore.delete(req.params.key); - auditSecretChange({ key: req.params.key, op: 'delete', source: 'http-secrets' }); - res.json({ success: true }); + const storeChoice = parseSecretStoreChoice( + (req.query.secret_store as string | undefined) ?? + (req.query.store as string | undefined) ?? + 'keychain', + ); + if (!storeChoice.ok) { + sendBadRequest(res, storeChoice.error); + return; + } + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + if (registry) { + await registry.deleteFrom(storeChoice.backend, req.params.key); + } else { + await state.secretStore.delete(req.params.key); + } + auditSecretChange({ + key: req.params.key, + op: 'delete', + source: + storeChoice.backend === 'memory' ? 'http-secrets-memory' : 'http-secrets', + }); + res.json({ success: true, secret_store: storeChoice.backend }); state.notifyModelsChanged('secret_deleted'); } catch (err: unknown) { const msg = err instanceof Error ? err.message : String(err); @@ -1155,8 +1181,13 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): } let exists = false; - if (source === 'keychain') { - exists = await state.secretStore.has(name); + if (source === 'keychain' || source === 'memory') { + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + exists = registry + ? await registry.hasIn(source, name) + : source === 'keychain' + ? await state.secretStore.has(name) + : false; } else if (source === 'env') { exists = !!process.env[name]; } @@ -1433,9 +1464,9 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): } // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; - const dual = isDualSecretStore(state.secretStore) ? state.secretStore : null; - if (dual) { - await dual.setIn(storeChoice.backend, secretName, apiKey); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + if (registry) { + await registry.setIn(storeChoice.backend, secretName, apiKey); } else { await state.secretStore.set(secretName, apiKey); } @@ -1454,10 +1485,15 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): config.providers[providerId].api_key_env_var_name = secretNameRef; delete config.providers[providerId].api_key_keychain_name; } else if (storeRaw === 'memory' || storeRaw === 'keychain') { - const exists = await state.secretStore.has(secretNameRef); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const exists = registry + ? await registry.hasIn(storeRaw, secretNameRef) + : await state.secretStore.has(secretNameRef); if (!exists) { res.status(400).json({ - error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, + error: + `Secret "${secretNameRef}" not found in ${storeRaw}; ` + + `POST /api/secrets first or pass apiKey`, }); return; } @@ -1466,15 +1502,20 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): config.providers[providerId].api_key_keychain_name = secretNameRef; delete config.providers[providerId].api_key_env_var_name; } else { - const exists = await state.secretStore.has(secretNameRef); + const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const exists = registry + ? await registry.hasIn('keychain', secretNameRef) + : await state.secretStore.has(secretNameRef); if (!exists) { res.status(400).json({ - error: `Secret "${secretNameRef}" not found; POST /api/secrets first or pass apiKey`, + error: + `Secret "${secretNameRef}" not found in keychain; ` + + `POST /api/secrets first, pass apiKey, or set secret_store`, }); return; } config.providers[providerId].secret_name = secretNameRef; - delete config.providers[providerId].secret_store; + config.providers[providerId].secret_store = 'keychain'; config.providers[providerId].api_key_keychain_name = secretNameRef; delete config.providers[providerId].api_key_env_var_name; } diff --git a/packages/daemon/tests/integration/grpc-real-service.test.ts b/packages/daemon/tests/integration/grpc-real-service.test.ts index ce481cc5..972c59f1 100644 --- a/packages/daemon/tests/integration/grpc-real-service.test.ts +++ b/packages/daemon/tests/integration/grpc-real-service.test.ts @@ -289,29 +289,43 @@ describe('Real gRPC service: Secrets', () => { value: 'ephemeral-value', store: 'SECRET_STORE_MEMORY', }); - const got = await callUnary(client, 'GetSecret', { key: 'MEM_ONLY' }); + const got = await callUnary(client, 'GetSecret', { + key: 'MEM_ONLY', + store: 'SECRET_STORE_MEMORY', + }); expect(got.value).toBe('ephemeral-value'); - // DaemonState uses DualSecretStore; mocked KeychainSecretStore is the keychain half. + // Default GetSecret (keychain namespace) must not see the memory value. + const fromDefault = await callUnary(client, 'GetSecret', { key: 'MEM_ONLY' }); + expect(fromDefault.value).toBe(''); + // DaemonState uses SecretStoreRegistry; mocked KeychainSecretStore is the keychain half. // Memory-only writes must not land in the keychain Map. expect(mockSecretStoreData.has('MEM_ONLY')).toBe(false); }); - it('should move a key from keychain to memory on SetSecret MEMORY', async () => { + it('should allow the same key name in memory and keychain (discrete namespaces)', async () => { await callUnary(client, 'SetSecret', { - key: 'MOVE_KEY', + key: 'BOTH_KEY', value: 'persistent', store: 'SECRET_STORE_KEYCHAIN', }); - expect(mockSecretStoreData.get('MOVE_KEY')).toBe('persistent'); + expect(mockSecretStoreData.get('BOTH_KEY')).toBe('persistent'); await callUnary(client, 'SetSecret', { - key: 'MOVE_KEY', + key: 'BOTH_KEY', value: 'ephemeral', store: 'SECRET_STORE_MEMORY', }); - expect(mockSecretStoreData.has('MOVE_KEY')).toBe(false); - const got = await callUnary(client, 'GetSecret', { key: 'MOVE_KEY' }); - expect(got.value).toBe('ephemeral'); + expect(mockSecretStoreData.get('BOTH_KEY')).toBe('persistent'); + const mem = await callUnary(client, 'GetSecret', { + key: 'BOTH_KEY', + store: 'SECRET_STORE_MEMORY', + }); + expect(mem.value).toBe('ephemeral'); + const kc = await callUnary(client, 'GetSecret', { + key: 'BOTH_KEY', + store: 'SECRET_STORE_KEYCHAIN', + }); + expect(kc.value).toBe('persistent'); }); it('should reject SECRET_STORE_ENV on SetSecret', async () => { diff --git a/packages/proto-ts/src/abbenay/v1/service.ts b/packages/proto-ts/src/abbenay/v1/service.ts index 04ba55eb..71af91da 100644 --- a/packages/proto-ts/src/abbenay/v1/service.ts +++ b/packages/proto-ts/src/abbenay/v1/service.ts @@ -1343,6 +1343,8 @@ export interface DeletePolicyRequest { export interface GetSecretRequest { key: string; + /** Backend namespace (default keychain) */ + store: SecretStore; } export interface GetSecretResponse { @@ -1352,12 +1354,14 @@ export interface GetSecretResponse { export interface SetSecretRequest { key: string; value: string; - /** Where to store */ + /** Where to store (default keychain) */ store: SecretStore; } export interface DeleteSecretRequest { key: string; + /** Backend namespace (default keychain) */ + store: SecretStore; } export interface ListSecretsRequest { @@ -13596,7 +13600,7 @@ export const DeletePolicyRequest: MessageFns = { }; function createBaseGetSecretRequest(): GetSecretRequest { - return { key: "" }; + return { key: "", store: 0 }; } export const GetSecretRequest: MessageFns = { @@ -13604,6 +13608,9 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } + if (message.store !== 0) { + writer.uint32(16).int32(message.store); + } return writer; }, @@ -13622,6 +13629,14 @@ export const GetSecretRequest: MessageFns = { message.key = reader.string(); continue; } + case 2: { + if (tag !== 16) { + break; + } + + message.store = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -13632,7 +13647,10 @@ export const GetSecretRequest: MessageFns = { }, fromJSON(object: any): GetSecretRequest { - return { key: isSet(object.key) ? globalThis.String(object.key) : "" }; + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + }; }, toJSON(message: GetSecretRequest): unknown { @@ -13640,6 +13658,9 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } + if (message.store !== 0) { + obj.store = secretStoreToJSON(message.store); + } return obj; }, @@ -13649,6 +13670,7 @@ export const GetSecretRequest: MessageFns = { fromPartial(object: DeepPartial): GetSecretRequest { const message = createBaseGetSecretRequest(); message.key = object.key ?? ""; + message.store = object.store ?? 0; return message; }, }; @@ -13804,7 +13826,7 @@ export const SetSecretRequest: MessageFns = { }; function createBaseDeleteSecretRequest(): DeleteSecretRequest { - return { key: "" }; + return { key: "", store: 0 }; } export const DeleteSecretRequest: MessageFns = { @@ -13812,6 +13834,9 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } + if (message.store !== 0) { + writer.uint32(16).int32(message.store); + } return writer; }, @@ -13830,6 +13855,14 @@ export const DeleteSecretRequest: MessageFns = { message.key = reader.string(); continue; } + case 2: { + if (tag !== 16) { + break; + } + + message.store = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -13840,7 +13873,10 @@ export const DeleteSecretRequest: MessageFns = { }, fromJSON(object: any): DeleteSecretRequest { - return { key: isSet(object.key) ? globalThis.String(object.key) : "" }; + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + }; }, toJSON(message: DeleteSecretRequest): unknown { @@ -13848,6 +13884,9 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } + if (message.store !== 0) { + obj.store = secretStoreToJSON(message.store); + } return obj; }, @@ -13857,6 +13896,7 @@ export const DeleteSecretRequest: MessageFns = { fromPartial(object: DeepPartial): DeleteSecretRequest { const message = createBaseDeleteSecretRequest(); message.key = object.key ?? ""; + message.store = object.store ?? 0; return message; }, }; diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py index 763c4195..2509f2ae 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xba\x03\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x32\n\x0csecret_store\x18\x07 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x04\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1f\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xba\x03\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x32\n\x0csecret_store\x18\x07 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x04\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"G\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"J\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -57,20 +57,20 @@ _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_options = b'8\001' _globals['_MCPTRANSPORT_ENVENTRY']._loaded_options = None _globals['_MCPTRANSPORT_ENVENTRY']._serialized_options = b'8\001' - _globals['_ROLE']._serialized_start=18391 - _globals['_ROLE']._serialized_end=18486 - _globals['_CLIENTTYPE']._serialized_start=18489 - _globals['_CLIENTTYPE']._serialized_end=18644 - _globals['_REPLAYFORMAT']._serialized_start=18647 - _globals['_REPLAYFORMAT']._serialized_end=18777 - _globals['_MODELSOURCE']._serialized_start=18779 - _globals['_MODELSOURCE']._serialized_end=18875 - _globals['_PROVIDERTYPE']._serialized_start=18877 - _globals['_PROVIDERTYPE']._serialized_end=18994 - _globals['_LOGLEVEL']._serialized_start=18997 - _globals['_LOGLEVEL']._serialized_end=19137 - _globals['_SECRETSTORE']._serialized_start=19139 - _globals['_SECRETSTORE']._serialized_end=19256 + _globals['_ROLE']._serialized_start=18471 + _globals['_ROLE']._serialized_end=18566 + _globals['_CLIENTTYPE']._serialized_start=18569 + _globals['_CLIENTTYPE']._serialized_end=18724 + _globals['_REPLAYFORMAT']._serialized_start=18727 + _globals['_REPLAYFORMAT']._serialized_end=18857 + _globals['_MODELSOURCE']._serialized_start=18859 + _globals['_MODELSOURCE']._serialized_end=18955 + _globals['_PROVIDERTYPE']._serialized_start=18957 + _globals['_PROVIDERTYPE']._serialized_end=19074 + _globals['_LOGLEVEL']._serialized_start=19077 + _globals['_LOGLEVEL']._serialized_end=19217 + _globals['_SECRETSTORE']._serialized_start=19219 + _globals['_SECRETSTORE']._serialized_end=19336 _globals['_EMPTY']._serialized_start=40 _globals['_EMPTY']._serialized_end=47 _globals['_TIMESTAMP']._serialized_start=49 @@ -310,119 +310,119 @@ _globals['_DELETEPOLICYREQUEST']._serialized_start=12960 _globals['_DELETEPOLICYREQUEST']._serialized_end=12995 _globals['_GETSECRETREQUEST']._serialized_start=12997 - _globals['_GETSECRETREQUEST']._serialized_end=13028 - _globals['_GETSECRETRESPONSE']._serialized_start=13030 - _globals['_GETSECRETRESPONSE']._serialized_end=13064 - _globals['_SETSECRETREQUEST']._serialized_start=13066 - _globals['_SETSECRETREQUEST']._serialized_end=13152 - _globals['_DELETESECRETREQUEST']._serialized_start=13154 - _globals['_DELETESECRETREQUEST']._serialized_end=13188 - _globals['_LISTSECRETSREQUEST']._serialized_start=13190 - _globals['_LISTSECRETSREQUEST']._serialized_end=13210 - _globals['_LISTSECRETSRESPONSE']._serialized_start=13212 - _globals['_LISTSECRETSRESPONSE']._serialized_end=13274 - _globals['_SECRETINFO']._serialized_start=13276 - _globals['_SECRETINFO']._serialized_end=13360 - _globals['_REGISTERREQUEST']._serialized_start=13362 - _globals['_REGISTERREQUEST']._serialized_end=13488 - _globals['_REGISTERRESPONSE']._serialized_start=13490 - _globals['_REGISTERRESPONSE']._serialized_end=13554 - _globals['_UNREGISTERREQUEST']._serialized_start=13556 - _globals['_UNREGISTERREQUEST']._serialized_end=13594 - _globals['_GETSTATUSREQUEST']._serialized_start=13596 - _globals['_GETSTATUSREQUEST']._serialized_end=13614 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13616 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13647 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13649 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13701 - _globals['_DAEMONSTATUS']._serialized_start=13704 - _globals['_DAEMONSTATUS']._serialized_end=13908 - _globals['_CONNECTEDCLIENT']._serialized_start=13911 - _globals['_CONNECTEDCLIENT']._serialized_end=14081 - _globals['_SHUTDOWNREQUEST']._serialized_start=14083 - _globals['_SHUTDOWNREQUEST']._serialized_end=14145 - _globals['_HEALTHCHECKREQUEST']._serialized_start=14147 - _globals['_HEALTHCHECKREQUEST']._serialized_end=14167 - _globals['_HEALTHCHECKRESPONSE']._serialized_start=14169 - _globals['_HEALTHCHECKRESPONSE']._serialized_end=14224 - _globals['_STARTWEBSERVERREQUEST']._serialized_start=14226 - _globals['_STARTWEBSERVERREQUEST']._serialized_end=14263 - _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14265 - _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14358 - _globals['_STOPWEBSERVERREQUEST']._serialized_start=14360 - _globals['_STOPWEBSERVERREQUEST']._serialized_end=14382 - _globals['_VSCODEREQUEST']._serialized_start=14385 - _globals['_VSCODEREQUEST']._serialized_end=14782 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14784 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14827 - _globals['_VSCODERESPONSE']._serialized_start=14830 - _globals['_VSCODERESPONSE']._serialized_end=15276 - _globals['_GETWORKSPACEREQUEST']._serialized_start=15278 - _globals['_GETWORKSPACEREQUEST']._serialized_end=15299 - _globals['_GETWORKSPACERESPONSE']._serialized_start=15301 - _globals['_GETWORKSPACERESPONSE']._serialized_end=15374 - _globals['_VSCODEERROR']._serialized_start=15376 - _globals['_VSCODEERROR']._serialized_end=15420 - _globals['_INVOKETOOLREQUEST']._serialized_start=15422 - _globals['_INVOKETOOLREQUEST']._serialized_end=15484 - _globals['_INVOKETOOLRESPONSE']._serialized_start=15486 - _globals['_INVOKETOOLRESPONSE']._serialized_end=15545 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15547 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15571 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15573 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15641 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15643 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15713 - _globals['_VSCODETOOLINFO']._serialized_start=15715 - _globals['_VSCODETOOLINFO']._serialized_end=15802 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15804 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15875 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15877 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=15944 - _globals['_VSCODEMODEL']._serialized_start=15946 - _globals['_VSCODEMODEL']._serialized_end=16043 - _globals['_SENDVSCODECHATREQUEST']._serialized_start=16046 - _globals['_SENDVSCODECHATREQUEST']._serialized_end=16208 - _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16210 - _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16279 - _globals['_VSCODECHATCHUNK']._serialized_start=16281 - _globals['_VSCODECHATCHUNK']._serialized_end=16372 - _globals['_VSCODETOOLCALL']._serialized_start=16374 - _globals['_VSCODETOOLCALL']._serialized_end=16445 - _globals['_LISTPOLICIESREQUEST']._serialized_start=16447 - _globals['_LISTPOLICIESREQUEST']._serialized_end=16468 - _globals['_LISTPOLICIESRESPONSE']._serialized_start=16470 - _globals['_LISTPOLICIESRESPONSE']._serialized_end=16534 - _globals['_POLICYINFO']._serialized_start=16536 - _globals['_POLICYINFO']._serialized_end=16621 - _globals['_POLICYCONFIG']._serialized_start=16624 - _globals['_POLICYCONFIG']._serialized_end=16946 - _globals['_POLICYSAMPLING']._serialized_start=16948 - _globals['_POLICYSAMPLING']._serialized_end=17066 - _globals['_POLICYOUTPUT']._serialized_start=17069 - _globals['_POLICYOUTPUT']._serialized_end=17337 - _globals['_POLICYCONTEXT']._serialized_start=17340 - _globals['_POLICYCONTEXT']._serialized_end=17469 - _globals['_POLICYTOOL']._serialized_start=17471 - _globals['_POLICYTOOL']._serialized_end=17579 - _globals['_POLICYRELIABILITY']._serialized_start=17581 - _globals['_POLICYRELIABILITY']._serialized_end=17696 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17699 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17904 - _globals['_MCPTRANSPORT']._serialized_start=17907 - _globals['_MCPTRANSPORT']._serialized_end=18205 + _globals['_GETSECRETREQUEST']._serialized_end=13068 + _globals['_GETSECRETRESPONSE']._serialized_start=13070 + _globals['_GETSECRETRESPONSE']._serialized_end=13104 + _globals['_SETSECRETREQUEST']._serialized_start=13106 + _globals['_SETSECRETREQUEST']._serialized_end=13192 + _globals['_DELETESECRETREQUEST']._serialized_start=13194 + _globals['_DELETESECRETREQUEST']._serialized_end=13268 + _globals['_LISTSECRETSREQUEST']._serialized_start=13270 + _globals['_LISTSECRETSREQUEST']._serialized_end=13290 + _globals['_LISTSECRETSRESPONSE']._serialized_start=13292 + _globals['_LISTSECRETSRESPONSE']._serialized_end=13354 + _globals['_SECRETINFO']._serialized_start=13356 + _globals['_SECRETINFO']._serialized_end=13440 + _globals['_REGISTERREQUEST']._serialized_start=13442 + _globals['_REGISTERREQUEST']._serialized_end=13568 + _globals['_REGISTERRESPONSE']._serialized_start=13570 + _globals['_REGISTERRESPONSE']._serialized_end=13634 + _globals['_UNREGISTERREQUEST']._serialized_start=13636 + _globals['_UNREGISTERREQUEST']._serialized_end=13674 + _globals['_GETSTATUSREQUEST']._serialized_start=13676 + _globals['_GETSTATUSREQUEST']._serialized_end=13694 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13696 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13727 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13729 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13781 + _globals['_DAEMONSTATUS']._serialized_start=13784 + _globals['_DAEMONSTATUS']._serialized_end=13988 + _globals['_CONNECTEDCLIENT']._serialized_start=13991 + _globals['_CONNECTEDCLIENT']._serialized_end=14161 + _globals['_SHUTDOWNREQUEST']._serialized_start=14163 + _globals['_SHUTDOWNREQUEST']._serialized_end=14225 + _globals['_HEALTHCHECKREQUEST']._serialized_start=14227 + _globals['_HEALTHCHECKREQUEST']._serialized_end=14247 + _globals['_HEALTHCHECKRESPONSE']._serialized_start=14249 + _globals['_HEALTHCHECKRESPONSE']._serialized_end=14304 + _globals['_STARTWEBSERVERREQUEST']._serialized_start=14306 + _globals['_STARTWEBSERVERREQUEST']._serialized_end=14343 + _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14345 + _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14438 + _globals['_STOPWEBSERVERREQUEST']._serialized_start=14440 + _globals['_STOPWEBSERVERREQUEST']._serialized_end=14462 + _globals['_VSCODEREQUEST']._serialized_start=14465 + _globals['_VSCODEREQUEST']._serialized_end=14862 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14864 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14907 + _globals['_VSCODERESPONSE']._serialized_start=14910 + _globals['_VSCODERESPONSE']._serialized_end=15356 + _globals['_GETWORKSPACEREQUEST']._serialized_start=15358 + _globals['_GETWORKSPACEREQUEST']._serialized_end=15379 + _globals['_GETWORKSPACERESPONSE']._serialized_start=15381 + _globals['_GETWORKSPACERESPONSE']._serialized_end=15454 + _globals['_VSCODEERROR']._serialized_start=15456 + _globals['_VSCODEERROR']._serialized_end=15500 + _globals['_INVOKETOOLREQUEST']._serialized_start=15502 + _globals['_INVOKETOOLREQUEST']._serialized_end=15564 + _globals['_INVOKETOOLRESPONSE']._serialized_start=15566 + _globals['_INVOKETOOLRESPONSE']._serialized_end=15625 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15627 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15651 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15653 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15721 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15723 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15793 + _globals['_VSCODETOOLINFO']._serialized_start=15795 + _globals['_VSCODETOOLINFO']._serialized_end=15882 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15884 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15955 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15957 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=16024 + _globals['_VSCODEMODEL']._serialized_start=16026 + _globals['_VSCODEMODEL']._serialized_end=16123 + _globals['_SENDVSCODECHATREQUEST']._serialized_start=16126 + _globals['_SENDVSCODECHATREQUEST']._serialized_end=16288 + _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16290 + _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16359 + _globals['_VSCODECHATCHUNK']._serialized_start=16361 + _globals['_VSCODECHATCHUNK']._serialized_end=16452 + _globals['_VSCODETOOLCALL']._serialized_start=16454 + _globals['_VSCODETOOLCALL']._serialized_end=16525 + _globals['_LISTPOLICIESREQUEST']._serialized_start=16527 + _globals['_LISTPOLICIESREQUEST']._serialized_end=16548 + _globals['_LISTPOLICIESRESPONSE']._serialized_start=16550 + _globals['_LISTPOLICIESRESPONSE']._serialized_end=16614 + _globals['_POLICYINFO']._serialized_start=16616 + _globals['_POLICYINFO']._serialized_end=16701 + _globals['_POLICYCONFIG']._serialized_start=16704 + _globals['_POLICYCONFIG']._serialized_end=17026 + _globals['_POLICYSAMPLING']._serialized_start=17028 + _globals['_POLICYSAMPLING']._serialized_end=17146 + _globals['_POLICYOUTPUT']._serialized_start=17149 + _globals['_POLICYOUTPUT']._serialized_end=17417 + _globals['_POLICYCONTEXT']._serialized_start=17420 + _globals['_POLICYCONTEXT']._serialized_end=17549 + _globals['_POLICYTOOL']._serialized_start=17551 + _globals['_POLICYTOOL']._serialized_end=17659 + _globals['_POLICYRELIABILITY']._serialized_start=17661 + _globals['_POLICYRELIABILITY']._serialized_end=17776 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17779 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17984 + _globals['_MCPTRANSPORT']._serialized_start=17987 + _globals['_MCPTRANSPORT']._serialized_end=18285 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10730 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10776 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10778 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10820 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18207 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18292 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18294 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18341 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18343 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18389 - _globals['_MCPBRIDGE']._serialized_start=19259 - _globals['_MCPBRIDGE']._serialized_end=19930 - _globals['_ABBENAY']._serialized_start=19933 - _globals['_ABBENAY']._serialized_end=23519 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18287 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18372 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18374 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18421 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18423 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18469 + _globals['_MCPBRIDGE']._serialized_start=19339 + _globals['_MCPBRIDGE']._serialized_end=20010 + _globals['_ABBENAY']._serialized_start=20013 + _globals['_ABBENAY']._serialized_end=23599 # @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi index 762fd3c1..2062ccae 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi @@ -1248,10 +1248,12 @@ class DeletePolicyRequest(_message.Message): def __init__(self, name: _Optional[str] = ...) -> None: ... class GetSecretRequest(_message.Message): - __slots__ = ("key",) + __slots__ = ("key", "store") KEY_FIELD_NUMBER: _ClassVar[int] + STORE_FIELD_NUMBER: _ClassVar[int] key: str - def __init__(self, key: _Optional[str] = ...) -> None: ... + store: SecretStore + def __init__(self, key: _Optional[str] = ..., store: _Optional[_Union[SecretStore, str]] = ...) -> None: ... class GetSecretResponse(_message.Message): __slots__ = ("value",) @@ -1270,10 +1272,12 @@ class SetSecretRequest(_message.Message): def __init__(self, key: _Optional[str] = ..., value: _Optional[str] = ..., store: _Optional[_Union[SecretStore, str]] = ...) -> None: ... class DeleteSecretRequest(_message.Message): - __slots__ = ("key",) + __slots__ = ("key", "store") KEY_FIELD_NUMBER: _ClassVar[int] + STORE_FIELD_NUMBER: _ClassVar[int] key: str - def __init__(self, key: _Optional[str] = ...) -> None: ... + store: SecretStore + def __init__(self, key: _Optional[str] = ..., store: _Optional[_Union[SecretStore, str]] = ...) -> None: ... class ListSecretsRequest(_message.Message): __slots__ = () diff --git a/packages/vscode/src/proto/abbenay/v1/service.ts b/packages/vscode/src/proto/abbenay/v1/service.ts index 04ba55eb..71af91da 100644 --- a/packages/vscode/src/proto/abbenay/v1/service.ts +++ b/packages/vscode/src/proto/abbenay/v1/service.ts @@ -1343,6 +1343,8 @@ export interface DeletePolicyRequest { export interface GetSecretRequest { key: string; + /** Backend namespace (default keychain) */ + store: SecretStore; } export interface GetSecretResponse { @@ -1352,12 +1354,14 @@ export interface GetSecretResponse { export interface SetSecretRequest { key: string; value: string; - /** Where to store */ + /** Where to store (default keychain) */ store: SecretStore; } export interface DeleteSecretRequest { key: string; + /** Backend namespace (default keychain) */ + store: SecretStore; } export interface ListSecretsRequest { @@ -13596,7 +13600,7 @@ export const DeletePolicyRequest: MessageFns = { }; function createBaseGetSecretRequest(): GetSecretRequest { - return { key: "" }; + return { key: "", store: 0 }; } export const GetSecretRequest: MessageFns = { @@ -13604,6 +13608,9 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } + if (message.store !== 0) { + writer.uint32(16).int32(message.store); + } return writer; }, @@ -13622,6 +13629,14 @@ export const GetSecretRequest: MessageFns = { message.key = reader.string(); continue; } + case 2: { + if (tag !== 16) { + break; + } + + message.store = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -13632,7 +13647,10 @@ export const GetSecretRequest: MessageFns = { }, fromJSON(object: any): GetSecretRequest { - return { key: isSet(object.key) ? globalThis.String(object.key) : "" }; + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + }; }, toJSON(message: GetSecretRequest): unknown { @@ -13640,6 +13658,9 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } + if (message.store !== 0) { + obj.store = secretStoreToJSON(message.store); + } return obj; }, @@ -13649,6 +13670,7 @@ export const GetSecretRequest: MessageFns = { fromPartial(object: DeepPartial): GetSecretRequest { const message = createBaseGetSecretRequest(); message.key = object.key ?? ""; + message.store = object.store ?? 0; return message; }, }; @@ -13804,7 +13826,7 @@ export const SetSecretRequest: MessageFns = { }; function createBaseDeleteSecretRequest(): DeleteSecretRequest { - return { key: "" }; + return { key: "", store: 0 }; } export const DeleteSecretRequest: MessageFns = { @@ -13812,6 +13834,9 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } + if (message.store !== 0) { + writer.uint32(16).int32(message.store); + } return writer; }, @@ -13830,6 +13855,14 @@ export const DeleteSecretRequest: MessageFns = { message.key = reader.string(); continue; } + case 2: { + if (tag !== 16) { + break; + } + + message.store = reader.int32() as any; + continue; + } } if ((tag & 7) === 4 || tag === 0) { break; @@ -13840,7 +13873,10 @@ export const DeleteSecretRequest: MessageFns = { }, fromJSON(object: any): DeleteSecretRequest { - return { key: isSet(object.key) ? globalThis.String(object.key) : "" }; + return { + key: isSet(object.key) ? globalThis.String(object.key) : "", + store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + }; }, toJSON(message: DeleteSecretRequest): unknown { @@ -13848,6 +13884,9 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } + if (message.store !== 0) { + obj.store = secretStoreToJSON(message.store); + } return obj; }, @@ -13857,6 +13896,7 @@ export const DeleteSecretRequest: MessageFns = { fromPartial(object: DeepPartial): DeleteSecretRequest { const message = createBaseDeleteSecretRequest(); message.key = object.key ?? ""; + message.store = object.store ?? 0; return message; }, }; diff --git a/proto/abbenay/v1/service.proto b/proto/abbenay/v1/service.proto index b4e68ba7..2165f5f2 100644 --- a/proto/abbenay/v1/service.proto +++ b/proto/abbenay/v1/service.proto @@ -1022,6 +1022,7 @@ message DeletePolicyRequest { message GetSecretRequest { string key = 1; + SecretStore store = 2; // Backend namespace (default keychain) } message GetSecretResponse { @@ -1031,7 +1032,7 @@ message GetSecretResponse { message SetSecretRequest { string key = 1; string value = 2; - SecretStore store = 3; // Where to store + SecretStore store = 3; // Where to store (default keychain) } enum SecretStore { @@ -1043,6 +1044,7 @@ enum SecretStore { message DeleteSecretRequest { string key = 1; + SecretStore store = 2; // Backend namespace (default keychain) } message ListSecretsRequest {} From 4077c90b715995d5db33125bc538cb12ce1dedb2 Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:41:33 -0700 Subject: [PATCH 07/18] fix(daemon): align secret remove/status with namespaced stores Configure references must pin secret_store; skip env/shared secret deletes on provider remove; make GetKeyStatus and ENV error wording store-aware. --- packages/daemon/src/core/config.ts | 11 +++++++ packages/daemon/src/core/index.ts | 2 +- .../src/daemon/secrets/registry.test.ts | 2 +- .../daemon/src/daemon/secrets/registry.ts | 2 +- .../src/daemon/server/abbenay-service.ts | 33 +++++++++++++++---- packages/daemon/src/daemon/web/server.ts | 22 ++++++++++--- .../tests/integration/consumer-auth.test.ts | 8 ++++- 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/packages/daemon/src/core/config.ts b/packages/daemon/src/core/config.ts index fdf299c9..3e9418ae 100644 --- a/packages/daemon/src/core/config.ts +++ b/packages/daemon/src/core/config.ts @@ -103,6 +103,17 @@ export function providerSecretName(cfg: ProviderConfig): string | undefined { return cfg.secret_name || cfg.api_key_keychain_name || undefined; } +/** + * True when `secretName` was invented for this provider (legacy 1:1 configure). + * Shared / explicitly picked names must not be deleted with the provider. + */ +export function isProviderOwnedSecretName(providerId: string, secretName: string): boolean { + return ( + secretName === `${providerId.toUpperCase()}_API_KEY` || + secretName === `abbenay.${providerId}` + ); +} + /** * How to resolve credentials for a provider. * `store` → named backend (memory|keychain) via (secret_store, secret_name); diff --git a/packages/daemon/src/core/index.ts b/packages/daemon/src/core/index.ts index 372353ee..7b955077 100644 --- a/packages/daemon/src/core/index.ts +++ b/packages/daemon/src/core/index.ts @@ -79,7 +79,7 @@ export type { ConfigFile } from './config.js'; /** Per-provider configuration block */ export type { ProviderConfig } from './config.js'; -export { providerSecretName, providerCredentialSource } from './config.js'; +export { providerSecretName, providerCredentialSource, isProviderOwnedSecretName } from './config.js'; /** Per-model configuration block */ export type { ModelConfig } from './config.js'; diff --git a/packages/daemon/src/daemon/secrets/registry.test.ts b/packages/daemon/src/daemon/secrets/registry.test.ts index a9caed58..dbd21e17 100644 --- a/packages/daemon/src/daemon/secrets/registry.test.ts +++ b/packages/daemon/src/daemon/secrets/registry.test.ts @@ -103,7 +103,7 @@ describe('parseSecretStoreChoice', () => { const result = parseSecretStoreChoice('SECRET_STORE_ENV'); expect(result.ok).toBe(false); if (!result.ok) { - expect(result.error).toMatch(/ENV/i); + expect(result.error).toMatch(/ENV|not writable|secrets API/i); } }); diff --git a/packages/daemon/src/daemon/secrets/registry.ts b/packages/daemon/src/daemon/secrets/registry.ts index b9795457..f5279277 100644 --- a/packages/daemon/src/daemon/secrets/registry.ts +++ b/packages/daemon/src/daemon/secrets/registry.ts @@ -156,7 +156,7 @@ export function parseSecretStoreChoice( return { ok: false, error: - 'SECRET_STORE_ENV is not writable via SetSecret; configure the provider with ' + + 'SECRET_STORE_ENV is not writable via the secrets API; configure the provider with ' + 'secret_name + secret_store=env (or api_key_env_var_name)', }; } diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index 4397fbf1..77746d5d 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -22,7 +22,7 @@ import { maybeSummarize, generateSessionSummary } from '../../core/session-summa import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, isValidVirtualName, - providerSecretName, + providerSecretName, isProviderOwnedSecretName, type ConfigFile, type ProviderConfig as DaemonProviderConfig, type McpServerConfig, } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; @@ -1992,10 +1992,24 @@ export function createAbbenayService( : loadConfig()) || { providers: {} }; if (config.providers && config.providers[providerId]) { - const secretName = providerSecretName(config.providers[providerId]); - if (secretName) { + const providerCfg = config.providers[providerId]; + const secretName = providerSecretName(providerCfg); + // Env-backed names are not store keys; shared picks must outlive the provider. + if ( + secretName && + providerCfg.secret_store !== 'env' && + isProviderOwnedSecretName(providerId, secretName) + ) { try { - await state.secretStore.delete(secretName); + const registry = isSecretStoreRegistry(state.secretStore) + ? state.secretStore + : null; + const backend = providerCfg.secret_store === 'memory' ? 'memory' : 'keychain'; + if (registry) { + await registry.deleteFrom(backend, secretName); + } else { + await state.secretStore.delete(secretName); + } auditSecretChange({ key: secretName, op: 'delete', source: 'grpc-configure' }); } catch { /* ignore */ } } @@ -2052,8 +2066,15 @@ export function createAbbenayService( (async () => { try { let exists = false; - if (source === 'keychain') { - exists = await state.secretStore.has(name); + if (source === 'keychain' || source === 'memory') { + const registry = isSecretStoreRegistry(state.secretStore) + ? state.secretStore + : null; + exists = registry + ? await registry.hasIn(source, name) + : source === 'keychain' + ? await state.secretStore.has(name) + : false; } else if (source === 'env') { exists = !!process.env[name]; } diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index 580dbd00..a86b2ae0 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -16,7 +16,7 @@ import * as path from 'node:path'; import * as fs from 'node:fs'; import { fileURLToPath } from 'node:url'; import { getDefaultSocketPath } from '../transport.js'; -import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, providerSecretName, type ConfigFile, type ProviderConfig } from '../../core/config.js'; +import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, providerSecretName, isProviderOwnedSecretName, type ConfigFile, type ProviderConfig } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; import { isSecretStoreRegistry, parseSecretStoreChoice } from '../secrets/registry.js'; import { @@ -1588,10 +1588,24 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): : loadConfig()) || { providers: {} }; if (config.providers && config.providers[providerId]) { - const secretName = providerSecretName(config.providers[providerId]); - if (secretName) { + const providerCfg = config.providers[providerId]; + const secretName = providerSecretName(providerCfg); + // Env-backed names are not store keys; shared picks must outlive the provider. + if ( + secretName && + providerCfg.secret_store !== 'env' && + isProviderOwnedSecretName(providerId, secretName) + ) { try { - await state.secretStore.delete(secretName); + const registry = isSecretStoreRegistry(state.secretStore) + ? state.secretStore + : null; + const backend = providerCfg.secret_store === 'memory' ? 'memory' : 'keychain'; + if (registry) { + await registry.deleteFrom(backend, secretName); + } else { + await state.secretStore.delete(secretName); + } auditSecretChange({ key: secretName, op: 'delete', source: 'http-configure' }); } catch { /* ignore */ } } diff --git a/packages/daemon/tests/integration/consumer-auth.test.ts b/packages/daemon/tests/integration/consumer-auth.test.ts index af964a01..153fab96 100644 --- a/packages/daemon/tests/integration/consumer-auth.test.ts +++ b/packages/daemon/tests/integration/consumer-auth.test.ts @@ -283,15 +283,21 @@ describe('Consumer auth RPC gating', () => { provider_id: 'work-openai', engine: 'mock', secret_name: 'SHARED_OPENAI', + secret_store: 'SECRET_STORE_MEMORY', }, GOOD_TOKEN); expect(res.success).toBe(true); const saved = mockSaveConfig.mock.calls.at(-1)?.[0] as { providers: { - 'work-openai': { secret_name?: string; api_key_keychain_name?: string }; + 'work-openai': { + secret_name?: string; + secret_store?: string; + api_key_keychain_name?: string; + }; }; }; expect(saved.providers['work-openai'].secret_name).toBe('SHARED_OPENAI'); + expect(saved.providers['work-openai'].secret_store).toBe('memory'); expect(saved.providers['work-openai'].api_key_keychain_name).toBe('SHARED_OPENAI'); // Reference path must not invent a provider-scoped key name or rewrite the secret. expect(mockSecretStoreData.has('WORK-OPENAI_API_KEY')).toBe(false); From 6c1e6b89bb6aeceecd30f26ed07346f9a56875ba Mon Sep 17 00:00:00 2001 From: "Bradley A. Thornton" Date: Wed, 12 Aug 2026 09:43:55 -0700 Subject: [PATCH 08/18] fix(daemon): normalize keytar missing values to null SecretStore.get promises string|null; keytar returns undefined for absent entries, which broke has() and flaked keychain unit tests in CI. --- packages/daemon/src/daemon/secrets/keychain.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/daemon/src/daemon/secrets/keychain.ts b/packages/daemon/src/daemon/secrets/keychain.ts index fdc8353c..d91def17 100644 --- a/packages/daemon/src/daemon/secrets/keychain.ts +++ b/packages/daemon/src/daemon/secrets/keychain.ts @@ -83,7 +83,8 @@ export class KeychainSecretStore implements SecretStore { if (!kt) return null; try { - return await kt.getPassword(SERVICE_NAME, key); + // keytar returns undefined for missing entries; SecretStore requires null. + return (await kt.getPassword(SERVICE_NAME, key)) ?? null; } catch (error: unknown) { const msg = error instanceof Error ? error.message : String(error); console.error(`[Secrets] Failed to get key '${key}':`, msg); From 9a5b7be57f2a17ef0242061cfd2eed3e14b0177b Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 05:14:29 -0700 Subject: [PATCH 09/18] test(daemon): cover namespaced secret store resolve and remove paths Add unit/integration coverage for providerCredentialSource, memory-vs-keychain resolveApiKey, RemoveProvider owned-secret deletion (and env/shared skips), ListSecrets per-backend rows, and HTTP memory delete/key-status isolation. Co-authored-by: Cursor --- packages/daemon/src/core/config.test.ts | 70 ++++++++++++++ packages/daemon/src/core/state.test.ts | 63 ++++++++++++ .../src/daemon/server/abbenay-service.test.ts | 95 ++++++++++++++++++- .../tests/integration/consumer-auth.test.ts | 2 +- .../integration/grpc-real-service.test.ts | 63 ++++++++++++ .../daemon/tests/integration/web-sse.test.ts | 68 +++++++++++-- 6 files changed, 349 insertions(+), 12 deletions(-) diff --git a/packages/daemon/src/core/config.test.ts b/packages/daemon/src/core/config.test.ts index 7b7bc056..2fa47e1b 100644 --- a/packages/daemon/src/core/config.test.ts +++ b/packages/daemon/src/core/config.test.ts @@ -31,6 +31,9 @@ import { getEnabledModelNames, isValidVirtualName, resolveEngineModelId, + providerSecretName, + isProviderOwnedSecretName, + providerCredentialSource, type ConfigFile, } from './config.js'; @@ -65,6 +68,73 @@ function createWorkspace(name: string, data: Record): string { // ── isValidVirtualName ──────────────────────────────────────────────────────── +describe('providerSecretName / isProviderOwnedSecretName / providerCredentialSource', () => { + it('prefers secret_name over legacy api_key_keychain_name', () => { + expect(providerSecretName({ engine: 'openai', secret_name: 'SHARED' })).toBe('SHARED'); + expect(providerSecretName({ + engine: 'openai', + secret_name: 'SHARED', + api_key_keychain_name: 'LEGACY', + })).toBe('SHARED'); + expect(providerSecretName({ + engine: 'openai', + api_key_keychain_name: 'LEGACY', + })).toBe('LEGACY'); + expect(providerSecretName({ engine: 'openai' })).toBeUndefined(); + }); + + it('recognizes only invented provider-owned secret names', () => { + expect(isProviderOwnedSecretName('work-openai', 'WORK-OPENAI_API_KEY')).toBe(true); + expect(isProviderOwnedSecretName('work-openai', 'abbenay.work-openai')).toBe(true); + expect(isProviderOwnedSecretName('work-openai', 'SHARED_OPENAI')).toBe(false); + expect(isProviderOwnedSecretName('work-openai', 'OPENAI_API_KEY')).toBe(false); + }); + + it('resolves store backends with keychain default and memory override', () => { + expect(providerCredentialSource({ + engine: 'openai', + secret_name: 'K', + })).toEqual({ kind: 'store', name: 'K', backend: 'keychain' }); + + expect(providerCredentialSource({ + engine: 'openai', + secret_name: 'K', + secret_store: 'memory', + })).toEqual({ kind: 'store', name: 'K', backend: 'memory' }); + + expect(providerCredentialSource({ + engine: 'openai', + secret_name: 'K', + secret_store: 'keychain', + })).toEqual({ kind: 'store', name: 'K', backend: 'keychain' }); + }); + + it('resolves env via secret_store=env or legacy api_key_env_var_name', () => { + expect(providerCredentialSource({ + engine: 'openai', + secret_name: 'MY_ENV', + secret_store: 'env', + })).toEqual({ kind: 'env', name: 'MY_ENV' }); + + expect(providerCredentialSource({ + engine: 'openai', + secret_store: 'env', + api_key_env_var_name: 'LEGACY_ENV', + })).toEqual({ kind: 'env', name: 'LEGACY_ENV' }); + + expect(providerCredentialSource({ + engine: 'openai', + api_key_env_var_name: 'ONLY_ENV', + })).toEqual({ kind: 'env', name: 'ONLY_ENV' }); + + expect(providerCredentialSource({ engine: 'openai' })).toBeNull(); + expect(providerCredentialSource({ + engine: 'openai', + secret_store: 'env', + })).toBeNull(); + }); +}); + describe('isValidVirtualName', () => { it('should accept simple lowercase names', () => { expect(isValidVirtualName('openrouter')).toBe(true); diff --git a/packages/daemon/src/core/state.test.ts b/packages/daemon/src/core/state.test.ts index 41c31646..69d22fbf 100644 --- a/packages/daemon/src/core/state.test.ts +++ b/packages/daemon/src/core/state.test.ts @@ -7,6 +7,7 @@ import type { ConfigFile } from './config.js'; import type { DiscoveredModel } from './engines.js'; import { MemorySecretStore } from './secrets.js'; import { ToolRegistry } from './tool-registry.js'; +import type { NamespacedSecretStore } from './secrets.js'; // ── Partial engines mock (preserve real getEngine for addProvider policy tests) ── @@ -260,6 +261,68 @@ describe('CoreState.resolveApiKey', () => { expect(await core.resolveApiKey('openrouter')).toBe('sk-from-store'); }); + it('reads only the configured memory backend from a namespaced store', async () => { + const memory = new Map([['SHARED', 'from-memory']]); + const keychain = new Map([['SHARED', 'from-keychain']]); + const store: NamespacedSecretStore = { + get: async (key) => keychain.get(key) ?? null, + set: async (key, value) => { keychain.set(key, value); }, + delete: async (key) => keychain.delete(key), + has: async (key) => keychain.has(key), + getFrom: async (backend, key) => (backend === 'memory' ? memory : keychain).get(key) ?? null, + setIn: async (backend, key, value) => { (backend === 'memory' ? memory : keychain).set(key, value); }, + deleteFrom: async (backend, key) => (backend === 'memory' ? memory : keychain).delete(key), + hasIn: async (backend, key) => (backend === 'memory' ? memory : keychain).has(key), + }; + const core = createCore({ + secretStore: store, + config: { + providers: { + mem: { + engine: 'openrouter', + secret_name: 'SHARED', + secret_store: 'memory', + models: {}, + }, + kc: { + engine: 'openrouter', + secret_name: 'SHARED', + secret_store: 'keychain', + models: {}, + }, + }, + }, + }); + + expect(await core.resolveApiKey('mem')).toBe('from-memory'); + expect(await core.resolveApiKey('kc')).toBe('from-keychain'); + }); + + it('resolves secret_store=env without consulting the secret store', async () => { + const store = new MemorySecretStore(); + await store.set('SHOULD_NOT_USE', 'from-store'); + const core = createCore({ + secretStore: store, + config: { + providers: { + envp: { + engine: 'openrouter', + secret_name: 'ABBENAY_TEST_RESOLVE_ENV', + secret_store: 'env', + models: {}, + }, + }, + }, + }); + + process.env.ABBENAY_TEST_RESOLVE_ENV = 'from-env'; + try { + expect(await core.resolveApiKey('envp')).toBe('from-env'); + } finally { + delete process.env.ABBENAY_TEST_RESOLVE_ENV; + } + }); + it('falls back to configured env var then engine default env var', async () => { const core = createCore({ config: { diff --git a/packages/daemon/src/daemon/server/abbenay-service.test.ts b/packages/daemon/src/daemon/server/abbenay-service.test.ts index cdb47455..d959ed0a 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.test.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.test.ts @@ -88,9 +88,13 @@ vi.mock('../../core/session-summarizer.js', () => ({ generateSessionSummary: (...a: unknown[]) => mockGenerateSessionSummary(...a), })); -vi.mock('../../core/secrets.js', () => ({ - auditSecretChange: (...a: unknown[]) => mockAuditSecretChange(...a), -})); +vi.mock('../../core/secrets.js', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + auditSecretChange: (...a: unknown[]) => mockAuditSecretChange(...a), + }; +}); vi.mock('../../core/provider-endpoint.js', () => ({ auditProviderEndpointChange: (...a: unknown[]) => mockAuditProviderEndpointChange(...a), @@ -995,6 +999,75 @@ describe('createAbbenayService handlers', () => { expect(state.notifyModelsChanged).toHaveBeenCalledWith('provider_removed'); }); + it('RemoveProvider deletes owned memory secret from the memory backend only', async () => { + const { SecretStoreRegistry } = await import('../secrets/registry.js'); + const { MemorySecretStore } = await import('../../core/secrets.js'); + const memory = new MemorySecretStore(); + const keychain = new MemorySecretStore(); + await memory.set('MYMOCK_API_KEY', 'mem-value'); + await keychain.set('MYMOCK_API_KEY', 'kc-value'); + const registry = new SecretStoreRegistry(memory, keychain); + + mockLoadConfig.mockReturnValue({ + providers: { + mymock: { + engine: 'mock', + secret_name: 'MYMOCK_API_KEY', + secret_store: 'memory', + }, + }, + }); + const state = createMockState({ secretStore: registry }); + const service = createServiceHandlers(state); + + const { error } = await invokeUnary(service.RemoveProvider, { provider_id: 'mymock' }); + expect(error).toBeNull(); + expect(await memory.has('MYMOCK_API_KEY')).toBe(false); + expect(await keychain.has('MYMOCK_API_KEY')).toBe(true); + expect(mockAuditSecretChange).toHaveBeenCalledWith({ + key: 'MYMOCK_API_KEY', + op: 'delete', + source: 'grpc-configure', + }); + }); + + it('RemoveProvider skips env-backed and shared secret names', async () => { + const { SecretStoreRegistry } = await import('../secrets/registry.js'); + const { MemorySecretStore } = await import('../../core/secrets.js'); + const memory = new MemorySecretStore(); + const keychain = new MemorySecretStore(); + await keychain.set('SHARED_OPENAI', 'shared'); + await keychain.set('ENV_LOOKALIKE', 'should-remain'); + const registry = new SecretStoreRegistry(memory, keychain); + const state = createMockState({ secretStore: registry }); + const service = createServiceHandlers(state); + + mockLoadConfig.mockReturnValue({ + providers: { + 'env-openai': { + engine: 'mock', + secret_name: 'ENV_LOOKALIKE', + secret_store: 'env', + }, + }, + }); + expect((await invokeUnary(service.RemoveProvider, { provider_id: 'env-openai' })).error).toBeNull(); + expect(await keychain.has('ENV_LOOKALIKE')).toBe(true); + + mockLoadConfig.mockReturnValue({ + providers: { + 'shared-openai': { + engine: 'mock', + secret_name: 'SHARED_OPENAI', + secret_store: 'keychain', + }, + }, + }); + expect((await invokeUnary(service.RemoveProvider, { provider_id: 'shared-openai' })).error).toBeNull(); + expect(await keychain.has('SHARED_OPENAI')).toBe(true); + expect(mockAuditSecretChange).not.toHaveBeenCalled(); + }); + it('GetKeyStatus checks keychain and env sources', async () => { const state = createMockState({ secretStore: { has: vi.fn().mockResolvedValue(true) }, @@ -1018,6 +1091,22 @@ describe('createAbbenayService handlers', () => { expect(missing.error?.code).toBe(grpc.status.INVALID_ARGUMENT); }); + it('GetKeyStatus checks memory independently of keychain', async () => { + const { SecretStoreRegistry } = await import('../secrets/registry.js'); + const { MemorySecretStore } = await import('../../core/secrets.js'); + const memory = new MemorySecretStore(); + const keychain = new MemorySecretStore(); + await memory.set('MEM_ONLY', 'v'); + const registry = new SecretStoreRegistry(memory, keychain); + const state = createMockState({ secretStore: registry }); + const service = createServiceHandlers(state); + + const mem = await invokeUnary(service.GetKeyStatus, { source: 'memory', name: 'MEM_ONLY' }); + expect(mem.response?.exists).toBe(true); + const kc = await invokeUnary(service.GetKeyStatus, { source: 'keychain', name: 'MEM_ONLY' }); + expect(kc.response?.exists).toBe(false); + }); + it('ListMcpServerConfigs merges config and runtime statuses', async () => { mockLoadConfig.mockReturnValue({ mcp_servers: { diff --git a/packages/daemon/tests/integration/consumer-auth.test.ts b/packages/daemon/tests/integration/consumer-auth.test.ts index 153fab96..f5fbbbdc 100644 --- a/packages/daemon/tests/integration/consumer-auth.test.ts +++ b/packages/daemon/tests/integration/consumer-auth.test.ts @@ -341,7 +341,7 @@ describe('Consumer auth RPC gating', () => { } }); - it('ConfigureProvider rejects secret_store=env is not required when unset', async () => { + it('ConfigureProvider accepts secret_store=env even when the env var is unset', async () => { delete process.env.ABBENAY_TEST_PROVIDER_ENV_MISSING; const res = await callUnary(client, 'ConfigureProvider', { provider_id: 'env-missing', diff --git a/packages/daemon/tests/integration/grpc-real-service.test.ts b/packages/daemon/tests/integration/grpc-real-service.test.ts index 972c59f1..8b51970c 100644 --- a/packages/daemon/tests/integration/grpc-real-service.test.ts +++ b/packages/daemon/tests/integration/grpc-real-service.test.ts @@ -337,6 +337,69 @@ describe('Real gRPC service: Secrets', () => { }), ).rejects.toMatchObject({ code: grpc.status.INVALID_ARGUMENT }); }); + + it('should delete SECRET_STORE_MEMORY without touching keychain', async () => { + await callUnary(client, 'SetSecret', { + key: 'BOTH_DEL', + value: 'persistent', + store: 'SECRET_STORE_KEYCHAIN', + }); + await callUnary(client, 'SetSecret', { + key: 'BOTH_DEL', + value: 'ephemeral', + store: 'SECRET_STORE_MEMORY', + }); + + await callUnary(client, 'DeleteSecret', { + key: 'BOTH_DEL', + store: 'SECRET_STORE_MEMORY', + }); + + const mem = await callUnary(client, 'GetSecret', { + key: 'BOTH_DEL', + store: 'SECRET_STORE_MEMORY', + }); + expect(mem.value).toBe(''); + const kc = await callUnary(client, 'GetSecret', { + key: 'BOTH_DEL', + store: 'SECRET_STORE_KEYCHAIN', + }); + expect(kc.value).toBe('persistent'); + expect(mockSecretStoreData.get('BOTH_DEL')).toBe('persistent'); + }); + + it('ListSecrets emits one row per backend that holds an engine key', async () => { + mockGetEngines.mockReturnValueOnce([ + { + id: 'openai', + requiresKey: true, + defaultEnvVar: 'OPENAI_API_KEY', + supportsTools: true, + createModel: () => { throw new Error('mock'); }, + }, + ]); + + await callUnary(client, 'SetSecret', { + key: 'OPENAI_API_KEY', + value: 'kc', + store: 'SECRET_STORE_KEYCHAIN', + }); + await callUnary(client, 'SetSecret', { + key: 'OPENAI_API_KEY', + value: 'mem', + store: 'SECRET_STORE_MEMORY', + }); + + const res = await callUnary(client, 'ListSecrets', {}); + const openaiRows = (res.secrets as Array<{ key: string; store?: string | number }>).filter( + (s) => s.key === 'OPENAI_API_KEY' && s.store, + ); + expect(openaiRows.length).toBe(2); + const stores = openaiRows.map((r) => String(r.store)); + expect(stores).toEqual( + expect.arrayContaining(['SECRET_STORE_MEMORY', 'SECRET_STORE_KEYCHAIN']), + ); + }); }); describe('Real gRPC service: Chat streaming', () => { diff --git a/packages/daemon/tests/integration/web-sse.test.ts b/packages/daemon/tests/integration/web-sse.test.ts index 704ea9ed..2257ecb2 100644 --- a/packages/daemon/tests/integration/web-sse.test.ts +++ b/packages/daemon/tests/integration/web-sse.test.ts @@ -37,7 +37,8 @@ import { createWebApp } from '../../src/daemon/web/server.js'; import type { DaemonState } from '../../src/daemon/state.js'; import type { ProviderInfo, ModelInfo } from '../../src/core/state.js'; import type { ConnectedClient } from '../../src/daemon/state.js'; -import type { SecretStore } from '../../src/core/secrets.js'; +import { MemorySecretStore } from '../../src/core/secrets.js'; +import { SecretStoreRegistry } from '../../src/daemon/secrets/registry.js'; // ─── Mock DaemonState ─────────────────────────────────────────────────── @@ -58,13 +59,11 @@ let mockChatConfig: MockChatConfig = { const chatRequests: Array<{ model: string; messages: any[] }> = []; -/** In-memory secret store for testing */ -const mockSecretStore: SecretStore = { - async get(key: string) { return key === 'OPENAI_API_KEY' ? 'sk-test' : null; }, - async set(_key: string, _value: string) {}, - async delete(_key: string) { return true; }, - async has(key: string) { return key === 'OPENAI_API_KEY'; }, -}; +/** Namespaced secret store matching daemon production wiring */ +const mockSecretStore = new SecretStoreRegistry( + new MemorySecretStore(), + new MemorySecretStore(), +); function sleep(ms: number): Promise { return new Promise((r) => setTimeout(r, ms)); @@ -141,6 +140,7 @@ let httpServer: http.Server; let baseUrl: string; beforeAll(async () => { + await mockSecretStore.setIn('keychain', 'OPENAI_API_KEY', 'sk-test'); const state = createMockState(); const app = createWebApp(state, { apiToken: 'test-integration-token', skipConfig: true }); @@ -496,6 +496,58 @@ describe('Web API - Secrets Endpoints', () => { expect(body.error).toMatch(/ENV/i); }); + it('DELETE /api/secrets/:key?secret_store=memory clears memory only', async () => { + await httpRequest('POST', `${baseUrl}/api/secrets/BOTH_HTTP`, { + value: 'persistent', + secret_store: 'keychain', + }); + await httpRequest('POST', `${baseUrl}/api/secrets/BOTH_HTTP`, { + value: 'ephemeral', + secret_store: 'memory', + }); + + const { statusCode, body } = await httpRequest( + 'DELETE', + `${baseUrl}/api/secrets/BOTH_HTTP?secret_store=memory`, + ); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + expect(body.secret_store).toBe('memory'); + + const memStatus = await httpRequest( + 'GET', + `${baseUrl}/api/key-status?source=memory&name=BOTH_HTTP`, + ); + expect(memStatus.statusCode).toBe(200); + expect(memStatus.body.exists).toBe(false); + + const kcStatus = await httpRequest( + 'GET', + `${baseUrl}/api/key-status?source=keychain&name=BOTH_HTTP`, + ); + expect(kcStatus.statusCode).toBe(200); + expect(kcStatus.body.exists).toBe(true); + }); + + it('GET /api/key-status?source=memory reports memory-only secrets', async () => { + await httpRequest('POST', `${baseUrl}/api/secrets/MEM_STATUS`, { + value: 'ephemeral', + secret_store: 'memory', + }); + const mem = await httpRequest( + 'GET', + `${baseUrl}/api/key-status?source=memory&name=MEM_STATUS`, + ); + expect(mem.statusCode).toBe(200); + expect(mem.body.exists).toBe(true); + const kc = await httpRequest( + 'GET', + `${baseUrl}/api/key-status?source=keychain&name=MEM_STATUS`, + ); + expect(kc.statusCode).toBe(200); + expect(kc.body.exists).toBe(false); + }); + it('POST /api/secrets/:key should reject missing value', async () => { const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets/TEST_KEY`, {}); expect(statusCode).toBe(400); From 7bcc55998d14d5864e5350172ed40acec5f4925a Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 05:20:24 -0700 Subject: [PATCH 10/18] test(daemon): raise patch coverage for namespaced secret HTTP/gRPC paths Cover provider configure/remove via HTTP, ConfigureProvider memory writes and validation conflicts, schema refinements, and secret_name/env YAML migration so codecov/patch can clear the 80% target. Co-authored-by: Cursor --- packages/daemon/src/core/config.test.ts | 33 ++++ .../src/daemon/server/abbenay-service.test.ts | 109 +++++++++++++ .../daemon/src/daemon/web/api-schemas.test.ts | 30 ++++ .../daemon/tests/integration/web-sse.test.ts | 151 ++++++++++++++++++ 4 files changed, 323 insertions(+) diff --git a/packages/daemon/src/core/config.test.ts b/packages/daemon/src/core/config.test.ts index 2fa47e1b..54c0cdcf 100644 --- a/packages/daemon/src/core/config.test.ts +++ b/packages/daemon/src/core/config.test.ts @@ -229,6 +229,39 @@ describe('loadConfigFromPath (new schema)', () => { }); expect(loadConfigFromPath(filePath)).toEqual({ providers: {} }); }); + + it('mirrors secret_name / env aliases and defaults secret_store', () => { + const filePath = writeYaml(path.join(tmpDir, 'secrets.yaml'), { + providers: { + named: { + engine: 'openai', + secret_name: 'SHARED_KEY', + models: {}, + }, + envlegacy: { + engine: 'openai', + api_key_env_var_name: 'ONLY_ENV', + models: {}, + }, + envin: { + engine: 'openai', + secret_name: 'MY_ENV', + secret_store: 'env', + models: {}, + }, + }, + }); + const config = loadConfigFromPath(filePath)!; + expect(config.providers!.named.secret_name).toBe('SHARED_KEY'); + expect(config.providers!.named.api_key_keychain_name).toBe('SHARED_KEY'); + expect(config.providers!.named.secret_store).toBe('keychain'); + + expect(config.providers!.envlegacy.secret_name).toBe('ONLY_ENV'); + expect(config.providers!.envlegacy.secret_store).toBe('env'); + + expect(config.providers!.envin.api_key_env_var_name).toBe('MY_ENV'); + expect(config.providers!.envin.secret_store).toBe('env'); + }); }); // ── loadConfigFromPath (old schema migration) ──────────────────────────────── diff --git a/packages/daemon/src/daemon/server/abbenay-service.test.ts b/packages/daemon/src/daemon/server/abbenay-service.test.ts index d959ed0a..cf1ba891 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.test.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.test.ts @@ -402,6 +402,19 @@ describe('protoToConfigFile', () => { expect(config.providers!['my-provider'].api_key_keychain_name).toBeUndefined(); }); + it('maps proto secret_store enum values onto provider config', () => { + const config = protoToConfigFile({ + providers: { + mem: { engine: 'openai', secret_name: 'M', secret_store: 3 }, + envp: { engine: 'openai', secret_name: 'E', secret_store: 'SECRET_STORE_ENV' }, + kc: { engine: 'openai', secret_name: 'K', secret_store: 'SECRET_STORE_KEYCHAIN' }, + }, + }); + expect(config.providers!.mem.secret_store).toBe('memory'); + expect(config.providers!.envp.secret_store).toBe('env'); + expect(config.providers!.kc.secret_store).toBe('keychain'); + }); + it('provider with no models gets undefined models field', () => { const proto = { providers: { @@ -982,6 +995,102 @@ describe('createAbbenayService handlers', () => { expect(mockAuditSecretChange).toHaveBeenCalled(); }); + it('ConfigureProvider writes api_key to memory and rejects conflicting credential fields', async () => { + const { SecretStoreRegistry } = await import('../secrets/registry.js'); + const { MemorySecretStore } = await import('../../core/secrets.js'); + const registry = new SecretStoreRegistry(new MemorySecretStore(), new MemorySecretStore()); + const state = createMockState({ secretStore: registry }); + const service = createServiceHandlers(state); + + const mem = await invokeUnary(service.ConfigureProvider, { + provider_id: 'mem-mock', + engine: 'mock', + api_key: 'ephemeral', + secret_store: 'SECRET_STORE_MEMORY', + secret_name: 'MEM_MOCK_API_KEY', + }); + expect(mem.response?.success).toBe(true); + expect(await registry.getFrom('memory', 'MEM_MOCK_API_KEY')).toBe('ephemeral'); + expect(await registry.hasIn('keychain', 'MEM_MOCK_API_KEY')).toBe(false); + expect(mockAuditSecretChange).toHaveBeenCalledWith({ + key: 'MEM_MOCK_API_KEY', + op: 'set', + source: 'grpc-configure-memory', + }); + + expect((await invokeUnary(service.ConfigureProvider, { + provider_id: 'bad-combo', + engine: 'mock', + api_key: 'x', + env_var_name: 'Y', + })).error?.code).toBe(grpc.status.INVALID_ARGUMENT); + + expect((await invokeUnary(service.ConfigureProvider, { + provider_id: 'bad-combo-2', + engine: 'mock', + secret_name: 'X', + env_var_name: 'Y', + })).error?.code).toBe(grpc.status.INVALID_ARGUMENT); + + expect((await invokeUnary(service.ConfigureProvider, { + provider_id: 'bad-store', + engine: 'mock', + api_key: 'x', + secret_store: 'SECRET_STORE_ENV', + })).error?.code).toBe(grpc.status.INVALID_ARGUMENT); + + expect((await invokeUnary(service.ConfigureProvider, { + provider_id: 'missing-secret', + engine: 'mock', + secret_name: 'DOES_NOT_EXIST', + secret_store: 'SECRET_STORE_MEMORY', + })).error?.code).toBe(grpc.status.INVALID_ARGUMENT); + + // secret_name without store defaults to keychain lookup. + await registry.setIn('keychain', 'DEFAULT_KC', 'v'); + const def = await invokeUnary(service.ConfigureProvider, { + provider_id: 'default-kc', + engine: 'mock', + secret_name: 'DEFAULT_KC', + }); + expect(def.response?.success).toBe(true); + + expect((await invokeUnary(service.ConfigureProvider, { + provider_id: 'bad-ref-store', + engine: 'mock', + secret_name: 'X', + secret_store: 'vault', + })).error?.code).toBe(grpc.status.INVALID_ARGUMENT); + }); + + it('Secrets RPCs reject unsupported store selections', async () => { + const state = createMockState(); + const service = createServiceHandlers(state); + expect((await invokeUnary(service.GetSecret, { key: 'K', store: 'vault' })).error?.code) + .toBe(grpc.status.INVALID_ARGUMENT); + expect((await invokeUnary(service.DeleteSecret, { key: 'K', store: 'SECRET_STORE_ENV' })).error?.code) + .toBe(grpc.status.INVALID_ARGUMENT); + }); + + it('ListSecrets returns empty has_value rows when registry backends lack the key', async () => { + mockGetEngine.mockImplementation((id: string) => ( + id === 'mock' ? { id: 'mock', requiresKey: false, defaultEnvVar: 'MOCK_API_KEY' } + : id === 'secure' ? { id: 'secure', requiresKey: true, defaultEnvVar: 'SECURE_API_KEY' } + : undefined + )); + // getEngines is mocked at module level to return mock+secure + const { SecretStoreRegistry } = await import('../secrets/registry.js'); + const { MemorySecretStore } = await import('../../core/secrets.js'); + const registry = new SecretStoreRegistry(new MemorySecretStore(), new MemorySecretStore()); + const state = createMockState({ secretStore: registry }); + const service = createServiceHandlers(state); + const listed = await invokeUnary(service.ListSecrets, {}); + const rows = rpcArray<{ key: string; has_value?: boolean }>(listed.response, 'secrets'); + const secure = rows.filter((r) => r.key === 'SECURE_API_KEY'); + expect(secure.length).toBeGreaterThanOrEqual(1); + expect(secure.every((r) => r.has_value === false)).toBe(true); + }); + it('RemoveProvider deletes provider and keychain secret', async () => { mockLoadConfig.mockReturnValue({ providers: { diff --git a/packages/daemon/src/daemon/web/api-schemas.test.ts b/packages/daemon/src/daemon/web/api-schemas.test.ts index 415c2d30..f3d943e7 100644 --- a/packages/daemon/src/daemon/web/api-schemas.test.ts +++ b/packages/daemon/src/daemon/web/api-schemas.test.ts @@ -74,6 +74,36 @@ describe('PostProviderConfigureBodySchema', () => { ).toBe(true); }); + it('accepts secretStore memory|keychain|env with apiKey or secretName', () => { + expect( + PostProviderConfigureBodySchema.safeParse({ + engine: 'openai', + apiKey: 'sk-test', + secretStore: 'memory', + secretName: 'MY_KEY', + }).success, + ).toBe(true); + expect( + PostProviderConfigureBodySchema.safeParse({ + engine: 'openai', + secretName: 'ENV_VAR', + secretStore: 'env', + }).success, + ).toBe(true); + }); + + it('rejects apiKey together with envVarName', () => { + const result = PostProviderConfigureBodySchema.safeParse({ + engine: 'openai', + apiKey: 'sk-test', + envVarName: 'OPENAI_API_KEY', + }); + expect(result.success).toBe(false); + if (!result.success) { + expect(result.error.issues.some((i) => i.path.includes('apiKey'))).toBe(true); + } + }); + it('rejects secretName together with envVarName', () => { expect( PostProviderConfigureBodySchema.safeParse({ diff --git a/packages/daemon/tests/integration/web-sse.test.ts b/packages/daemon/tests/integration/web-sse.test.ts index 2257ecb2..4c3e6275 100644 --- a/packages/daemon/tests/integration/web-sse.test.ts +++ b/packages/daemon/tests/integration/web-sse.test.ts @@ -548,6 +548,157 @@ describe('Web API - Secrets Endpoints', () => { expect(kc.body.exists).toBe(false); }); + it('POST /api/provider/:id/configure writes apiKey to memory backend', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/mem-openai/configure`, { + engine: 'openai', + apiKey: 'sk-mem', + secretName: 'MEM_OPENAI_API_KEY', + secretStore: 'memory', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + expect(await mockSecretStore.getFrom('memory', 'MEM_OPENAI_API_KEY')).toBe('sk-mem'); + expect(await mockSecretStore.hasIn('keychain', 'MEM_OPENAI_API_KEY')).toBe(false); + }); + + it('POST /api/provider/:id/configure picks an existing memory secret', async () => { + await httpRequest('POST', `${baseUrl}/api/secrets/SHARED_MEM`, { + value: 'shared-value', + secret_store: 'memory', + }); + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/shared-openai/configure`, { + engine: 'openai', + secretName: 'SHARED_MEM', + secretStore: 'memory', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + }); + + it('POST /api/provider/:id/configure accepts secretStore=env without writing store', async () => { + const before = await mockSecretStore.locateAll('ABBENAY_HTTP_ENV'); + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/env-openai/configure`, { + engine: 'openai', + secretName: 'ABBENAY_HTTP_ENV', + secretStore: 'env', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + expect(await mockSecretStore.locateAll('ABBENAY_HTTP_ENV')).toEqual(before); + }); + + it('POST /api/provider/:id/configure rejects missing referenced secret', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/missing-openai/configure`, { + engine: 'openai', + secretName: 'DOES_NOT_EXIST', + secretStore: 'memory', + }); + expect(statusCode).toBe(400); + expect(body.error).toMatch(/not found/i); + }); + + it('POST /api/provider/:id/configure defaults omitted secretStore to keychain', async () => { + await httpRequest('POST', `${baseUrl}/api/secrets/DEFAULT_KC`, { + value: 'kc-value', + secret_store: 'keychain', + }); + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/default-kc/configure`, { + engine: 'openai', + secretName: 'DEFAULT_KC', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + }); + + it('POST /api/provider/:id/configure rejects missing keychain secret when store omitted', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/missing-kc/configure`, { + engine: 'openai', + secretName: 'NO_SUCH_KEYCHAIN_SECRET', + }); + expect(statusCode).toBe(400); + expect(body.error).toMatch(/not found in keychain/i); + }); + + it('POST /api/provider/:id/configure accepts envVarName legacy field', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/legacy-env/configure`, { + engine: 'openai', + envVarName: 'ABBENAY_LEGACY_ENV', + }); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + }); + + it('POST /api/secrets/:key rejects invalid store and legacy POST accepts memory', async () => { + const bad = await httpRequest('POST', `${baseUrl}/api/secrets/BAD_STORE`, { + value: 'x', + secret_store: 'vault', + }); + expect(bad.statusCode).toBe(400); + + const legacy = await httpRequest('POST', `${baseUrl}/api/secrets`, { + key: 'LEGACY_MEM', + value: 'v', + store: 'memory', + }); + expect(legacy.statusCode).toBe(200); + expect(legacy.body.secret_store).toBe('memory'); + expect(await mockSecretStore.getFrom('memory', 'LEGACY_MEM')).toBe('v'); + }); + + it('DELETE /api/secrets/:key rejects invalid store', async () => { + const { statusCode } = await httpRequest( + 'DELETE', + `${baseUrl}/api/secrets/ANY?secret_store=vault`, + ); + expect(statusCode).toBe(400); + }); + + it('POST /api/provider/:id/configure rejects apiKey with secretStore=env', async () => { + const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/provider/bad-openai/configure`, { + engine: 'openai', + apiKey: 'sk-x', + secretStore: 'env', + }); + expect(statusCode).toBe(400); + expect(body.error).toMatch(/ENV|not writable|secrets API/i); + }); + + it('DELETE /api/provider/:id removes owned memory secret only', async () => { + await httpRequest('POST', `${baseUrl}/api/provider/owndel/configure`, { + engine: 'openai', + apiKey: 'sk-owned', + secretName: 'OWNDEL_API_KEY', + secretStore: 'memory', + }); + await mockSecretStore.setIn('keychain', 'OWNDEL_API_KEY', 'keep-me'); + + const { statusCode, body } = await httpRequest('DELETE', `${baseUrl}/api/provider/owndel`); + expect(statusCode).toBe(200); + expect(body.success).toBe(true); + expect(await mockSecretStore.hasIn('memory', 'OWNDEL_API_KEY')).toBe(false); + expect(await mockSecretStore.hasIn('keychain', 'OWNDEL_API_KEY')).toBe(true); + }); + + it('DELETE /api/provider/:id skips shared and env-backed secrets', async () => { + await mockSecretStore.setIn('keychain', 'SHARED_KEEP', 'shared'); + // Seed config with shared + env providers via configure endpoints. + await httpRequest('POST', `${baseUrl}/api/provider/shared-keep/configure`, { + engine: 'openai', + secretName: 'SHARED_KEEP', + secretStore: 'keychain', + }); + await httpRequest('POST', `${baseUrl}/api/provider/env-keep/configure`, { + engine: 'openai', + secretName: 'ENV_KEEP', + secretStore: 'env', + }); + + expect((await httpRequest('DELETE', `${baseUrl}/api/provider/shared-keep`)).statusCode).toBe(200); + expect(await mockSecretStore.hasIn('keychain', 'SHARED_KEEP')).toBe(true); + + expect((await httpRequest('DELETE', `${baseUrl}/api/provider/env-keep`)).statusCode).toBe(200); + }); + it('POST /api/secrets/:key should reject missing value', async () => { const { statusCode, body } = await httpRequest('POST', `${baseUrl}/api/secrets/TEST_KEY`, {}); expect(statusCode).toBe(400); From 8ca5edb1949d3dc598c3183700a0a5b6c2086430 Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 05:30:49 -0700 Subject: [PATCH 11/18] ci(sonar): classify test-env.ts as a test helper, not production source Sonar only treated *.test.ts as tests, so the colocated withEnv helper was flagged for uncovered lines. Exclude/include it the same way as test files. Co-authored-by: Cursor --- sonar-project.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 1e5dae08..c31b4794 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -13,8 +13,8 @@ sonar.organization=redhat-developer sonar.projectKey=redhat-developer_abbenay sonar.sources=packages/daemon/src/,packages/vscode/src/ sonar.tests=packages/daemon/src/,packages/daemon/tests/,packages/vscode/src/test/ -# Keep source/test sets disjoint: co-located *.test.ts live under source roots -# but must be classified only as tests (not main sources). -sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/python/**,**/*.test.ts -sonar.test.inclusions=**/*.test.ts +# Keep source/test sets disjoint: co-located *.test.ts (and test helpers like +# test-env.ts) live under source roots but must be classified only as tests. +sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/python/**,**/*.test.ts,**/test-env.ts +sonar.test.inclusions=**/*.test.ts,**/test-env.ts sonar.verbose=false From 00841c9d164a9cfcc996c7b40a82b01600c0e5c8 Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 05:37:15 -0700 Subject: [PATCH 12/18] test(daemon): cover withEnv restore path for previously set keys Co-authored-by: Cursor --- .../daemon/src/daemon/server/test-env.test.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 packages/daemon/src/daemon/server/test-env.test.ts diff --git a/packages/daemon/src/daemon/server/test-env.test.ts b/packages/daemon/src/daemon/server/test-env.test.ts new file mode 100644 index 00000000..0df14f9e --- /dev/null +++ b/packages/daemon/src/daemon/server/test-env.test.ts @@ -0,0 +1,30 @@ +/** + * Unit tests for the withEnv test helper. + */ + +import { describe, it, expect } from 'vitest'; +import { withEnv } from './test-env.js'; + +describe('withEnv', () => { + it('restores a previously set env value after the callback', async () => { + const key = 'ABBENAY_TEST_ENV_RESTORE'; + process.env[key] = 'original'; + try { + await withEnv(key, 'temporary', () => { + expect(process.env[key]).toBe('temporary'); + }); + expect(process.env[key]).toBe('original'); + } finally { + delete process.env[key]; + } + }); + + it('deletes the key when it was previously unset', async () => { + const key = 'ABBENAY_TEST_ENV_DELETE'; + delete process.env[key]; + await withEnv(key, 'temporary', () => { + expect(process.env[key]).toBe('temporary'); + }); + expect(process.env[key]).toBeUndefined(); + }); +}); From 06f6a3133580b41038641b4715fae68c009b4bcc Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 05:46:20 -0700 Subject: [PATCH 13/18] fix(proto): make secret request store fields optional Proto3 enums are not omitable without optional, so typed clients were forced to pass store despite documented keychain defaulting on Get/Set/DeleteSecret. Co-authored-by: Cursor --- packages/proto-ts/src/abbenay/v1/service.ts | 38 +-- .../abbenay_grpc/abbenay/v1/service_pb2.py | 258 +++++++++--------- .../abbenay_grpc/abbenay/v1/service_pb2.pyi | 64 ++--- .../abbenay/v1/service_pb2_grpc.py | 14 +- .../vscode/src/proto/abbenay/v1/service.ts | 38 +-- proto/abbenay/v1/service.proto | 6 +- 6 files changed, 209 insertions(+), 209 deletions(-) diff --git a/packages/proto-ts/src/abbenay/v1/service.ts b/packages/proto-ts/src/abbenay/v1/service.ts index 71af91da..a69bcb11 100644 --- a/packages/proto-ts/src/abbenay/v1/service.ts +++ b/packages/proto-ts/src/abbenay/v1/service.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v3.19.6 +// protoc v6.33.4 // source: abbenay/v1/service.proto /* eslint-disable */ @@ -1344,7 +1344,7 @@ export interface DeletePolicyRequest { export interface GetSecretRequest { key: string; /** Backend namespace (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface GetSecretResponse { @@ -1355,13 +1355,13 @@ export interface SetSecretRequest { key: string; value: string; /** Where to store (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface DeleteSecretRequest { key: string; /** Backend namespace (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface ListSecretsRequest { @@ -13600,7 +13600,7 @@ export const DeletePolicyRequest: MessageFns = { }; function createBaseGetSecretRequest(): GetSecretRequest { - return { key: "", store: 0 }; + return { key: "", store: undefined }; } export const GetSecretRequest: MessageFns = { @@ -13608,7 +13608,7 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(16).int32(message.store); } return writer; @@ -13649,7 +13649,7 @@ export const GetSecretRequest: MessageFns = { fromJSON(object: any): GetSecretRequest { return { key: isSet(object.key) ? globalThis.String(object.key) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13658,7 +13658,7 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13670,7 +13670,7 @@ export const GetSecretRequest: MessageFns = { fromPartial(object: DeepPartial): GetSecretRequest { const message = createBaseGetSecretRequest(); message.key = object.key ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; @@ -13734,7 +13734,7 @@ export const GetSecretResponse: MessageFns = { }; function createBaseSetSecretRequest(): SetSecretRequest { - return { key: "", value: "", store: 0 }; + return { key: "", value: "", store: undefined }; } export const SetSecretRequest: MessageFns = { @@ -13745,7 +13745,7 @@ export const SetSecretRequest: MessageFns = { if (message.value !== "") { writer.uint32(18).string(message.value); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(24).int32(message.store); } return writer; @@ -13795,7 +13795,7 @@ export const SetSecretRequest: MessageFns = { return { key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object.value) ? globalThis.String(object.value) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13807,7 +13807,7 @@ export const SetSecretRequest: MessageFns = { if (message.value !== "") { obj.value = message.value; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13820,13 +13820,13 @@ export const SetSecretRequest: MessageFns = { const message = createBaseSetSecretRequest(); message.key = object.key ?? ""; message.value = object.value ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; function createBaseDeleteSecretRequest(): DeleteSecretRequest { - return { key: "", store: 0 }; + return { key: "", store: undefined }; } export const DeleteSecretRequest: MessageFns = { @@ -13834,7 +13834,7 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(16).int32(message.store); } return writer; @@ -13875,7 +13875,7 @@ export const DeleteSecretRequest: MessageFns = { fromJSON(object: any): DeleteSecretRequest { return { key: isSet(object.key) ? globalThis.String(object.key) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13884,7 +13884,7 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13896,7 +13896,7 @@ export const DeleteSecretRequest: MessageFns = { fromPartial(object: DeepPartial): DeleteSecretRequest { const message = createBaseDeleteSecretRequest(); message.key = object.key ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py index 2509f2ae..0b4896fb 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.py @@ -2,7 +2,7 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # NO CHECKED-IN PROTOBUF GENCODE # source: abbenay/v1/service.proto -# Protobuf Python Version: 6.31.1 +# Protobuf Python Version: 7.35.1 """Generated protocol buffer code.""" from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool @@ -11,8 +11,8 @@ from google.protobuf.internal import builder as _builder _runtime_version.ValidateProtobufRuntimeVersion( _runtime_version.Domain.PUBLIC, - 6, - 31, + 7, + 35, 1, '', 'abbenay/v1/service.proto' @@ -24,7 +24,7 @@ -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xba\x03\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x32\n\x0csecret_store\x18\x07 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x04\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"G\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"V\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12&\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"J\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x61\x62\x62\x65nay/v1/service.proto\x12\nabbenay.v1\"\x07\n\x05\x45mpty\"+\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\x12\r\n\x05nanos\x18\x02 \x01(\x05\"C\n\x13ListMcpToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\":\n\x14ListMcpToolsResponse\x12\"\n\x05tools\x18\x01 \x03(\x0b\x32\x13.abbenay.v1.McpTool\"o\n\x07McpTool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x19\n\x11input_schema_json\x18\x03 \x01(\t\x12\x11\n\tserver_id\x18\x04 \x01(\t\x12\x13\n\x0b\x61nnotations\x18\x05 \x03(\t\"\xcf\x01\n\x0f\x43\x61llToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\x12\x17\n\nrequest_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x39\n\x07\x63ontext\x18\x04 \x03(\x0b\x32(.abbenay.v1.CallToolRequest.ContextEntry\x1a.\n\x0c\x43ontextEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_request_id\"\xc9\x02\n\x11ToolResponseChunk\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12,\n\x08progress\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.ToolProgressH\x00\x12/\n\ntext_delta\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.ToolTextDeltaH\x00\x12\x30\n\x07partial\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ToolPartialResultH\x00\x12\x33\n\x0c\x66inal_result\x18\x05 \x01(\x0b\x32\x1b.abbenay.v1.ToolFinalResultH\x00\x12&\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.ToolErrorH\x00\x12(\n\x06prompt\x18\x07 \x01(\x0b\x32\x16.abbenay.v1.ToolPromptH\x00\x42\x08\n\x06result\"]\n\x0cToolProgress\x12\x12\n\npercentage\x18\x01 \x01(\x02\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x18\n\x0b\x65ta_seconds\x18\x03 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_eta_seconds\"\x1d\n\rToolTextDelta\x12\x0c\n\x04text\x18\x01 \x01(\t\";\n\x11ToolPartialResult\x12\x14\n\x0c\x63ontent_json\x18\x01 \x01(\t\x12\x10\n\x08is_final\x18\x02 \x01(\x08\"M\n\x0fToolFinalResult\x12(\n\x07\x63ontent\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"W\n\x0bToolContent\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\x0c\x12\x0b\n\x03uri\x18\x05 \x01(\t\"V\n\tToolError\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x19\n\x0c\x64\x65tails_json\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_details_json\"o\n\nToolPrompt\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x0f\n\x07options\x18\x03 \x03(\t\x12\x1a\n\rdefault_value\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_default_value\"\xae\x01\n\x16ToolInteractiveRequest\x12+\n\x04\x63\x61ll\x18\x01 \x01(\x0b\x32\x1b.abbenay.v1.CallToolRequestH\x00\x12\x32\n\x08response\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.ToolPromptResponseH\x00\x12(\n\x06\x63\x61ncel\x18\x03 \x01(\x0b\x32\x16.abbenay.v1.ToolCancelH\x00\x42\t\n\x07request\"9\n\x12ToolPromptResponse\x12\x11\n\tprompt_id\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"0\n\nToolCancel\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x0e\n\x06reason\x18\x02 \x01(\t\"Z\n\x15\x43\x61llToolsBatchRequest\x12*\n\x05\x63\x61lls\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.CallToolRequest\x12\x15\n\rstop_on_error\x18\x02 \x01(\x08\"l\n\x14ListResourcesRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nuri_prefix\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_server_filterB\r\n\x0b_uri_prefix\"C\n\x15ListResourcesResponse\x12*\n\tresources\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.McpResource\"P\n\x0bMcpResource\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\"\"\n\x13ReadResourceRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\"A\n\x14ReadResourceResponse\x12)\n\x08\x63ontents\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.ToolContent\"B\n\x12ListPromptsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"=\n\x13ListPromptsResponse\x12&\n\x07prompts\x18\x01 \x03(\x0b\x32\x15.abbenay.v1.McpPrompt\"`\n\tMcpPrompt\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x30\n\targuments\x18\x03 \x03(\x0b\x32\x1d.abbenay.v1.McpPromptArgument\"H\n\x11McpPromptArgument\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x10\n\x08required\x18\x03 \x01(\x08\"\x92\x01\n\x10GetPromptRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12>\n\targuments\x18\x02 \x03(\x0b\x32+.abbenay.v1.GetPromptRequest.ArgumentsEntry\x1a\x30\n\x0e\x41rgumentsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"U\n\x11GetPromptResponse\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12+\n\x08messages\x18\x02 \x03(\x0b\x32\x19.abbenay.v1.PromptMessage\".\n\rPromptMessage\x12\x0c\n\x04role\x18\x01 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\"\xc8\x01\n\x0b\x43hatRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12\x1f\n\x05tools\x18\x04 \x03(\x0b\x32\x10.abbenay.v1.Tool\x12-\n\x06policy\x18\x05 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb2\x01\n\x12SessionChatRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12$\n\x07message\x18\x02 \x01(\x0b\x32\x13.abbenay.v1.Message\x12(\n\x07options\x18\x03 \x01(\x0b\x32\x17.abbenay.v1.ChatOptions\x12-\n\x06policy\x18\x04 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfigH\x00\x88\x01\x01\x42\t\n\x07_policy\"\xb9\x02\n\x0b\x43hatOptions\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05top_p\x18\x03 \x01(\x02H\x02\x88\x01\x01\x12\x0c\n\x04stop\x18\x04 \x03(\t\x12\x14\n\x0c\x65nable_tools\x18\x05 \x01(\x08\x12\x1b\n\x13max_tool_iterations\x18\x06 \x01(\x05\x12\x13\n\x0btool_filter\x18\x07 \x03(\t\x12\x12\n\x05top_k\x18\x08 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x04\x88\x01\x01\x12\x16\n\ttool_mode\x18\n \x01(\tH\x05\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokensB\x08\n\x06_top_pB\x08\n\x06_top_kB\n\n\x08_timeoutB\x0c\n\n_tool_mode\"\xc3\x02\n\tChatChunk\x12%\n\x04text\x18\x01 \x01(\x0b\x32\x15.abbenay.v1.TextChunkH\x00\x12.\n\ttool_call\x18\x02 \x01(\x0b\x32\x19.abbenay.v1.ToolCallChunkH\x00\x12\x32\n\x0btool_result\x18\x03 \x01(\x0b\x32\x1b.abbenay.v1.ToolResultChunkH\x00\x12)\n\x06prompt\x18\x04 \x01(\x0b\x32\x17.abbenay.v1.PromptChunkH\x00\x12\'\n\x05usage\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.UsageChunkH\x00\x12\'\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x16.abbenay.v1.ErrorChunkH\x00\x12%\n\x04\x64one\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.DoneChunkH\x00\x42\x07\n\x05\x63hunk\"\x19\n\tTextChunk\x12\x0c\n\x04text\x18\x01 \x01(\t\"<\n\rToolCallChunk\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"X\n\x0fToolResultChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\t\x12\x10\n\x08is_error\x18\x04 \x01(\x08\"\\\n\x0bPromptChunk\x12\x14\n\x0ctool_call_id\x18\x01 \x01(\t\x12\x11\n\ttool_name\x18\x02 \x01(\t\x12\x13\n\x0bprompt_text\x18\x03 \x01(\t\x12\x0f\n\x07options\x18\x04 \x03(\t\"T\n\nUsageChunk\x12\x15\n\rprompt_tokens\x18\x01 \x01(\x05\x12\x19\n\x11\x63ompletion_tokens\x18\x02 \x01(\x05\x12\x14\n\x0ctotal_tokens\x18\x03 \x01(\x05\"+\n\nErrorChunk\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\"\"\n\tDoneChunk\x12\x15\n\rfinish_reason\x18\x01 \x01(\t\"\x88\x01\n\x07Message\x12\x1e\n\x04role\x18\x01 \x01(\x0e\x32\x10.abbenay.v1.Role\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12(\n\ntool_calls\x18\x03 \x03(\x0b\x32\x14.abbenay.v1.ToolCall\x12\x14\n\x0ctool_call_id\x18\x04 \x01(\t\x12\x0c\n\x04name\x18\x05 \x01(\t\"7\n\x08ToolCall\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\targuments\x18\x03 \x01(\t\"\xc4\x03\n\x07Session\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12%\n\x08messages\x18\x04 \x03(\x0b\x32\x13.abbenay.v1.Message\x12*\n\ncreated_by\x18\x05 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x33\n\x08metadata\x18\x08 \x03(\x0b\x32!.abbenay.v1.Session.MetadataEntry\x12\x18\n\x0b\x66orked_from\x18\t \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\n \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0e\x63\x61\x63hed_summary\x18\x0b \x01(\tH\x02\x88\x01\x01\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0e\n\x0c_forked_fromB\r\n\x0b_fork_pointB\x11\n\x0f_cached_summary\"Z\n\nClientInfo\x12+\n\x0b\x63lient_type\x18\x01 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12\x0c\n\x04user\x18\x03 \x01(\t\"\xb6\x01\n\x14\x43reateSessionRequest\x12\r\n\x05model\x18\x01 \x01(\t\x12\x12\n\x05topic\x18\x02 \x01(\tH\x00\x88\x01\x01\x12@\n\x08metadata\x18\x03 \x03(\x0b\x32..abbenay.v1.CreateSessionRequest.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_topic\"A\n\x11GetSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x18\n\x10include_messages\x18\x02 \x01(\x08\"\x8e\x01\n\x13ListSessionsRequest\x12\r\n\x05limit\x18\x01 \x01(\x05\x12\x0e\n\x06offset\x18\x02 \x01(\x05\x12\x1a\n\rsource_filter\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cmodel_filter\x18\x04 \x01(\tH\x01\x88\x01\x01\x42\x10\n\x0e_source_filterB\x0f\n\r_model_filter\"Y\n\x14ListSessionsResponse\x12,\n\x08sessions\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x13\n\x0btotal_count\x18\x02 \x01(\x05\"\xcf\x01\n\x0eSessionSummary\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05model\x18\x02 \x01(\t\x12\r\n\x05topic\x18\x03 \x01(\t\x12\x15\n\rmessage_count\x18\x04 \x01(\x05\x12&\n\x06source\x18\x05 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12)\n\ncreated_at\x18\x06 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12)\n\nupdated_at\x18\x07 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\"*\n\x14\x44\x65leteSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"\x16\n\x14WatchSessionsRequest\"\xb8\x01\n\x0cSessionEvent\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12-\n\x07\x63reated\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.SessionCreatedH\x00\x12-\n\x07updated\x18\x03 \x01(\x0b\x32\x1a.abbenay.v1.SessionUpdatedH\x00\x12-\n\x07\x64\x65leted\x18\x04 \x01(\x0b\x32\x1a.abbenay.v1.SessionDeletedH\x00\x42\x07\n\x05\x65vent\"=\n\x0eSessionCreated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\"X\n\x0eSessionUpdated\x12+\n\x07session\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.SessionSummary\x12\x19\n\x11new_message_count\x18\x02 \x01(\x05\"\x10\n\x0eSessionDeleted\"\x80\x01\n\x14ReplaySessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12(\n\x06\x66ormat\x18\x02 \x01(\x0e\x32\x18.abbenay.v1.ReplayFormat\x12\x19\n\x0cmax_messages\x18\x03 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_max_messages\"a\n\x15ReplaySessionResponse\x12\x19\n\x11\x66ormatted_content\x18\x01 \x01(\t\x12\x15\n\rmessage_count\x18\x02 \x01(\x05\x12\x16\n\x0etoken_estimate\x18\x03 \x01(\x05\"_\n\x17SummarizeSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x0fsummarize_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x12\n\x10_summarize_model\"?\n\x18SummarizeSessionResponse\x12\x0f\n\x07summary\x18\x01 \x01(\t\x12\x12\n\nfrom_cache\x18\x02 \x01(\x08\"v\n\x12\x46orkSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x16\n\tnew_model\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfork_point\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\x0c\n\n_new_modelB\r\n\x0b_fork_point\"b\n\x14\x45xportSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x1c\n\x14include_tool_results\x18\x02 \x01(\x08\x12\x18\n\x10include_metadata\x18\x03 \x01(\x08\"-\n\x15\x45xportSessionResponse\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\"E\n\x14ImportSessionRequest\x12\x14\n\x0cjson_content\x18\x01 \x01(\t\x12\x17\n\x0fgenerate_new_id\x18\x02 \x01(\x08\"^\n\x11ListModelsRequest\x12\x1c\n\x0fprovider_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\x0fworkspace_paths\x18\x02 \x03(\tB\x12\n\x10_provider_filter\"7\n\x12ListModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x9a\x01\n\x15\x44iscoverModelsRequest\x12\x11\n\tengine_id\x18\x01 \x01(\t\x12\x14\n\x07\x61pi_key\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bprovider_id\x18\x04 \x01(\tH\x02\x88\x01\x01\x42\n\n\x08_api_keyB\x0b\n\t_base_urlB\x0e\n\x0c_provider_id\";\n\x16\x44iscoverModelsResponse\x12!\n\x06models\x18\x01 \x03(\x0b\x32\x11.abbenay.v1.Model\"\x93\x02\n\x05Model\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08provider\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x33\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1d.abbenay.v1.ModelCapabilities\x12\'\n\x06source\x18\x05 \x01(\x0e\x32\x17.abbenay.v1.ModelSource\x12\x0e\n\x06\x65ngine\x18\x06 \x01(\t\x12,\n\x06params\x18\x07 \x01(\x0b\x32\x17.abbenay.v1.ModelParamsH\x00\x88\x01\x01\x12\x17\n\x0f\x65ngine_model_id\x18\x08 \x01(\t\x12\x13\n\x06policy\x18\t \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_paramsB\t\n\x07_policy\"\xa3\x02\n\x0bModelParams\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x12\n\x05top_k\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x14\n\x07timeout\x18\x07 \x01(\x05H\x06\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\r\n\x0b_max_tokensB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x08\n\x06_top_kB\n\n\x08_timeout\"\x90\x01\n\x11ModelCapabilities\x12\x1a\n\x12supports_streaming\x18\x01 \x01(\x08\x12\x16\n\x0esupports_tools\x18\x02 \x01(\x08\x12\x17\n\x0fsupports_vision\x18\x03 \x01(\x08\x12\x1b\n\x0e\x63ontext_window\x18\x04 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_context_window\"/\n\x14ListProvidersRequest\x12\x17\n\x0fworkspace_paths\x18\x01 \x03(\t\"@\n\x15ListProvidersResponse\x12\'\n\tproviders\x18\x01 \x03(\x0b\x32\x14.abbenay.v1.Provider\"\xea\x01\n\x08Provider\x12\n\n\x02id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12/\n\rprovider_type\x18\x04 \x01(\x0e\x32\x18.abbenay.v1.ProviderType\x12\x14\n\x0crequires_key\x18\x05 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x06 \x01(\tH\x00\x88\x01\x01\x12\x0e\n\x06\x65ngine\x18\x07 \x01(\t\x12\x15\n\x08\x62\x61se_url\x18\x08 \x01(\tH\x01\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x0b\n\t_base_url\"/\n\x18GetProviderStatusRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\"\x93\x01\n\x0eProviderStatus\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x12\n\nconfigured\x18\x02 \x01(\x08\x12\x0f\n\x07healthy\x18\x03 \x01(\x08\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x12)\n\nlast_check\x18\x05 \x01(\x0b\x32\x15.abbenay.v1.TimestampB\x08\n\x06_error\"\x14\n\x12ListEnginesRequest\":\n\x13ListEnginesResponse\x12#\n\x07\x65ngines\x18\x01 \x03(\x0b\x32\x12.abbenay.v1.Engine\"\xbc\x01\n\x06\x45ngine\x12\n\n\x02id\x18\x01 \x01(\t\x12\x14\n\x0crequires_key\x18\x02 \x01(\x08\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x1c\n\x0f\x64\x65\x66\x61ult_env_var\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x64isplay_name\x18\x05 \x01(\tH\x02\x88\x01\x01\x42\x13\n\x11_default_base_urlB\x12\n\x10_default_env_varB\x0f\n\r_display_name\"@\n\x10ListToolsRequest\x12\x1a\n\rserver_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_server_filter\"4\n\x11ListToolsResponse\x12\x1f\n\x05tools\x18\x01 \x03(\x0b\x32\x10.abbenay.v1.Tool\"O\n\x04Tool\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0e\n\x06server\x18\x04 \x01(\t\"5\n\x12\x45xecuteToolRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\targuments\x18\x02 \x01(\t\"8\n\x13\x45xecuteToolResponse\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"6\n\x10GetConfigRequest\x12\x15\n\x08location\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"E\n\x11GetConfigResponse\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x0c\n\x04path\x18\x02 \x01(\t\"\xd9\x03\n\x06\x43onfig\x12\x34\n\tproviders\x18\x01 \x03(\x0b\x32!.abbenay.v1.Config.ProvidersEntry\x12\x37\n\x0bmcp_servers\x18\x02 \x03(\x0b\x32\".abbenay.v1.Config.McpServersEntry\x12\x34\n\x0btool_policy\x18\x03 \x01(\x0b\x32\x1f.abbenay.v1.ToolPolicyConfigMsg\x12\x34\n\tconsumers\x18\x04 \x03(\x0b\x32!.abbenay.v1.Config.ConsumersEntry\x1aP\n\x0eProvidersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.FullProviderConfig:\x02\x38\x01\x1aQ\n\x0fMcpServersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12-\n\x05value\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.McpServerConfigMsg:\x02\x38\x01\x1aO\n\x0e\x43onsumersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12,\n\x05value\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.ConsumerConfigMsg:\x02\x38\x01\"\xba\x03\n\x12\x46ullProviderConfig\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\"\n\x15\x61pi_key_keychain_name\x18\x02 \x01(\tH\x00\x88\x01\x01\x12!\n\x14\x61pi_key_env_var_name\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x04 \x01(\tH\x02\x88\x01\x01\x12:\n\x06models\x18\x05 \x03(\x0b\x32*.abbenay.v1.FullProviderConfig.ModelsEntry\x12\x18\n\x0bsecret_name\x18\x06 \x01(\tH\x03\x88\x01\x01\x12\x32\n\x0csecret_store\x18\x07 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x04\x88\x01\x01\x1aK\n\x0bModelsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05value\x18\x02 \x01(\x0b\x32\x1c.abbenay.v1.ModelParamConfig:\x02\x38\x01\x42\x18\n\x16_api_key_keychain_nameB\x17\n\x15_api_key_env_var_nameB\x0b\n\t_base_urlB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\"\xec\x02\n\x10ModelParamConfig\x12\x15\n\x08model_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x06policy\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1a\n\rsystem_prompt\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0btemperature\x18\x05 \x01(\x02H\x04\x88\x01\x01\x12\x12\n\x05top_p\x18\x06 \x01(\x02H\x05\x88\x01\x01\x12\x12\n\x05top_k\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x14\n\x07timeout\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x0b\n\t_model_idB\t\n\x07_policyB\x10\n\x0e_system_promptB\x15\n\x13_system_prompt_modeB\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_kB\r\n\x0b_max_tokensB\n\n\x08_timeout\"\x88\x03\n\x12McpServerConfigMsg\x12\x14\n\x07\x63ommand\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x02 \x03(\t\x12\x10\n\x03url\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x11\n\ttransport\x18\x04 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x05 \x01(\x08\x12<\n\x07headers\x18\x06 \x03(\x0b\x32+.abbenay.v1.McpServerConfigMsg.HeadersEntry\x12\x34\n\x03\x65nv\x18\x07 \x03(\x0b\x32\'.abbenay.v1.McpServerConfigMsg.EnvEntry\x12\x1e\n\x11max_response_size\x18\x08 \x01(\x05H\x02\x88\x01\x01\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_urlB\x14\n\x12_max_response_size\"\x86\x02\n\x13ToolPolicyConfigMsg\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x0c\x61uto_approve\x18\x02 \x03(\t\x12\x18\n\x10require_approval\x18\x03 \x03(\t\x12\x16\n\x0e\x64isabled_tools\x18\x04 \x03(\t\x12=\n\x07\x61liases\x18\x05 \x03(\x0b\x32,.abbenay.v1.ToolPolicyConfigMsg.AliasesEntry\x1a.\n\x0c\x41liasesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x16\n\x14_max_tool_iterations\"\xa4\x01\n\x11\x43onsumerConfigMsg\x12\x16\n\ttoken_env\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0etoken_keychain\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x39\n\x0c\x63\x61pabilities\x18\x03 \x01(\x0b\x32#.abbenay.v1.ConsumerCapabilitiesMsgB\x0c\n\n_token_envB\x11\n\x0f_token_keychain\"\x9b\x02\n\x17\x43onsumerCapabilitiesMsg\x12\x1a\n\rinline_policy\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x19\n\x0cmcp_register\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x14\n\x07secrets\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x13\n\x06\x63onfig\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x16\n\tproviders\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x15\n\x08shutdown\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x11\n\x04\x63hat\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x10\n\x0e_inline_policyB\x0f\n\r_mcp_registerB\n\n\x08_secretsB\t\n\x07_configB\x0c\n\n_providersB\x0b\n\t_shutdownB\x07\n\x05_chat\"]\n\x13UpdateConfigRequest\x12\"\n\x06\x63onfig\x18\x01 \x01(\x0b\x32\x12.abbenay.v1.Config\x12\x15\n\x08location\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0b\n\t_location\"\x80\x03\n\x18\x43onfigureProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06\x65ngine\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07\x61pi_key\x18\x03 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0c\x65nv_var_name\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x62\x61se_url\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06target\x18\x06 \x01(\tH\x04\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x07 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0bsecret_name\x18\x08 \x01(\tH\x06\x88\x01\x01\x12\x32\n\x0csecret_store\x18\t \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x07\x88\x01\x01\x42\t\n\x07_engineB\n\n\x08_api_keyB\x0f\n\r_env_var_nameB\x0b\n\t_base_urlB\t\n\x07_targetB\x11\n\x0f_workspace_pathB\x0e\n\x0c_secret_nameB\x0f\n\r_secret_store\",\n\x19\x43onfigureProviderResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"|\n\x15RemoveProviderRequest\x12\x13\n\x0bprovider_id\x18\x01 \x01(\t\x12\x13\n\x06target\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x1b\n\x0eworkspace_path\x18\x03 \x01(\tH\x01\x88\x01\x01\x42\t\n\x07_targetB\x11\n\x0f_workspace_path\"\x1d\n\x1bGetProviderTemplatesRequest\"O\n\x1cGetProviderTemplatesResponse\x12/\n\ttemplates\x18\x01 \x03(\x0b\x32\x1c.abbenay.v1.ProviderTemplate\"\x84\x01\n\x10ProviderTemplate\x12\x0e\n\x06\x65ngine\x18\x01 \x01(\t\x12\x16\n\x0esuggested_name\x18\x02 \x01(\t\x12\x1d\n\x10\x64\x65\x66\x61ult_base_url\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x0crequires_key\x18\x04 \x01(\x08\x42\x13\n\x11_default_base_url\"3\n\x13GetKeyStatusRequest\x12\x0e\n\x06source\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\"&\n\x14GetKeyStatusResponse\x12\x0e\n\x06\x65xists\x18\x01 \x01(\x08\"\x1d\n\x1bListMcpServerConfigsRequest\"U\n\x1cListMcpServerConfigsResponse\x12\x35\n\x0bmcp_servers\x18\x01 \x03(\x0b\x32 .abbenay.v1.McpServerStatusEntry\"\x88\x01\n\x14McpServerStatusEntry\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\ttransport\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x12\n\ntool_count\x18\x05 \x01(\x05\x12\x12\n\x05\x65rror\x18\x06 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\".\n\x19ReconnectMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\"M\n\x13\x43reatePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12(\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"#\n\x13\x44\x65letePolicyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"V\n\x10GetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x00\x88\x01\x01\x42\x08\n\x06_store\"\"\n\x11GetSecretResponse\x12\r\n\x05value\x18\x01 \x01(\t\"e\n\x10SetSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\x12+\n\x05store\x18\x03 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x00\x88\x01\x01\x42\x08\n\x06_store\"Y\n\x13\x44\x65leteSecretRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12+\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStoreH\x00\x88\x01\x01\x42\x08\n\x06_store\"\x14\n\x12ListSecretsRequest\">\n\x13ListSecretsResponse\x12\'\n\x07secrets\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.SecretInfo\"T\n\nSecretInfo\x12\x0b\n\x03key\x18\x01 \x01(\t\x12&\n\x05store\x18\x02 \x01(\x0e\x32\x17.abbenay.v1.SecretStore\x12\x11\n\thas_value\x18\x03 \x01(\x08\"~\n\x0fRegisterRequest\x12&\n\x06\x63lient\x18\x01 \x01(\x0b\x32\x16.abbenay.v1.ClientInfo\x12\x12\n\nis_spawner\x18\x02 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x03 \x01(\t\x12\x17\n\x0fworkspace_paths\x18\x04 \x03(\t\"@\n\x10RegisterResponse\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x19\n\x11\x63onnected_clients\x18\x02 \x01(\x05\"&\n\x11UnregisterRequest\x12\x11\n\tclient_id\x18\x01 \x01(\t\"\x12\n\x10GetStatusRequest\"\x1f\n\x1dGetConnectedWorkspacesRequest\"4\n\x1eGetConnectedWorkspacesResponse\x12\x12\n\nworkspaces\x18\x01 \x03(\t\"\xcc\x01\n\x0c\x44\x61\x65monStatus\x12\x0f\n\x07version\x18\x01 \x01(\t\x12)\n\nstarted_at\x18\x02 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x19\n\x11\x63onnected_clients\x18\x03 \x01(\x05\x12\x17\n\x0f\x61\x63tive_sessions\x18\x04 \x01(\x05\x12,\n\x07\x63lients\x18\x05 \x03(\x0b\x32\x1b.abbenay.v1.ConnectedClient\x12\x1e\n\x16registered_mcp_servers\x18\x06 \x03(\t\"\xaa\x01\n\x0f\x43onnectedClient\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12+\n\x0b\x63lient_type\x18\x02 \x01(\x0e\x32\x16.abbenay.v1.ClientType\x12+\n\x0c\x63onnected_at\x18\x03 \x01(\x0b\x32\x15.abbenay.v1.Timestamp\x12\x12\n\nis_spawner\x18\x04 \x01(\x08\x12\x16\n\x0eworkspace_path\x18\x05 \x01(\t\">\n\x0fShutdownRequest\x12\r\n\x05\x66orce\x18\x01 \x01(\x08\x12\x1c\n\x14grace_period_seconds\x18\x02 \x01(\x05\"\x14\n\x12HealthCheckRequest\"7\n\x13HealthCheckResponse\x12\x0f\n\x07healthy\x18\x01 \x01(\x08\x12\x0f\n\x07version\x18\x02 \x01(\t\"%\n\x15StartWebServerRequest\x12\x0c\n\x04port\x18\x01 \x01(\x05\"]\n\x16StartWebServerResponse\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x17\n\x0f\x61lready_running\x18\x02 \x01(\x08\x12\x0c\n\x04port\x18\x03 \x01(\x05\x12\x0b\n\x03url\x18\x04 \x01(\t\"\x16\n\x14StopWebServerRequest\"\x8d\x03\n\rVSCodeRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x34\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1d.abbenay.v1.InvokeToolRequestH\x00\x12:\n\x0blist_models\x18\x03 \x01(\x0b\x32#.abbenay.v1.ListVSCodeModelsRequestH\x00\x12\x36\n\tsend_chat\x18\x04 \x01(\x0b\x32!.abbenay.v1.SendVSCodeChatRequestH\x00\x12\x38\n\rget_workspace\x18\x06 \x01(\x0b\x32\x1f.abbenay.v1.GetWorkspaceRequestH\x00\x12?\n\x0emodels_changed\x18\x07 \x01(\x0b\x32%.abbenay.v1.ModelsChangedNotificationH\x00\x12\x38\n\nlist_tools\x18\x08 \x01(\x0b\x32\".abbenay.v1.ListVSCodeToolsRequestH\x00\x42\t\n\x07request\"+\n\x19ModelsChangedNotification\x12\x0e\n\x06reason\x18\x01 \x01(\t\"\xbe\x03\n\x0eVSCodeResponse\x12\x12\n\nrequest_id\x18\x01 \x01(\t\x12\x35\n\x0binvoke_tool\x18\x02 \x01(\x0b\x32\x1e.abbenay.v1.InvokeToolResponseH\x00\x12;\n\x0blist_models\x18\x03 \x01(\x0b\x32$.abbenay.v1.ListVSCodeModelsResponseH\x00\x12\x37\n\tsend_chat\x18\x04 \x01(\x0b\x32\".abbenay.v1.SendVSCodeChatResponseH\x00\x12(\n\x05\x65rror\x18\x06 \x01(\x0b\x32\x17.abbenay.v1.VSCodeErrorH\x00\x12\x39\n\rget_workspace\x18\x07 \x01(\x0b\x32 .abbenay.v1.GetWorkspaceResponseH\x00\x12\x39\n\nlist_tools\x18\x08 \x01(\x0b\x32#.abbenay.v1.ListVSCodeToolsResponseH\x00\x12?\n\x0eregister_tools\x18\t \x01(\x0b\x32%.abbenay.v1.RegisterToolsNotificationH\x00\x42\n\n\x08response\"\x15\n\x13GetWorkspaceRequest\"I\n\x14GetWorkspaceResponse\x12\x16\n\x0eworkspace_path\x18\x01 \x01(\t\x12\x19\n\x11workspace_folders\x18\x02 \x03(\t\",\n\x0bVSCodeError\x12\x0f\n\x07message\x18\x01 \x01(\t\x12\x0c\n\x04\x63ode\x18\x02 \x01(\t\">\n\x11InvokeToolRequest\x12\x11\n\ttool_name\x18\x01 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x02 \x01(\t\";\n\x12InvokeToolResponse\x12\x13\n\x0bresult_json\x18\x01 \x01(\t\x12\x10\n\x08is_error\x18\x02 \x01(\x08\"\x18\n\x16ListVSCodeToolsRequest\"D\n\x17ListVSCodeToolsResponse\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"F\n\x19RegisterToolsNotification\x12)\n\x05tools\x18\x01 \x03(\x0b\x32\x1a.abbenay.v1.VSCodeToolInfo\"W\n\x0eVSCodeToolInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x14\n\x0cinput_schema\x18\x03 \x01(\t\x12\x0c\n\x04tags\x18\x04 \x03(\t\"G\n\x17ListVSCodeModelsRequest\x12\x1a\n\rfamily_filter\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x10\n\x0e_family_filter\"C\n\x18ListVSCodeModelsResponse\x12\'\n\x06models\x18\x01 \x03(\x0b\x32\x17.abbenay.v1.VSCodeModel\"a\n\x0bVSCodeModel\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06vendor\x18\x03 \x01(\t\x12\x0e\n\x06\x66\x61mily\x18\x04 \x01(\t\x12\x18\n\x10max_input_tokens\x18\x05 \x01(\x05\"\xa2\x01\n\x15SendVSCodeChatRequest\x12\x10\n\x08model_id\x18\x01 \x01(\t\x12%\n\x08messages\x18\x02 \x03(\x0b\x32\x13.abbenay.v1.Message\x12\x18\n\x0btemperature\x18\x03 \x01(\x02H\x00\x88\x01\x01\x12\x17\n\nmax_tokens\x18\x04 \x01(\x05H\x01\x88\x01\x01\x42\x0e\n\x0c_temperatureB\r\n\x0b_max_tokens\"E\n\x16SendVSCodeChatResponse\x12+\n\x06\x63hunks\x18\x01 \x03(\x0b\x32\x1b.abbenay.v1.VSCodeChatChunk\"[\n\x0fVSCodeChatChunk\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12/\n\ttool_call\x18\x02 \x01(\x0b\x32\x1a.abbenay.v1.VSCodeToolCallH\x00\x42\x07\n\x05\x63hunk\"G\n\x0eVSCodeToolCall\x12\x0f\n\x07\x63\x61ll_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x16\n\x0e\x61rguments_json\x18\x03 \x01(\t\"\x15\n\x13ListPoliciesRequest\"@\n\x14ListPoliciesResponse\x12(\n\x08policies\x18\x01 \x03(\x0b\x32\x16.abbenay.v1.PolicyInfo\"U\n\nPolicyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07\x62uiltin\x18\x02 \x01(\x08\x12(\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x18.abbenay.v1.PolicyConfig\"\xc2\x02\n\x0cPolicyConfig\x12\x31\n\x08sampling\x18\x01 \x01(\x0b\x32\x1a.abbenay.v1.PolicySamplingH\x00\x88\x01\x01\x12-\n\x06output\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.PolicyOutputH\x01\x88\x01\x01\x12/\n\x07\x63ontext\x18\x03 \x01(\x0b\x32\x19.abbenay.v1.PolicyContextH\x02\x88\x01\x01\x12)\n\x04tool\x18\x04 \x01(\x0b\x32\x16.abbenay.v1.PolicyToolH\x03\x88\x01\x01\x12\x37\n\x0breliability\x18\x05 \x01(\x0b\x32\x1d.abbenay.v1.PolicyReliabilityH\x04\x88\x01\x01\x42\x0b\n\t_samplingB\t\n\x07_outputB\n\n\x08_contextB\x07\n\x05_toolB\x0e\n\x0c_reliability\"v\n\x0ePolicySampling\x12\x18\n\x0btemperature\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12\x12\n\x05top_p\x18\x02 \x01(\x02H\x01\x88\x01\x01\x12\x12\n\x05top_k\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x0e\n\x0c_temperatureB\x08\n\x06_top_pB\x08\n\x06_top_k\"\x8c\x02\n\x0cPolicyOutput\x12\x17\n\nmax_tokens\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12#\n\x16reserved_output_tokens\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ormat\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\"\n\x15system_prompt_snippet\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1f\n\x12system_prompt_mode\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\r\n\x0b_max_tokensB\x19\n\x17_reserved_output_tokensB\t\n\x07_formatB\x18\n\x16_system_prompt_snippetB\x15\n\x13_system_prompt_mode\"\x81\x01\n\rPolicyContext\x12\x1e\n\x11\x63ontext_threshold\x18\x01 \x01(\x02H\x00\x88\x01\x01\x12!\n\x14\x63ompression_strategy\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x14\n\x12_context_thresholdB\x17\n\x15_compression_strategy\"l\n\nPolicyTool\x12 \n\x13max_tool_iterations\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttool_mode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x16\n\x14_max_tool_iterationsB\x0c\n\n_tool_mode\"s\n\x11PolicyReliability\x12\"\n\x15retry_on_invalid_json\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x14\n\x07timeout\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x18\n\x16_retry_on_invalid_jsonB\n\n\x08_timeout\"\xcd\x01\n\x18RegisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\x12+\n\ttransport\x18\x02 \x01(\x0b\x32\x18.abbenay.v1.McpTransport\x12\x17\n\nsession_id\x18\x03 \x01(\tH\x00\x88\x01\x01\x12\x13\n\x0btool_filter\x18\x04 \x03(\t\x12\x1e\n\x11max_response_size\x18\x05 \x01(\x05H\x01\x88\x01\x01\x42\r\n\x0b_session_idB\x14\n\x12_max_response_size\"\xaa\x02\n\x0cMcpTransport\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x14\n\x07\x63ommand\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x0c\n\x04\x61rgs\x18\x03 \x03(\t\x12\x10\n\x03url\x18\x04 \x01(\tH\x01\x88\x01\x01\x12\x36\n\x07headers\x18\x05 \x03(\x0b\x32%.abbenay.v1.McpTransport.HeadersEntry\x12.\n\x03\x65nv\x18\x06 \x03(\x0b\x32!.abbenay.v1.McpTransport.EnvEntry\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a*\n\x08\x45nvEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\n\n\x08_commandB\x06\n\x04_url\"U\n\x19RegisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x18\n\x10\x64iscovered_tools\x18\x03 \x03(\t\"/\n\x1aUnregisterMcpServerRequest\x12\x11\n\tserver_id\x18\x01 \x01(\t\".\n\x1bUnregisterMcpServerResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*_\n\x04Role\x12\x14\n\x10ROLE_UNSPECIFIED\x10\x00\x12\x0f\n\x0bROLE_SYSTEM\x10\x01\x12\r\n\tROLE_USER\x10\x02\x12\x12\n\x0eROLE_ASSISTANT\x10\x03\x12\r\n\tROLE_TOOL\x10\x04*\x9b\x01\n\nClientType\x12\x1b\n\x17\x43LIENT_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12\x43LIENT_TYPE_VSCODE\x10\x01\x12\x13\n\x0f\x43LIENT_TYPE_CLI\x10\x02\x12\x16\n\x12\x43LIENT_TYPE_PYTHON\x10\x03\x12\x16\n\x12\x43LIENT_TYPE_NODEJS\x10\x04\x12\x13\n\x0f\x43LIENT_TYPE_MCP\x10\x05*\x82\x01\n\x0cReplayFormat\x12\x1d\n\x19REPLAY_FORMAT_UNSPECIFIED\x10\x00\x12\x16\n\x12REPLAY_FORMAT_FULL\x10\x01\x12\x1b\n\x17REPLAY_FORMAT_CONDENSED\x10\x02\x12\x1e\n\x1aREPLAY_FORMAT_SUMMARY_ONLY\x10\x03*`\n\x0bModelSource\x12\x1c\n\x18MODEL_SOURCE_UNSPECIFIED\x10\x00\x12\x17\n\x13MODEL_SOURCE_DIRECT\x10\x01\x12\x1a\n\x16MODEL_SOURCE_VSCODE_LM\x10\x02*u\n\x0cProviderType\x12\x1d\n\x19PROVIDER_TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12PROVIDER_TYPE_HTTP\x10\x01\x12\x15\n\x11PROVIDER_TYPE_MCP\x10\x02\x12\x17\n\x13PROVIDER_TYPE_LOCAL\x10\x03*\x8c\x01\n\x08LogLevel\x12\x19\n\x15LOG_LEVEL_UNSPECIFIED\x10\x00\x12\x13\n\x0fLOG_LEVEL_ERROR\x10\x01\x12\x12\n\x0eLOG_LEVEL_WARN\x10\x02\x12\x12\n\x0eLOG_LEVEL_INFO\x10\x03\x12\x13\n\x0fLOG_LEVEL_DEBUG\x10\x04\x12\x13\n\x0fLOG_LEVEL_TRACE\x10\x05*u\n\x0bSecretStore\x12\x1c\n\x18SECRET_STORE_UNSPECIFIED\x10\x00\x12\x19\n\x15SECRET_STORE_KEYCHAIN\x10\x01\x12\x14\n\x10SECRET_STORE_ENV\x10\x02\x12\x17\n\x13SECRET_STORE_MEMORY\x10\x03\x32\x9f\x05\n\tMcpBridge\x12Q\n\x0cListMcpTools\x12\x1f.abbenay.v1.ListMcpToolsRequest\x1a .abbenay.v1.ListMcpToolsResponse\x12H\n\x08\x43\x61llTool\x12\x1b.abbenay.v1.CallToolRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12\\\n\x13\x43\x61llToolInteractive\x12\".abbenay.v1.ToolInteractiveRequest\x1a\x1d.abbenay.v1.ToolResponseChunk(\x01\x30\x01\x12T\n\x0e\x43\x61llToolsBatch\x12!.abbenay.v1.CallToolsBatchRequest\x1a\x1d.abbenay.v1.ToolResponseChunk0\x01\x12T\n\rListResources\x12 .abbenay.v1.ListResourcesRequest\x1a!.abbenay.v1.ListResourcesResponse\x12Q\n\x0cReadResource\x12\x1f.abbenay.v1.ReadResourceRequest\x1a .abbenay.v1.ReadResourceResponse\x12N\n\x0bListPrompts\x12\x1e.abbenay.v1.ListPromptsRequest\x1a\x1f.abbenay.v1.ListPromptsResponse\x12H\n\tGetPrompt\x12\x1c.abbenay.v1.GetPromptRequest\x1a\x1d.abbenay.v1.GetPromptResponse2\x82\x1c\n\x07\x41\x62\x62\x65nay\x12\x38\n\x04\x43hat\x12\x17.abbenay.v1.ChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\x0bSessionChat\x12\x1e.abbenay.v1.SessionChatRequest\x1a\x15.abbenay.v1.ChatChunk0\x01\x12\x46\n\rCreateSession\x12 .abbenay.v1.CreateSessionRequest\x1a\x13.abbenay.v1.Session\x12@\n\nGetSession\x12\x1d.abbenay.v1.GetSessionRequest\x1a\x13.abbenay.v1.Session\x12Q\n\x0cListSessions\x12\x1f.abbenay.v1.ListSessionsRequest\x1a .abbenay.v1.ListSessionsResponse\x12\x44\n\rDeleteSession\x12 .abbenay.v1.DeleteSessionRequest\x1a\x11.abbenay.v1.Empty\x12M\n\rWatchSessions\x12 .abbenay.v1.WatchSessionsRequest\x1a\x18.abbenay.v1.SessionEvent0\x01\x12T\n\rReplaySession\x12 .abbenay.v1.ReplaySessionRequest\x1a!.abbenay.v1.ReplaySessionResponse\x12]\n\x10SummarizeSession\x12#.abbenay.v1.SummarizeSessionRequest\x1a$.abbenay.v1.SummarizeSessionResponse\x12\x42\n\x0b\x46orkSession\x12\x1e.abbenay.v1.ForkSessionRequest\x1a\x13.abbenay.v1.Session\x12T\n\rExportSession\x12 .abbenay.v1.ExportSessionRequest\x1a!.abbenay.v1.ExportSessionResponse\x12\x46\n\rImportSession\x12 .abbenay.v1.ImportSessionRequest\x1a\x13.abbenay.v1.Session\x12K\n\nListModels\x12\x1d.abbenay.v1.ListModelsRequest\x1a\x1e.abbenay.v1.ListModelsResponse\x12W\n\x0e\x44iscoverModels\x12!.abbenay.v1.DiscoverModelsRequest\x1a\".abbenay.v1.DiscoverModelsResponse\x12T\n\rListProviders\x12 .abbenay.v1.ListProvidersRequest\x1a!.abbenay.v1.ListProvidersResponse\x12U\n\x11GetProviderStatus\x12$.abbenay.v1.GetProviderStatusRequest\x1a\x1a.abbenay.v1.ProviderStatus\x12N\n\x0bListEngines\x12\x1e.abbenay.v1.ListEnginesRequest\x1a\x1f.abbenay.v1.ListEnginesResponse\x12`\n\x11\x43onfigureProvider\x12$.abbenay.v1.ConfigureProviderRequest\x1a%.abbenay.v1.ConfigureProviderResponse\x12\x46\n\x0eRemoveProvider\x12!.abbenay.v1.RemoveProviderRequest\x1a\x11.abbenay.v1.Empty\x12i\n\x14GetProviderTemplates\x12\'.abbenay.v1.GetProviderTemplatesRequest\x1a(.abbenay.v1.GetProviderTemplatesResponse\x12Q\n\x0cListPolicies\x12\x1f.abbenay.v1.ListPoliciesRequest\x1a .abbenay.v1.ListPoliciesResponse\x12\x42\n\x0c\x43reatePolicy\x12\x1f.abbenay.v1.CreatePolicyRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65letePolicy\x12\x1f.abbenay.v1.DeletePolicyRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tListTools\x12\x1c.abbenay.v1.ListToolsRequest\x1a\x1d.abbenay.v1.ListToolsResponse\x12N\n\x0b\x45xecuteTool\x12\x1e.abbenay.v1.ExecuteToolRequest\x1a\x1f.abbenay.v1.ExecuteToolResponse\x12H\n\tGetConfig\x12\x1c.abbenay.v1.GetConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12N\n\x0cUpdateConfig\x12\x1f.abbenay.v1.UpdateConfigRequest\x1a\x1d.abbenay.v1.GetConfigResponse\x12Q\n\x0cGetKeyStatus\x12\x1f.abbenay.v1.GetKeyStatusRequest\x1a .abbenay.v1.GetKeyStatusResponse\x12i\n\x14ListMcpServerConfigs\x12\'.abbenay.v1.ListMcpServerConfigsRequest\x1a(.abbenay.v1.ListMcpServerConfigsResponse\x12N\n\x12ReconnectMcpServer\x12%.abbenay.v1.ReconnectMcpServerRequest\x1a\x11.abbenay.v1.Empty\x12H\n\tGetSecret\x12\x1c.abbenay.v1.GetSecretRequest\x1a\x1d.abbenay.v1.GetSecretResponse\x12<\n\tSetSecret\x12\x1c.abbenay.v1.SetSecretRequest\x1a\x11.abbenay.v1.Empty\x12\x42\n\x0c\x44\x65leteSecret\x12\x1f.abbenay.v1.DeleteSecretRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bListSecrets\x12\x1e.abbenay.v1.ListSecretsRequest\x1a\x1f.abbenay.v1.ListSecretsResponse\x12\x45\n\x08Register\x12\x1b.abbenay.v1.RegisterRequest\x1a\x1c.abbenay.v1.RegisterResponse\x12>\n\nUnregister\x12\x1d.abbenay.v1.UnregisterRequest\x1a\x11.abbenay.v1.Empty\x12\x43\n\tGetStatus\x12\x1c.abbenay.v1.GetStatusRequest\x1a\x18.abbenay.v1.DaemonStatus\x12o\n\x16GetConnectedWorkspaces\x12).abbenay.v1.GetConnectedWorkspacesRequest\x1a*.abbenay.v1.GetConnectedWorkspacesResponse\x12:\n\x08Shutdown\x12\x1b.abbenay.v1.ShutdownRequest\x1a\x11.abbenay.v1.Empty\x12N\n\x0bHealthCheck\x12\x1e.abbenay.v1.HealthCheckRequest\x1a\x1f.abbenay.v1.HealthCheckResponse\x12W\n\x0eStartWebServer\x12!.abbenay.v1.StartWebServerRequest\x1a\".abbenay.v1.StartWebServerResponse\x12\x44\n\rStopWebServer\x12 .abbenay.v1.StopWebServerRequest\x1a\x11.abbenay.v1.Empty\x12`\n\x11RegisterMcpServer\x12$.abbenay.v1.RegisterMcpServerRequest\x1a%.abbenay.v1.RegisterMcpServerResponse\x12\x66\n\x13UnregisterMcpServer\x12&.abbenay.v1.UnregisterMcpServerRequest\x1a\'.abbenay.v1.UnregisterMcpServerResponse\x12I\n\x0cVSCodeStream\x12\x1a.abbenay.v1.VSCodeResponse\x1a\x19.abbenay.v1.VSCodeRequest(\x01\x30\x01\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -57,20 +57,20 @@ _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_options = b'8\001' _globals['_MCPTRANSPORT_ENVENTRY']._loaded_options = None _globals['_MCPTRANSPORT_ENVENTRY']._serialized_options = b'8\001' - _globals['_ROLE']._serialized_start=18471 - _globals['_ROLE']._serialized_end=18566 - _globals['_CLIENTTYPE']._serialized_start=18569 - _globals['_CLIENTTYPE']._serialized_end=18724 - _globals['_REPLAYFORMAT']._serialized_start=18727 - _globals['_REPLAYFORMAT']._serialized_end=18857 - _globals['_MODELSOURCE']._serialized_start=18859 - _globals['_MODELSOURCE']._serialized_end=18955 - _globals['_PROVIDERTYPE']._serialized_start=18957 - _globals['_PROVIDERTYPE']._serialized_end=19074 - _globals['_LOGLEVEL']._serialized_start=19077 - _globals['_LOGLEVEL']._serialized_end=19217 - _globals['_SECRETSTORE']._serialized_start=19219 - _globals['_SECRETSTORE']._serialized_end=19336 + _globals['_ROLE']._serialized_start=18516 + _globals['_ROLE']._serialized_end=18611 + _globals['_CLIENTTYPE']._serialized_start=18614 + _globals['_CLIENTTYPE']._serialized_end=18769 + _globals['_REPLAYFORMAT']._serialized_start=18772 + _globals['_REPLAYFORMAT']._serialized_end=18902 + _globals['_MODELSOURCE']._serialized_start=18904 + _globals['_MODELSOURCE']._serialized_end=19000 + _globals['_PROVIDERTYPE']._serialized_start=19002 + _globals['_PROVIDERTYPE']._serialized_end=19119 + _globals['_LOGLEVEL']._serialized_start=19122 + _globals['_LOGLEVEL']._serialized_end=19262 + _globals['_SECRETSTORE']._serialized_start=19264 + _globals['_SECRETSTORE']._serialized_end=19381 _globals['_EMPTY']._serialized_start=40 _globals['_EMPTY']._serialized_end=47 _globals['_TIMESTAMP']._serialized_start=49 @@ -310,119 +310,119 @@ _globals['_DELETEPOLICYREQUEST']._serialized_start=12960 _globals['_DELETEPOLICYREQUEST']._serialized_end=12995 _globals['_GETSECRETREQUEST']._serialized_start=12997 - _globals['_GETSECRETREQUEST']._serialized_end=13068 - _globals['_GETSECRETRESPONSE']._serialized_start=13070 - _globals['_GETSECRETRESPONSE']._serialized_end=13104 - _globals['_SETSECRETREQUEST']._serialized_start=13106 - _globals['_SETSECRETREQUEST']._serialized_end=13192 - _globals['_DELETESECRETREQUEST']._serialized_start=13194 - _globals['_DELETESECRETREQUEST']._serialized_end=13268 - _globals['_LISTSECRETSREQUEST']._serialized_start=13270 - _globals['_LISTSECRETSREQUEST']._serialized_end=13290 - _globals['_LISTSECRETSRESPONSE']._serialized_start=13292 - _globals['_LISTSECRETSRESPONSE']._serialized_end=13354 - _globals['_SECRETINFO']._serialized_start=13356 - _globals['_SECRETINFO']._serialized_end=13440 - _globals['_REGISTERREQUEST']._serialized_start=13442 - _globals['_REGISTERREQUEST']._serialized_end=13568 - _globals['_REGISTERRESPONSE']._serialized_start=13570 - _globals['_REGISTERRESPONSE']._serialized_end=13634 - _globals['_UNREGISTERREQUEST']._serialized_start=13636 - _globals['_UNREGISTERREQUEST']._serialized_end=13674 - _globals['_GETSTATUSREQUEST']._serialized_start=13676 - _globals['_GETSTATUSREQUEST']._serialized_end=13694 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13696 - _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13727 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13729 - _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13781 - _globals['_DAEMONSTATUS']._serialized_start=13784 - _globals['_DAEMONSTATUS']._serialized_end=13988 - _globals['_CONNECTEDCLIENT']._serialized_start=13991 - _globals['_CONNECTEDCLIENT']._serialized_end=14161 - _globals['_SHUTDOWNREQUEST']._serialized_start=14163 - _globals['_SHUTDOWNREQUEST']._serialized_end=14225 - _globals['_HEALTHCHECKREQUEST']._serialized_start=14227 - _globals['_HEALTHCHECKREQUEST']._serialized_end=14247 - _globals['_HEALTHCHECKRESPONSE']._serialized_start=14249 - _globals['_HEALTHCHECKRESPONSE']._serialized_end=14304 - _globals['_STARTWEBSERVERREQUEST']._serialized_start=14306 - _globals['_STARTWEBSERVERREQUEST']._serialized_end=14343 - _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14345 - _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14438 - _globals['_STOPWEBSERVERREQUEST']._serialized_start=14440 - _globals['_STOPWEBSERVERREQUEST']._serialized_end=14462 - _globals['_VSCODEREQUEST']._serialized_start=14465 - _globals['_VSCODEREQUEST']._serialized_end=14862 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14864 - _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14907 - _globals['_VSCODERESPONSE']._serialized_start=14910 - _globals['_VSCODERESPONSE']._serialized_end=15356 - _globals['_GETWORKSPACEREQUEST']._serialized_start=15358 - _globals['_GETWORKSPACEREQUEST']._serialized_end=15379 - _globals['_GETWORKSPACERESPONSE']._serialized_start=15381 - _globals['_GETWORKSPACERESPONSE']._serialized_end=15454 - _globals['_VSCODEERROR']._serialized_start=15456 - _globals['_VSCODEERROR']._serialized_end=15500 - _globals['_INVOKETOOLREQUEST']._serialized_start=15502 - _globals['_INVOKETOOLREQUEST']._serialized_end=15564 - _globals['_INVOKETOOLRESPONSE']._serialized_start=15566 - _globals['_INVOKETOOLRESPONSE']._serialized_end=15625 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15627 - _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15651 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15653 - _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15721 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15723 - _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15793 - _globals['_VSCODETOOLINFO']._serialized_start=15795 - _globals['_VSCODETOOLINFO']._serialized_end=15882 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15884 - _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=15955 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=15957 - _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=16024 - _globals['_VSCODEMODEL']._serialized_start=16026 - _globals['_VSCODEMODEL']._serialized_end=16123 - _globals['_SENDVSCODECHATREQUEST']._serialized_start=16126 - _globals['_SENDVSCODECHATREQUEST']._serialized_end=16288 - _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16290 - _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16359 - _globals['_VSCODECHATCHUNK']._serialized_start=16361 - _globals['_VSCODECHATCHUNK']._serialized_end=16452 - _globals['_VSCODETOOLCALL']._serialized_start=16454 - _globals['_VSCODETOOLCALL']._serialized_end=16525 - _globals['_LISTPOLICIESREQUEST']._serialized_start=16527 - _globals['_LISTPOLICIESREQUEST']._serialized_end=16548 - _globals['_LISTPOLICIESRESPONSE']._serialized_start=16550 - _globals['_LISTPOLICIESRESPONSE']._serialized_end=16614 - _globals['_POLICYINFO']._serialized_start=16616 - _globals['_POLICYINFO']._serialized_end=16701 - _globals['_POLICYCONFIG']._serialized_start=16704 - _globals['_POLICYCONFIG']._serialized_end=17026 - _globals['_POLICYSAMPLING']._serialized_start=17028 - _globals['_POLICYSAMPLING']._serialized_end=17146 - _globals['_POLICYOUTPUT']._serialized_start=17149 - _globals['_POLICYOUTPUT']._serialized_end=17417 - _globals['_POLICYCONTEXT']._serialized_start=17420 - _globals['_POLICYCONTEXT']._serialized_end=17549 - _globals['_POLICYTOOL']._serialized_start=17551 - _globals['_POLICYTOOL']._serialized_end=17659 - _globals['_POLICYRELIABILITY']._serialized_start=17661 - _globals['_POLICYRELIABILITY']._serialized_end=17776 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17779 - _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=17984 - _globals['_MCPTRANSPORT']._serialized_start=17987 - _globals['_MCPTRANSPORT']._serialized_end=18285 + _globals['_GETSECRETREQUEST']._serialized_end=13083 + _globals['_GETSECRETRESPONSE']._serialized_start=13085 + _globals['_GETSECRETRESPONSE']._serialized_end=13119 + _globals['_SETSECRETREQUEST']._serialized_start=13121 + _globals['_SETSECRETREQUEST']._serialized_end=13222 + _globals['_DELETESECRETREQUEST']._serialized_start=13224 + _globals['_DELETESECRETREQUEST']._serialized_end=13313 + _globals['_LISTSECRETSREQUEST']._serialized_start=13315 + _globals['_LISTSECRETSREQUEST']._serialized_end=13335 + _globals['_LISTSECRETSRESPONSE']._serialized_start=13337 + _globals['_LISTSECRETSRESPONSE']._serialized_end=13399 + _globals['_SECRETINFO']._serialized_start=13401 + _globals['_SECRETINFO']._serialized_end=13485 + _globals['_REGISTERREQUEST']._serialized_start=13487 + _globals['_REGISTERREQUEST']._serialized_end=13613 + _globals['_REGISTERRESPONSE']._serialized_start=13615 + _globals['_REGISTERRESPONSE']._serialized_end=13679 + _globals['_UNREGISTERREQUEST']._serialized_start=13681 + _globals['_UNREGISTERREQUEST']._serialized_end=13719 + _globals['_GETSTATUSREQUEST']._serialized_start=13721 + _globals['_GETSTATUSREQUEST']._serialized_end=13739 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_start=13741 + _globals['_GETCONNECTEDWORKSPACESREQUEST']._serialized_end=13772 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_start=13774 + _globals['_GETCONNECTEDWORKSPACESRESPONSE']._serialized_end=13826 + _globals['_DAEMONSTATUS']._serialized_start=13829 + _globals['_DAEMONSTATUS']._serialized_end=14033 + _globals['_CONNECTEDCLIENT']._serialized_start=14036 + _globals['_CONNECTEDCLIENT']._serialized_end=14206 + _globals['_SHUTDOWNREQUEST']._serialized_start=14208 + _globals['_SHUTDOWNREQUEST']._serialized_end=14270 + _globals['_HEALTHCHECKREQUEST']._serialized_start=14272 + _globals['_HEALTHCHECKREQUEST']._serialized_end=14292 + _globals['_HEALTHCHECKRESPONSE']._serialized_start=14294 + _globals['_HEALTHCHECKRESPONSE']._serialized_end=14349 + _globals['_STARTWEBSERVERREQUEST']._serialized_start=14351 + _globals['_STARTWEBSERVERREQUEST']._serialized_end=14388 + _globals['_STARTWEBSERVERRESPONSE']._serialized_start=14390 + _globals['_STARTWEBSERVERRESPONSE']._serialized_end=14483 + _globals['_STOPWEBSERVERREQUEST']._serialized_start=14485 + _globals['_STOPWEBSERVERREQUEST']._serialized_end=14507 + _globals['_VSCODEREQUEST']._serialized_start=14510 + _globals['_VSCODEREQUEST']._serialized_end=14907 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_start=14909 + _globals['_MODELSCHANGEDNOTIFICATION']._serialized_end=14952 + _globals['_VSCODERESPONSE']._serialized_start=14955 + _globals['_VSCODERESPONSE']._serialized_end=15401 + _globals['_GETWORKSPACEREQUEST']._serialized_start=15403 + _globals['_GETWORKSPACEREQUEST']._serialized_end=15424 + _globals['_GETWORKSPACERESPONSE']._serialized_start=15426 + _globals['_GETWORKSPACERESPONSE']._serialized_end=15499 + _globals['_VSCODEERROR']._serialized_start=15501 + _globals['_VSCODEERROR']._serialized_end=15545 + _globals['_INVOKETOOLREQUEST']._serialized_start=15547 + _globals['_INVOKETOOLREQUEST']._serialized_end=15609 + _globals['_INVOKETOOLRESPONSE']._serialized_start=15611 + _globals['_INVOKETOOLRESPONSE']._serialized_end=15670 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_start=15672 + _globals['_LISTVSCODETOOLSREQUEST']._serialized_end=15696 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_start=15698 + _globals['_LISTVSCODETOOLSRESPONSE']._serialized_end=15766 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_start=15768 + _globals['_REGISTERTOOLSNOTIFICATION']._serialized_end=15838 + _globals['_VSCODETOOLINFO']._serialized_start=15840 + _globals['_VSCODETOOLINFO']._serialized_end=15927 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_start=15929 + _globals['_LISTVSCODEMODELSREQUEST']._serialized_end=16000 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_start=16002 + _globals['_LISTVSCODEMODELSRESPONSE']._serialized_end=16069 + _globals['_VSCODEMODEL']._serialized_start=16071 + _globals['_VSCODEMODEL']._serialized_end=16168 + _globals['_SENDVSCODECHATREQUEST']._serialized_start=16171 + _globals['_SENDVSCODECHATREQUEST']._serialized_end=16333 + _globals['_SENDVSCODECHATRESPONSE']._serialized_start=16335 + _globals['_SENDVSCODECHATRESPONSE']._serialized_end=16404 + _globals['_VSCODECHATCHUNK']._serialized_start=16406 + _globals['_VSCODECHATCHUNK']._serialized_end=16497 + _globals['_VSCODETOOLCALL']._serialized_start=16499 + _globals['_VSCODETOOLCALL']._serialized_end=16570 + _globals['_LISTPOLICIESREQUEST']._serialized_start=16572 + _globals['_LISTPOLICIESREQUEST']._serialized_end=16593 + _globals['_LISTPOLICIESRESPONSE']._serialized_start=16595 + _globals['_LISTPOLICIESRESPONSE']._serialized_end=16659 + _globals['_POLICYINFO']._serialized_start=16661 + _globals['_POLICYINFO']._serialized_end=16746 + _globals['_POLICYCONFIG']._serialized_start=16749 + _globals['_POLICYCONFIG']._serialized_end=17071 + _globals['_POLICYSAMPLING']._serialized_start=17073 + _globals['_POLICYSAMPLING']._serialized_end=17191 + _globals['_POLICYOUTPUT']._serialized_start=17194 + _globals['_POLICYOUTPUT']._serialized_end=17462 + _globals['_POLICYCONTEXT']._serialized_start=17465 + _globals['_POLICYCONTEXT']._serialized_end=17594 + _globals['_POLICYTOOL']._serialized_start=17596 + _globals['_POLICYTOOL']._serialized_end=17704 + _globals['_POLICYRELIABILITY']._serialized_start=17706 + _globals['_POLICYRELIABILITY']._serialized_end=17821 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_start=17824 + _globals['_REGISTERMCPSERVERREQUEST']._serialized_end=18029 + _globals['_MCPTRANSPORT']._serialized_start=18032 + _globals['_MCPTRANSPORT']._serialized_end=18330 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_start=10730 _globals['_MCPTRANSPORT_HEADERSENTRY']._serialized_end=10776 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_start=10778 _globals['_MCPTRANSPORT_ENVENTRY']._serialized_end=10820 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18287 - _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18372 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18374 - _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18421 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18423 - _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18469 - _globals['_MCPBRIDGE']._serialized_start=19339 - _globals['_MCPBRIDGE']._serialized_end=20010 - _globals['_ABBENAY']._serialized_start=20013 - _globals['_ABBENAY']._serialized_end=23599 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_start=18332 + _globals['_REGISTERMCPSERVERRESPONSE']._serialized_end=18417 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_start=18419 + _globals['_UNREGISTERMCPSERVERREQUEST']._serialized_end=18466 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_start=18468 + _globals['_UNREGISTERMCPSERVERRESPONSE']._serialized_end=18514 + _globals['_MCPBRIDGE']._serialized_start=19384 + _globals['_MCPBRIDGE']._serialized_end=20055 + _globals['_ABBENAY']._serialized_start=20058 + _globals['_ABBENAY']._serialized_end=23644 # @@protoc_insertion_point(module_scope) diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi index 2062ccae..c55dbe5b 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2.pyi @@ -189,7 +189,7 @@ class ToolPartialResult(_message.Message): IS_FINAL_FIELD_NUMBER: _ClassVar[int] content_json: str is_final: bool - def __init__(self, content_json: _Optional[str] = ..., is_final: bool = ...) -> None: ... + def __init__(self, content_json: _Optional[str] = ..., is_final: _Optional[bool] = ...) -> None: ... class ToolFinalResult(_message.Message): __slots__ = ("content", "is_error") @@ -197,7 +197,7 @@ class ToolFinalResult(_message.Message): IS_ERROR_FIELD_NUMBER: _ClassVar[int] content: _containers.RepeatedCompositeFieldContainer[ToolContent] is_error: bool - def __init__(self, content: _Optional[_Iterable[_Union[ToolContent, _Mapping]]] = ..., is_error: bool = ...) -> None: ... + def __init__(self, content: _Optional[_Iterable[_Union[ToolContent, _Mapping]]] = ..., is_error: _Optional[bool] = ...) -> None: ... class ToolContent(_message.Message): __slots__ = ("type", "text", "mime_type", "data", "uri") @@ -267,7 +267,7 @@ class CallToolsBatchRequest(_message.Message): STOP_ON_ERROR_FIELD_NUMBER: _ClassVar[int] calls: _containers.RepeatedCompositeFieldContainer[CallToolRequest] stop_on_error: bool - def __init__(self, calls: _Optional[_Iterable[_Union[CallToolRequest, _Mapping]]] = ..., stop_on_error: bool = ...) -> None: ... + def __init__(self, calls: _Optional[_Iterable[_Union[CallToolRequest, _Mapping]]] = ..., stop_on_error: _Optional[bool] = ...) -> None: ... class ListResourcesRequest(_message.Message): __slots__ = ("server_filter", "uri_prefix") @@ -337,7 +337,7 @@ class McpPromptArgument(_message.Message): name: str description: str required: bool - def __init__(self, name: _Optional[str] = ..., description: _Optional[str] = ..., required: bool = ...) -> None: ... + def __init__(self, name: _Optional[str] = ..., description: _Optional[str] = ..., required: _Optional[bool] = ...) -> None: ... class GetPromptRequest(_message.Message): __slots__ = ("name", "arguments") @@ -418,7 +418,7 @@ class ChatOptions(_message.Message): top_k: int timeout: int tool_mode: str - def __init__(self, temperature: _Optional[float] = ..., max_tokens: _Optional[int] = ..., top_p: _Optional[float] = ..., stop: _Optional[_Iterable[str]] = ..., enable_tools: bool = ..., max_tool_iterations: _Optional[int] = ..., tool_filter: _Optional[_Iterable[str]] = ..., top_k: _Optional[int] = ..., timeout: _Optional[int] = ..., tool_mode: _Optional[str] = ...) -> None: ... + def __init__(self, temperature: _Optional[float] = ..., max_tokens: _Optional[int] = ..., top_p: _Optional[float] = ..., stop: _Optional[_Iterable[str]] = ..., enable_tools: _Optional[bool] = ..., max_tool_iterations: _Optional[int] = ..., tool_filter: _Optional[_Iterable[str]] = ..., top_k: _Optional[int] = ..., timeout: _Optional[int] = ..., tool_mode: _Optional[str] = ...) -> None: ... class ChatChunk(_message.Message): __slots__ = ("text", "tool_call", "tool_result", "prompt", "usage", "error", "done") @@ -464,7 +464,7 @@ class ToolResultChunk(_message.Message): name: str content: str is_error: bool - def __init__(self, tool_call_id: _Optional[str] = ..., name: _Optional[str] = ..., content: _Optional[str] = ..., is_error: bool = ...) -> None: ... + def __init__(self, tool_call_id: _Optional[str] = ..., name: _Optional[str] = ..., content: _Optional[str] = ..., is_error: _Optional[bool] = ...) -> None: ... class PromptChunk(_message.Message): __slots__ = ("tool_call_id", "tool_name", "prompt_text", "options") @@ -592,7 +592,7 @@ class GetSessionRequest(_message.Message): INCLUDE_MESSAGES_FIELD_NUMBER: _ClassVar[int] session_id: str include_messages: bool - def __init__(self, session_id: _Optional[str] = ..., include_messages: bool = ...) -> None: ... + def __init__(self, session_id: _Optional[str] = ..., include_messages: _Optional[bool] = ...) -> None: ... class ListSessionsRequest(_message.Message): __slots__ = ("limit", "offset", "source_filter", "model_filter") @@ -706,7 +706,7 @@ class SummarizeSessionResponse(_message.Message): FROM_CACHE_FIELD_NUMBER: _ClassVar[int] summary: str from_cache: bool - def __init__(self, summary: _Optional[str] = ..., from_cache: bool = ...) -> None: ... + def __init__(self, summary: _Optional[str] = ..., from_cache: _Optional[bool] = ...) -> None: ... class ForkSessionRequest(_message.Message): __slots__ = ("session_id", "new_model", "fork_point") @@ -726,7 +726,7 @@ class ExportSessionRequest(_message.Message): session_id: str include_tool_results: bool include_metadata: bool - def __init__(self, session_id: _Optional[str] = ..., include_tool_results: bool = ..., include_metadata: bool = ...) -> None: ... + def __init__(self, session_id: _Optional[str] = ..., include_tool_results: _Optional[bool] = ..., include_metadata: _Optional[bool] = ...) -> None: ... class ExportSessionResponse(_message.Message): __slots__ = ("json_content",) @@ -740,7 +740,7 @@ class ImportSessionRequest(_message.Message): GENERATE_NEW_ID_FIELD_NUMBER: _ClassVar[int] json_content: str generate_new_id: bool - def __init__(self, json_content: _Optional[str] = ..., generate_new_id: bool = ...) -> None: ... + def __init__(self, json_content: _Optional[str] = ..., generate_new_id: _Optional[bool] = ...) -> None: ... class ListModelsRequest(_message.Message): __slots__ = ("provider_filter", "workspace_paths") @@ -824,7 +824,7 @@ class ModelCapabilities(_message.Message): supports_tools: bool supports_vision: bool context_window: int - def __init__(self, supports_streaming: bool = ..., supports_tools: bool = ..., supports_vision: bool = ..., context_window: _Optional[int] = ...) -> None: ... + def __init__(self, supports_streaming: _Optional[bool] = ..., supports_tools: _Optional[bool] = ..., supports_vision: _Optional[bool] = ..., context_window: _Optional[int] = ...) -> None: ... class ListProvidersRequest(_message.Message): __slots__ = ("workspace_paths",) @@ -856,7 +856,7 @@ class Provider(_message.Message): default_base_url: str engine: str base_url: str - def __init__(self, id: _Optional[str] = ..., configured: bool = ..., healthy: bool = ..., provider_type: _Optional[_Union[ProviderType, str]] = ..., requires_key: bool = ..., default_base_url: _Optional[str] = ..., engine: _Optional[str] = ..., base_url: _Optional[str] = ...) -> None: ... + def __init__(self, id: _Optional[str] = ..., configured: _Optional[bool] = ..., healthy: _Optional[bool] = ..., provider_type: _Optional[_Union[ProviderType, str]] = ..., requires_key: _Optional[bool] = ..., default_base_url: _Optional[str] = ..., engine: _Optional[str] = ..., base_url: _Optional[str] = ...) -> None: ... class GetProviderStatusRequest(_message.Message): __slots__ = ("provider_id",) @@ -876,7 +876,7 @@ class ProviderStatus(_message.Message): healthy: bool error: str last_check: Timestamp - def __init__(self, provider_id: _Optional[str] = ..., configured: bool = ..., healthy: bool = ..., error: _Optional[str] = ..., last_check: _Optional[_Union[Timestamp, _Mapping]] = ...) -> None: ... + def __init__(self, provider_id: _Optional[str] = ..., configured: _Optional[bool] = ..., healthy: _Optional[bool] = ..., error: _Optional[str] = ..., last_check: _Optional[_Union[Timestamp, _Mapping]] = ...) -> None: ... class ListEnginesRequest(_message.Message): __slots__ = () @@ -900,7 +900,7 @@ class Engine(_message.Message): default_base_url: str default_env_var: str display_name: str - def __init__(self, id: _Optional[str] = ..., requires_key: bool = ..., default_base_url: _Optional[str] = ..., default_env_var: _Optional[str] = ..., display_name: _Optional[str] = ...) -> None: ... + def __init__(self, id: _Optional[str] = ..., requires_key: _Optional[bool] = ..., default_base_url: _Optional[str] = ..., default_env_var: _Optional[str] = ..., display_name: _Optional[str] = ...) -> None: ... class ListToolsRequest(_message.Message): __slots__ = ("server_filter",) @@ -940,7 +940,7 @@ class ExecuteToolResponse(_message.Message): IS_ERROR_FIELD_NUMBER: _ClassVar[int] content: str is_error: bool - def __init__(self, content: _Optional[str] = ..., is_error: bool = ...) -> None: ... + def __init__(self, content: _Optional[str] = ..., is_error: _Optional[bool] = ...) -> None: ... class GetConfigRequest(_message.Message): __slots__ = ("location",) @@ -1068,7 +1068,7 @@ class McpServerConfigMsg(_message.Message): headers: _containers.ScalarMap[str, str] env: _containers.ScalarMap[str, str] max_response_size: int - def __init__(self, command: _Optional[str] = ..., args: _Optional[_Iterable[str]] = ..., url: _Optional[str] = ..., transport: _Optional[str] = ..., enabled: bool = ..., headers: _Optional[_Mapping[str, str]] = ..., env: _Optional[_Mapping[str, str]] = ..., max_response_size: _Optional[int] = ...) -> None: ... + def __init__(self, command: _Optional[str] = ..., args: _Optional[_Iterable[str]] = ..., url: _Optional[str] = ..., transport: _Optional[str] = ..., enabled: _Optional[bool] = ..., headers: _Optional[_Mapping[str, str]] = ..., env: _Optional[_Mapping[str, str]] = ..., max_response_size: _Optional[int] = ...) -> None: ... class ToolPolicyConfigMsg(_message.Message): __slots__ = ("max_tool_iterations", "auto_approve", "require_approval", "disabled_tools", "aliases") @@ -1117,7 +1117,7 @@ class ConsumerCapabilitiesMsg(_message.Message): providers: bool shutdown: bool chat: bool - def __init__(self, inline_policy: bool = ..., mcp_register: bool = ..., secrets: bool = ..., config: bool = ..., providers: bool = ..., shutdown: bool = ..., chat: bool = ...) -> None: ... + def __init__(self, inline_policy: _Optional[bool] = ..., mcp_register: _Optional[bool] = ..., secrets: _Optional[bool] = ..., config: _Optional[bool] = ..., providers: _Optional[bool] = ..., shutdown: _Optional[bool] = ..., chat: _Optional[bool] = ...) -> None: ... class UpdateConfigRequest(_message.Message): __slots__ = ("config", "location") @@ -1153,7 +1153,7 @@ class ConfigureProviderResponse(_message.Message): __slots__ = ("success",) SUCCESS_FIELD_NUMBER: _ClassVar[int] success: bool - def __init__(self, success: bool = ...) -> None: ... + def __init__(self, success: _Optional[bool] = ...) -> None: ... class RemoveProviderRequest(_message.Message): __slots__ = ("provider_id", "target", "workspace_path") @@ -1185,7 +1185,7 @@ class ProviderTemplate(_message.Message): suggested_name: str default_base_url: str requires_key: bool - def __init__(self, engine: _Optional[str] = ..., suggested_name: _Optional[str] = ..., default_base_url: _Optional[str] = ..., requires_key: bool = ...) -> None: ... + def __init__(self, engine: _Optional[str] = ..., suggested_name: _Optional[str] = ..., default_base_url: _Optional[str] = ..., requires_key: _Optional[bool] = ...) -> None: ... class GetKeyStatusRequest(_message.Message): __slots__ = ("source", "name") @@ -1199,7 +1199,7 @@ class GetKeyStatusResponse(_message.Message): __slots__ = ("exists",) EXISTS_FIELD_NUMBER: _ClassVar[int] exists: bool - def __init__(self, exists: bool = ...) -> None: ... + def __init__(self, exists: _Optional[bool] = ...) -> None: ... class ListMcpServerConfigsRequest(_message.Message): __slots__ = () @@ -1225,7 +1225,7 @@ class McpServerStatusEntry(_message.Message): status: str tool_count: int error: str - def __init__(self, id: _Optional[str] = ..., transport: _Optional[str] = ..., enabled: bool = ..., status: _Optional[str] = ..., tool_count: _Optional[int] = ..., error: _Optional[str] = ...) -> None: ... + def __init__(self, id: _Optional[str] = ..., transport: _Optional[str] = ..., enabled: _Optional[bool] = ..., status: _Optional[str] = ..., tool_count: _Optional[int] = ..., error: _Optional[str] = ...) -> None: ... class ReconnectMcpServerRequest(_message.Message): __slots__ = ("server_id",) @@ -1297,7 +1297,7 @@ class SecretInfo(_message.Message): key: str store: SecretStore has_value: bool - def __init__(self, key: _Optional[str] = ..., store: _Optional[_Union[SecretStore, str]] = ..., has_value: bool = ...) -> None: ... + def __init__(self, key: _Optional[str] = ..., store: _Optional[_Union[SecretStore, str]] = ..., has_value: _Optional[bool] = ...) -> None: ... class RegisterRequest(_message.Message): __slots__ = ("client", "is_spawner", "workspace_path", "workspace_paths") @@ -1309,7 +1309,7 @@ class RegisterRequest(_message.Message): is_spawner: bool workspace_path: str workspace_paths: _containers.RepeatedScalarFieldContainer[str] - def __init__(self, client: _Optional[_Union[ClientInfo, _Mapping]] = ..., is_spawner: bool = ..., workspace_path: _Optional[str] = ..., workspace_paths: _Optional[_Iterable[str]] = ...) -> None: ... + def __init__(self, client: _Optional[_Union[ClientInfo, _Mapping]] = ..., is_spawner: _Optional[bool] = ..., workspace_path: _Optional[str] = ..., workspace_paths: _Optional[_Iterable[str]] = ...) -> None: ... class RegisterResponse(_message.Message): __slots__ = ("client_id", "connected_clients") @@ -1367,7 +1367,7 @@ class ConnectedClient(_message.Message): connected_at: Timestamp is_spawner: bool workspace_path: str - def __init__(self, client_id: _Optional[str] = ..., client_type: _Optional[_Union[ClientType, str]] = ..., connected_at: _Optional[_Union[Timestamp, _Mapping]] = ..., is_spawner: bool = ..., workspace_path: _Optional[str] = ...) -> None: ... + def __init__(self, client_id: _Optional[str] = ..., client_type: _Optional[_Union[ClientType, str]] = ..., connected_at: _Optional[_Union[Timestamp, _Mapping]] = ..., is_spawner: _Optional[bool] = ..., workspace_path: _Optional[str] = ...) -> None: ... class ShutdownRequest(_message.Message): __slots__ = ("force", "grace_period_seconds") @@ -1375,7 +1375,7 @@ class ShutdownRequest(_message.Message): GRACE_PERIOD_SECONDS_FIELD_NUMBER: _ClassVar[int] force: bool grace_period_seconds: int - def __init__(self, force: bool = ..., grace_period_seconds: _Optional[int] = ...) -> None: ... + def __init__(self, force: _Optional[bool] = ..., grace_period_seconds: _Optional[int] = ...) -> None: ... class HealthCheckRequest(_message.Message): __slots__ = () @@ -1387,7 +1387,7 @@ class HealthCheckResponse(_message.Message): VERSION_FIELD_NUMBER: _ClassVar[int] healthy: bool version: str - def __init__(self, healthy: bool = ..., version: _Optional[str] = ...) -> None: ... + def __init__(self, healthy: _Optional[bool] = ..., version: _Optional[str] = ...) -> None: ... class StartWebServerRequest(_message.Message): __slots__ = ("port",) @@ -1405,7 +1405,7 @@ class StartWebServerResponse(_message.Message): already_running: bool port: int url: str - def __init__(self, started: bool = ..., already_running: bool = ..., port: _Optional[int] = ..., url: _Optional[str] = ...) -> None: ... + def __init__(self, started: _Optional[bool] = ..., already_running: _Optional[bool] = ..., port: _Optional[int] = ..., url: _Optional[str] = ...) -> None: ... class StopWebServerRequest(_message.Message): __slots__ = () @@ -1489,7 +1489,7 @@ class InvokeToolResponse(_message.Message): IS_ERROR_FIELD_NUMBER: _ClassVar[int] result_json: str is_error: bool - def __init__(self, result_json: _Optional[str] = ..., is_error: bool = ...) -> None: ... + def __init__(self, result_json: _Optional[str] = ..., is_error: _Optional[bool] = ...) -> None: ... class ListVSCodeToolsRequest(_message.Message): __slots__ = () @@ -1599,7 +1599,7 @@ class PolicyInfo(_message.Message): name: str builtin: bool config: PolicyConfig - def __init__(self, name: _Optional[str] = ..., builtin: bool = ..., config: _Optional[_Union[PolicyConfig, _Mapping]] = ...) -> None: ... + def __init__(self, name: _Optional[str] = ..., builtin: _Optional[bool] = ..., config: _Optional[_Union[PolicyConfig, _Mapping]] = ...) -> None: ... class PolicyConfig(_message.Message): __slots__ = ("sampling", "output", "context", "tool", "reliability") @@ -1661,7 +1661,7 @@ class PolicyReliability(_message.Message): TIMEOUT_FIELD_NUMBER: _ClassVar[int] retry_on_invalid_json: bool timeout: int - def __init__(self, retry_on_invalid_json: bool = ..., timeout: _Optional[int] = ...) -> None: ... + def __init__(self, retry_on_invalid_json: _Optional[bool] = ..., timeout: _Optional[int] = ...) -> None: ... class RegisterMcpServerRequest(_message.Message): __slots__ = ("server_id", "transport", "session_id", "tool_filter", "max_response_size") @@ -1715,7 +1715,7 @@ class RegisterMcpServerResponse(_message.Message): success: bool error: str discovered_tools: _containers.RepeatedScalarFieldContainer[str] - def __init__(self, success: bool = ..., error: _Optional[str] = ..., discovered_tools: _Optional[_Iterable[str]] = ...) -> None: ... + def __init__(self, success: _Optional[bool] = ..., error: _Optional[str] = ..., discovered_tools: _Optional[_Iterable[str]] = ...) -> None: ... class UnregisterMcpServerRequest(_message.Message): __slots__ = ("server_id",) @@ -1727,4 +1727,4 @@ class UnregisterMcpServerResponse(_message.Message): __slots__ = ("success",) SUCCESS_FIELD_NUMBER: _ClassVar[int] success: bool - def __init__(self, success: bool = ...) -> None: ... + def __init__(self, success: _Optional[bool] = ...) -> None: ... diff --git a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2_grpc.py b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2_grpc.py index 8a821554..b111770a 100644 --- a/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2_grpc.py +++ b/packages/python/src/abbenay_grpc/abbenay/v1/service_pb2_grpc.py @@ -5,7 +5,7 @@ from abbenay_grpc.abbenay.v1 import service_pb2 as abbenay_dot_v1_dot_service__pb2 -GRPC_GENERATED_VERSION = '1.78.0' +GRPC_GENERATED_VERSION = '1.83.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False @@ -25,7 +25,7 @@ ) -class McpBridgeStub(object): +class McpBridgeStub: """ MCP Bridge Service - High-performance tool execution @@ -86,7 +86,7 @@ def __init__(self, channel): _registered_method=True) -class McpBridgeServicer(object): +class McpBridgeServicer: """ MCP Bridge Service - High-performance tool execution @@ -208,7 +208,7 @@ def add_McpBridgeServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. -class McpBridge(object): +class McpBridge: """ MCP Bridge Service - High-performance tool execution @@ -438,7 +438,7 @@ def GetPrompt(request, _registered_method=True) -class AbbenayStub(object): +class AbbenayStub: """ Main Service - Unified daemon API @@ -681,7 +681,7 @@ def __init__(self, channel): _registered_method=True) -class AbbenayServicer(object): +class AbbenayServicer: """ Main Service - Unified daemon API @@ -1290,7 +1290,7 @@ def add_AbbenayServicer_to_server(servicer, server): # This class is part of an EXPERIMENTAL API. -class Abbenay(object): +class Abbenay: """ Main Service - Unified daemon API diff --git a/packages/vscode/src/proto/abbenay/v1/service.ts b/packages/vscode/src/proto/abbenay/v1/service.ts index 71af91da..a69bcb11 100644 --- a/packages/vscode/src/proto/abbenay/v1/service.ts +++ b/packages/vscode/src/proto/abbenay/v1/service.ts @@ -1,7 +1,7 @@ // Code generated by protoc-gen-ts_proto. DO NOT EDIT. // versions: // protoc-gen-ts_proto v2.11.5 -// protoc v3.19.6 +// protoc v6.33.4 // source: abbenay/v1/service.proto /* eslint-disable */ @@ -1344,7 +1344,7 @@ export interface DeletePolicyRequest { export interface GetSecretRequest { key: string; /** Backend namespace (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface GetSecretResponse { @@ -1355,13 +1355,13 @@ export interface SetSecretRequest { key: string; value: string; /** Where to store (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface DeleteSecretRequest { key: string; /** Backend namespace (default keychain) */ - store: SecretStore; + store?: SecretStore | undefined; } export interface ListSecretsRequest { @@ -13600,7 +13600,7 @@ export const DeletePolicyRequest: MessageFns = { }; function createBaseGetSecretRequest(): GetSecretRequest { - return { key: "", store: 0 }; + return { key: "", store: undefined }; } export const GetSecretRequest: MessageFns = { @@ -13608,7 +13608,7 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(16).int32(message.store); } return writer; @@ -13649,7 +13649,7 @@ export const GetSecretRequest: MessageFns = { fromJSON(object: any): GetSecretRequest { return { key: isSet(object.key) ? globalThis.String(object.key) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13658,7 +13658,7 @@ export const GetSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13670,7 +13670,7 @@ export const GetSecretRequest: MessageFns = { fromPartial(object: DeepPartial): GetSecretRequest { const message = createBaseGetSecretRequest(); message.key = object.key ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; @@ -13734,7 +13734,7 @@ export const GetSecretResponse: MessageFns = { }; function createBaseSetSecretRequest(): SetSecretRequest { - return { key: "", value: "", store: 0 }; + return { key: "", value: "", store: undefined }; } export const SetSecretRequest: MessageFns = { @@ -13745,7 +13745,7 @@ export const SetSecretRequest: MessageFns = { if (message.value !== "") { writer.uint32(18).string(message.value); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(24).int32(message.store); } return writer; @@ -13795,7 +13795,7 @@ export const SetSecretRequest: MessageFns = { return { key: isSet(object.key) ? globalThis.String(object.key) : "", value: isSet(object.value) ? globalThis.String(object.value) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13807,7 +13807,7 @@ export const SetSecretRequest: MessageFns = { if (message.value !== "") { obj.value = message.value; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13820,13 +13820,13 @@ export const SetSecretRequest: MessageFns = { const message = createBaseSetSecretRequest(); message.key = object.key ?? ""; message.value = object.value ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; function createBaseDeleteSecretRequest(): DeleteSecretRequest { - return { key: "", store: 0 }; + return { key: "", store: undefined }; } export const DeleteSecretRequest: MessageFns = { @@ -13834,7 +13834,7 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { writer.uint32(10).string(message.key); } - if (message.store !== 0) { + if (message.store !== undefined) { writer.uint32(16).int32(message.store); } return writer; @@ -13875,7 +13875,7 @@ export const DeleteSecretRequest: MessageFns = { fromJSON(object: any): DeleteSecretRequest { return { key: isSet(object.key) ? globalThis.String(object.key) : "", - store: isSet(object.store) ? secretStoreFromJSON(object.store) : 0, + store: isSet(object.store) ? secretStoreFromJSON(object.store) : undefined, }; }, @@ -13884,7 +13884,7 @@ export const DeleteSecretRequest: MessageFns = { if (message.key !== "") { obj.key = message.key; } - if (message.store !== 0) { + if (message.store !== undefined) { obj.store = secretStoreToJSON(message.store); } return obj; @@ -13896,7 +13896,7 @@ export const DeleteSecretRequest: MessageFns = { fromPartial(object: DeepPartial): DeleteSecretRequest { const message = createBaseDeleteSecretRequest(); message.key = object.key ?? ""; - message.store = object.store ?? 0; + message.store = object.store ?? undefined; return message; }, }; diff --git a/proto/abbenay/v1/service.proto b/proto/abbenay/v1/service.proto index 2165f5f2..024dfcdb 100644 --- a/proto/abbenay/v1/service.proto +++ b/proto/abbenay/v1/service.proto @@ -1022,7 +1022,7 @@ message DeletePolicyRequest { message GetSecretRequest { string key = 1; - SecretStore store = 2; // Backend namespace (default keychain) + optional SecretStore store = 2; // Backend namespace (default keychain) } message GetSecretResponse { @@ -1032,7 +1032,7 @@ message GetSecretResponse { message SetSecretRequest { string key = 1; string value = 2; - SecretStore store = 3; // Where to store (default keychain) + optional SecretStore store = 3; // Where to store (default keychain) } enum SecretStore { @@ -1044,7 +1044,7 @@ enum SecretStore { message DeleteSecretRequest { string key = 1; - SecretStore store = 2; // Backend namespace (default keychain) + optional SecretStore store = 2; // Backend namespace (default keychain) } message ListSecretsRequest {} From 5f4c61ece3d5baeb07cee874b5888757f48fa81a Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:02:17 -0700 Subject: [PATCH 14/18] fix(daemon): move withEnv helper out of production sources Sonar still scored the colocated test helper under src/, and finalize could not re-analyze fork PRs to pick up exclusions. Relocate withEnv under tests/helpers (already coverage-excluded) and resolve fork PR numbers by head OID in finalize. Co-authored-by: Cursor --- .github/workflows/finalize.yml | 9 +++++++++ .../daemon/src/daemon/server/abbenay-service.test.ts | 2 +- .../daemon/src/daemon/server/consumer-auth.test.ts | 2 +- .../helpers/with-env.test.ts} | 2 +- .../server/test-env.ts => tests/helpers/with-env.ts} | 7 +++++-- sonar-project.properties | 10 ++++++---- 6 files changed, 23 insertions(+), 9 deletions(-) rename packages/daemon/{src/daemon/server/test-env.test.ts => tests/helpers/with-env.test.ts} (95%) rename packages/daemon/{src/daemon/server/test-env.ts => tests/helpers/with-env.ts} (73%) diff --git a/.github/workflows/finalize.yml b/.github/workflows/finalize.yml index 21bead22..e929b5a2 100644 --- a/.github/workflows/finalize.yml +++ b/.github/workflows/finalize.yml @@ -77,6 +77,15 @@ jobs: --jq '.[0].number // empty') fi + # Fork PR head SHAs are often missing from the commits/{sha}/pulls API + # and workflow_run.pull_requests. Match an open PR by head OID instead. + if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then + PR_NUMBER=$(gh pr list --repo "${REPO}" --state open --limit 100 \ + --json number,headRefOid \ + --jq ".[] | select(.headRefOid == \"${HEAD_SHA}\") | .number" \ + | head -n1) + fi + if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then echo "::error::Unable to resolve a trusted PR number for head SHA ${HEAD_SHA}" exit 1 diff --git a/packages/daemon/src/daemon/server/abbenay-service.test.ts b/packages/daemon/src/daemon/server/abbenay-service.test.ts index cf1ba891..98f70e37 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.test.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.test.ts @@ -121,7 +121,7 @@ import { authorizeInlinePolicy, DEFAULT_CONSUMER_AUTH_CONTEXT, } from './abbenay-service.js'; -import { withEnv } from './test-env.js'; +import { withEnv } from '../../../tests/helpers/with-env.js'; describe('configFileToProto', () => { it('converts an empty config', () => { diff --git a/packages/daemon/src/daemon/server/consumer-auth.test.ts b/packages/daemon/src/daemon/server/consumer-auth.test.ts index 2b56d9fd..05f25978 100644 --- a/packages/daemon/src/daemon/server/consumer-auth.test.ts +++ b/packages/daemon/src/daemon/server/consumer-auth.test.ts @@ -18,7 +18,7 @@ import { type ConsumerCapability, } from './consumer-auth.js'; import type { ConfigFile } from '../../core/config.js'; -import { withEnv } from './test-env.js'; +import { withEnv } from '../../../tests/helpers/with-env.js'; function mockGrpcCall(token?: string): { metadata: grpc.Metadata } { const metadata = new grpc.Metadata(); diff --git a/packages/daemon/src/daemon/server/test-env.test.ts b/packages/daemon/tests/helpers/with-env.test.ts similarity index 95% rename from packages/daemon/src/daemon/server/test-env.test.ts rename to packages/daemon/tests/helpers/with-env.test.ts index 0df14f9e..56b68034 100644 --- a/packages/daemon/src/daemon/server/test-env.test.ts +++ b/packages/daemon/tests/helpers/with-env.test.ts @@ -3,7 +3,7 @@ */ import { describe, it, expect } from 'vitest'; -import { withEnv } from './test-env.js'; +import { withEnv } from './with-env.js'; describe('withEnv', () => { it('restores a previously set env value after the callback', async () => { diff --git a/packages/daemon/src/daemon/server/test-env.ts b/packages/daemon/tests/helpers/with-env.ts similarity index 73% rename from packages/daemon/src/daemon/server/test-env.ts rename to packages/daemon/tests/helpers/with-env.ts index d6da8bdd..47d30d9e 100644 --- a/packages/daemon/src/daemon/server/test-env.ts +++ b/packages/daemon/tests/helpers/with-env.ts @@ -9,7 +9,10 @@ export async function withEnv( try { await fn(); } finally { - if (prev === undefined) delete process.env[key]; - else process.env[key] = prev; + if (prev === undefined) { + delete process.env[key]; + } else { + process.env[key] = prev; + } } } diff --git a/sonar-project.properties b/sonar-project.properties index c31b4794..58b7e2d8 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -13,8 +13,10 @@ sonar.organization=redhat-developer sonar.projectKey=redhat-developer_abbenay sonar.sources=packages/daemon/src/,packages/vscode/src/ sonar.tests=packages/daemon/src/,packages/daemon/tests/,packages/vscode/src/test/ -# Keep source/test sets disjoint: co-located *.test.ts (and test helpers like -# test-env.ts) live under source roots but must be classified only as tests. -sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/python/**,**/*.test.ts,**/test-env.ts -sonar.test.inclusions=**/*.test.ts,**/test-env.ts +# Keep source/test sets disjoint: co-located *.test.ts live under source roots +# but must be classified only as tests (not main sources). +sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/python/**,**/*.test.ts +sonar.test.inclusions=**/*.test.ts +# Test helpers under packages/*/tests must never count toward coverage gates. +sonar.coverage.exclusions=**/*.test.ts,**/tests/helpers/** sonar.verbose=false From 2b3b896ac0e7c77234e5bb58902b8e8205677211 Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:14:40 -0700 Subject: [PATCH 15/18] ci(sonar): sync finalize fork PR resolution with #118 Co-authored-by: Cursor --- .github/workflows/finalize.yml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/finalize.yml b/.github/workflows/finalize.yml index e929b5a2..83879901 100644 --- a/.github/workflows/finalize.yml +++ b/.github/workflows/finalize.yml @@ -64,6 +64,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} + HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} REPO: ${{ github.repository }} # Trusted GitHub payload — not PR-controlled artifact content PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }} @@ -78,12 +80,24 @@ jobs: fi # Fork PR head SHAs are often missing from the commits/{sha}/pulls API - # and workflow_run.pull_requests. Match an open PR by head OID instead. + # and workflow_run.pull_requests. Resolve via trusted head owner:branch, + # then require an exact head OID match (fail if 0 or >1). if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then - PR_NUMBER=$(gh pr list --repo "${REPO}" --state open --limit 100 \ - --json number,headRefOid \ - --jq ".[] | select(.headRefOid == \"${HEAD_SHA}\") | .number" \ - | head -n1) + if [[ -z "${HEAD_BRANCH}" || -z "${HEAD_REPOSITORY}" ]]; then + echo "::error::Missing workflow_run head_branch/head_repository for SHA ${HEAD_SHA}" + exit 1 + fi + HEAD_OWNER="${HEAD_REPOSITORY%%/*}" + MATCHES=$(gh api \ + -H "Accept: application/vnd.github+json" \ + "repos/${REPO}/pulls?state=open&head=${HEAD_OWNER}:${HEAD_BRANCH}" \ + --jq "[.[] | select(.head.sha == \"${HEAD_SHA}\") | .number]") + MATCH_COUNT=$(jq 'length' <<< "${MATCHES}") + if [[ "${MATCH_COUNT}" -ne 1 ]]; then + echo "::error::Expected exactly one open PR for ${HEAD_OWNER}:${HEAD_BRANCH}@${HEAD_SHA}, found ${MATCH_COUNT}: ${MATCHES}" + exit 1 + fi + PR_NUMBER=$(jq -r '.[0]' <<< "${MATCHES}") fi if [[ ! "${PR_NUMBER}" =~ ^[0-9]+$ ]]; then From 05fbef843f5ed07fb24b0f8eb25bcad84277abcf Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:27:07 -0700 Subject: [PATCH 16/18] ci(sonar): exclude generated vscode proto stubs from analysis Optional store fields regenerated packages/vscode/src/proto, and Sonar counted ~1.6k uncovered generated lines against new-code coverage. Co-authored-by: Cursor --- sonar-project.properties | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 58b7e2d8..14f07bb1 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -15,8 +15,9 @@ sonar.sources=packages/daemon/src/,packages/vscode/src/ sonar.tests=packages/daemon/src/,packages/daemon/tests/,packages/vscode/src/test/ # Keep source/test sets disjoint: co-located *.test.ts live under source roots # but must be classified only as tests (not main sources). -sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/python/**,**/*.test.ts +# Generated proto stubs under vscode mirror packages/proto-ts (already excluded). +sonar.exclusions=**/node_modules/**,**/dist/**,**/coverage/**,packages/proto-ts/**,packages/vscode/src/proto/**,packages/python/**,**/*.test.ts sonar.test.inclusions=**/*.test.ts -# Test helpers under packages/*/tests must never count toward coverage gates. -sonar.coverage.exclusions=**/*.test.ts,**/tests/helpers/** +# Test helpers and generated stubs must never count toward coverage gates. +sonar.coverage.exclusions=**/*.test.ts,**/tests/helpers/**,packages/vscode/src/proto/** sonar.verbose=false From 77d58758be2ba2f779676063d26f72418ccaf7a7 Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:30:57 -0700 Subject: [PATCH 17/18] test(daemon): assert keytar load-failure cache without console.warn spy Parallel CI files can clobber a shared console.warn spy, making the short-circuit test flake. Assert the sticky loadError instead. Co-authored-by: Cursor --- packages/daemon/src/daemon/secrets/keychain.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/daemon/src/daemon/secrets/keychain.test.ts b/packages/daemon/src/daemon/secrets/keychain.test.ts index 92064a63..c9b203d1 100644 --- a/packages/daemon/src/daemon/secrets/keychain.test.ts +++ b/packages/daemon/src/daemon/secrets/keychain.test.ts @@ -272,10 +272,17 @@ describe('KeychainSecretStore', () => { it('short-circuits further loads after keytar import failure', async () => { const store = await loadStoreWithFailingKeytarImport(); + const internals = store as unknown as KeychainInternals; await expect(store.get('ONE')).resolves.toBeNull(); + expect(internals.keytar).toBeNull(); + expect(internals.loadError).toMatch(/keytar missing/); + const cachedError = internals.loadError; + await expect(store.get('TWO')).resolves.toBeNull(); - expect(warnSpy).toHaveBeenCalledTimes(1); + // Failure is sticky — no second import attempt / error rewrite. + expect(internals.loadError).toBe(cachedError); + expect(internals.keytar).toBeNull(); }); it('loads keytar from named export when default export lacks getPassword', async () => { From 7edbbe328992f7d7b986f913383d0721483a03bf Mon Sep 17 00:00:00 2001 From: bthornto Date: Thu, 13 Aug 2026 06:36:42 -0700 Subject: [PATCH 18/18] fix(daemon): reject memory secret_store without SecretStoreRegistry Clients could request memory while a plain store silently persisted to keychain and audited as memory. Require a namespaced registry for memory on gRPC/HTTP secrets and configure paths. Co-authored-by: Cursor --- .../src/daemon/secrets/registry.test.ts | 19 ++++++++ .../daemon/src/daemon/secrets/registry.ts | 20 +++++++++ .../src/daemon/server/abbenay-service.test.ts | 33 ++++++++++++++ .../src/daemon/server/abbenay-service.ts | 44 ++++++++++++++++++- packages/daemon/src/daemon/web/server.ts | 30 ++++++++++++- 5 files changed, 143 insertions(+), 3 deletions(-) diff --git a/packages/daemon/src/daemon/secrets/registry.test.ts b/packages/daemon/src/daemon/secrets/registry.test.ts index dbd21e17..57f329eb 100644 --- a/packages/daemon/src/daemon/secrets/registry.test.ts +++ b/packages/daemon/src/daemon/secrets/registry.test.ts @@ -7,6 +7,7 @@ import { MemorySecretStore } from '../../core/secrets.js'; import { SecretStoreRegistry, parseSecretStoreChoice, + requireNamespacedMemory, secretBackendToProto, } from './registry.js'; @@ -120,6 +121,24 @@ describe('parseSecretStoreChoice', () => { }); }); +describe('requireNamespacedMemory', () => { + it('allows memory when a registry is present', async () => { + const { MemorySecretStore } = await import('../../core/secrets.js'); + const registry = new SecretStoreRegistry(new MemorySecretStore(), new MemorySecretStore()); + expect(requireNamespacedMemory(registry, 'memory')).toEqual({ ok: true }); + expect(requireNamespacedMemory(registry, 'keychain')).toEqual({ ok: true }); + }); + + it('rejects memory when only a plain secret store is available', () => { + const result = requireNamespacedMemory(null, 'memory'); + expect(result.ok).toBe(false); + if (!result.ok) { + expect(result.error).toMatch(/memory|SecretStoreRegistry/i); + } + expect(requireNamespacedMemory(null, 'keychain')).toEqual({ ok: true }); + }); +}); + describe('secretBackendToProto', () => { it('maps backends to proto enum numbers', () => { expect(secretBackendToProto('keychain')).toBe(1); diff --git a/packages/daemon/src/daemon/secrets/registry.ts b/packages/daemon/src/daemon/secrets/registry.ts index f5279277..050e5923 100644 --- a/packages/daemon/src/daemon/secrets/registry.ts +++ b/packages/daemon/src/daemon/secrets/registry.ts @@ -115,6 +115,26 @@ export function isSecretStoreRegistry(store: SecretStore): store is SecretStoreR return store instanceof SecretStoreRegistry; } +/** + * Memory is only meaningful with {@link SecretStoreRegistry}. Reject it when the + * daemon is running a plain SecretStore so clients cannot request memory while + * the write silently lands in keychain (or another non-ephemeral backend). + */ +export function requireNamespacedMemory( + registry: SecretStoreRegistry | null, + backend: string, +): { ok: true } | { ok: false; error: string } { + if (backend === 'memory' && !registry) { + return { + ok: false, + error: + 'secret_store=memory requires a namespaced secret store (memory + keychain); ' + + 'this daemon is not running with SecretStoreRegistry', + }; + } + return { ok: true }; +} + /** * Parse SetSecret / ConfigureProvider `store` / `secret_store` field. * Unspecified / omitted / keychain → keychain (default for writes). diff --git a/packages/daemon/src/daemon/server/abbenay-service.test.ts b/packages/daemon/src/daemon/server/abbenay-service.test.ts index 98f70e37..a936b67c 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.test.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.test.ts @@ -1072,6 +1072,39 @@ describe('createAbbenayService handlers', () => { .toBe(grpc.status.INVALID_ARGUMENT); }); + it('Secrets RPCs reject memory when secret store is not a registry', async () => { + const set = vi.fn().mockResolvedValue(undefined); + const state = createMockState({ + secretStore: { + get: vi.fn().mockResolvedValue(null), + set, + delete: vi.fn().mockResolvedValue(true), + has: vi.fn().mockResolvedValue(false), + }, + }); + const service = createServiceHandlers(state); + + for (const method of ['GetSecret', 'SetSecret', 'DeleteSecret'] as const) { + const req = + method === 'SetSecret' + ? { key: 'K', value: 'v', store: 'SECRET_STORE_MEMORY' } + : { key: 'K', store: 'SECRET_STORE_MEMORY' }; + const { error } = await invokeUnary(service[method], req); + expect(error?.code, method).toBe(grpc.status.INVALID_ARGUMENT); + expect(error?.message, method).toMatch(/memory|SecretStoreRegistry/i); + } + expect(set).not.toHaveBeenCalled(); + + const configure = await invokeUnary(service.ConfigureProvider, { + provider_id: 'plain-mem', + engine: 'mock', + api_key: 'x', + secret_store: 'SECRET_STORE_MEMORY', + }); + expect(configure.error?.code).toBe(grpc.status.INVALID_ARGUMENT); + expect(set).not.toHaveBeenCalled(); + }); + it('ListSecrets returns empty has_value rows when registry backends lack the key', async () => { mockGetEngine.mockImplementation((id: string) => ( id === 'mock' ? { id: 'mock', requiresKey: false, defaultEnvVar: 'MOCK_API_KEY' } diff --git a/packages/daemon/src/daemon/server/abbenay-service.ts b/packages/daemon/src/daemon/server/abbenay-service.ts index 77746d5d..b94a0d84 100644 --- a/packages/daemon/src/daemon/server/abbenay-service.ts +++ b/packages/daemon/src/daemon/server/abbenay-service.ts @@ -29,6 +29,7 @@ import { auditSecretChange } from '../../core/secrets.js'; import { isSecretStoreRegistry, parseSecretStoreChoice, + requireNamespacedMemory, secretBackendToProto, } from '../secrets/registry.js'; import { @@ -814,6 +815,14 @@ export function createAbbenayService( } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, parsed.backend); + if (!memoryOk.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: memoryOk.error, + }); + return; + } const read = registry ? registry.getFrom(parsed.backend, key) : state.secretStore.get(key); @@ -851,6 +860,14 @@ export function createAbbenayService( } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, parsed.backend); + if (!memoryOk.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: memoryOk.error, + }); + return; + } const write = registry ? registry.setIn(parsed.backend, key, value) : state.secretStore.set(key, value); @@ -889,6 +906,14 @@ export function createAbbenayService( } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, parsed.backend); + if (!memoryOk.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: memoryOk.error, + }); + return; + } const remove = registry ? registry.deleteFrom(parsed.backend, key) : state.secretStore.delete(key); @@ -1852,6 +1877,14 @@ export function createAbbenayService( // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: memoryOk.error, + }); + return; + } if (registry) { await registry.setIn(storeChoice.backend, secretName, apiKey); } else { @@ -1891,6 +1924,14 @@ export function createAbbenayService( delete config.providers[providerId].api_key_keychain_name; } else { const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + callback({ + code: grpc.status.INVALID_ARGUMENT, + message: memoryOk.error, + }); + return; + } const exists = registry ? await registry.hasIn(storeChoice.backend, secretNameRef) : await state.secretStore.has(secretNameRef); @@ -2007,7 +2048,8 @@ export function createAbbenayService( const backend = providerCfg.secret_store === 'memory' ? 'memory' : 'keychain'; if (registry) { await registry.deleteFrom(backend, secretName); - } else { + } else if (backend === 'keychain') { + // Memory without a registry was never a valid write target. await state.secretStore.delete(secretName); } auditSecretChange({ key: secretName, op: 'delete', source: 'grpc-configure' }); diff --git a/packages/daemon/src/daemon/web/server.ts b/packages/daemon/src/daemon/web/server.ts index a86b2ae0..2e978b0c 100644 --- a/packages/daemon/src/daemon/web/server.ts +++ b/packages/daemon/src/daemon/web/server.ts @@ -18,7 +18,7 @@ import { fileURLToPath } from 'node:url'; import { getDefaultSocketPath } from '../transport.js'; import { loadConfig, saveConfig, loadWorkspaceConfig, saveWorkspaceConfig, getUserConfigPath, getWorkspaceConfigPath, providerSecretName, isProviderOwnedSecretName, type ConfigFile, type ProviderConfig } from '../../core/config.js'; import { auditSecretChange } from '../../core/secrets.js'; -import { isSecretStoreRegistry, parseSecretStoreChoice } from '../secrets/registry.js'; +import { isSecretStoreRegistry, parseSecretStoreChoice, requireNamespacedMemory } from '../secrets/registry.js'; import { auditProviderEndpointChange, auditProviderEndpointConfigDiff, @@ -1072,6 +1072,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): return; } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + sendBadRequest(res, memoryOk.error); + return; + } if (registry) { await registry.setIn(storeChoice.backend, key, parsed.data.value); } else { @@ -1108,6 +1113,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): return; } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + sendBadRequest(res, memoryOk.error); + return; + } if (registry) { await registry.setIn(storeChoice.backend, parsed.data.key, parsed.data.value); } else { @@ -1146,6 +1156,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): return; } const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + sendBadRequest(res, memoryOk.error); + return; + } if (registry) { await registry.deleteFrom(storeChoice.backend, req.params.key); } else { @@ -1465,6 +1480,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): // Explicit name, or legacy invent from provider id (1:1 shortcut). const secretName = secretNameRef || `${providerId.toUpperCase()}_API_KEY`; const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeChoice.backend); + if (!memoryOk.ok) { + sendBadRequest(res, memoryOk.error); + return; + } if (registry) { await registry.setIn(storeChoice.backend, secretName, apiKey); } else { @@ -1486,6 +1506,11 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): delete config.providers[providerId].api_key_keychain_name; } else if (storeRaw === 'memory' || storeRaw === 'keychain') { const registry = isSecretStoreRegistry(state.secretStore) ? state.secretStore : null; + const memoryOk = requireNamespacedMemory(registry, storeRaw); + if (!memoryOk.ok) { + sendBadRequest(res, memoryOk.error); + return; + } const exists = registry ? await registry.hasIn(storeRaw, secretNameRef) : await state.secretStore.has(secretNameRef); @@ -1603,7 +1628,8 @@ export function createWebApp(state: DaemonState, options?: WebSecurityOptions): const backend = providerCfg.secret_store === 'memory' ? 'memory' : 'keychain'; if (registry) { await registry.deleteFrom(backend, secretName); - } else { + } else if (backend === 'keychain') { + // Memory without a registry was never a valid write target. await state.secretStore.delete(secretName); } auditSecretChange({ key: secretName, op: 'delete', source: 'http-configure' });